API rate limiting 在很多服務的 Open API 裡都可以看到,像是 facebookgithubtwitter…等等,其目的是要限制每個 consumer 的使用量,進而避免 server over loading

根據 twitter 官方的說明

Rate limiting of the standard API is primarily on a per-user basis — or more accurately described, per user access token. If a method allows for 15 requests per rate limit window, then it allows 15 requests per window per access token.

常見的 pattern 就是,每個 access token 在每段時間內有一定的使用量(usage),當該 access token 超出使用量後,發出的 request 都會得到 429 Too Many Requests 的回應

Implementation

假設今天我們要設計一個 每個 token 每分鐘最多 100 次 request 的 rate limiter,如標題所寫,可以利用 Redis 來達成

def limit_api_call(access_token: str) -> bool:
    current_minute = datetime.datetime.now().minute
    key = f'{access_token}:{current_minute}'

    usage, _ = redis.pipeline().incr(key).expire(key, 60).execute()

    if usage <= 100:
        return True
    else:
        return False

概念上大概是這樣

  1. counter key 的 pattern 設定為 {access_token}:{current_minute}
  2. MULTI/EXECINCREXPIRE 包在一起,以確保兩個指令都會執行
  3. 判斷用量決定是否放行

如果你想以 IP 或是其他東西做為限制的依據,只要將 key 換掉就好

References