RFC 看到的 Rate Limit

因緣巧合,剛好有看到 Rate Limit 討論,然後看到 header 定義覺得哪裡怪怪的,然後就認真查了一下,意外發現 RFC 有定義相關的 header。

開始來看 RFC

首先 HTTP 狀態碼 429 Too Many Requests 定義在 RFC 6585 這份文件裡,重點如下:

  1. HTTP 回應的 representations(先當這個是 body)應該要說明限流條件,但沒有定義如何說明。
  2. 可以加上 Retry-After 的 header,讓客戶端知道還需要等多久才能繼續呼叫(下個段落會說明詳細)。
  3. 未定義識別使用者的方法,或是限流的演算法等,這些應該可以因需求而調整。
  4. HTTP 429 狀態碼禁止快取。

其中 Retry-After 的 header 定義在 RFC 9110 這份文件裡,重點如下:

  1. 指示客戶端發出下一個請求前,應該要等待多長的時間。
  2. 當搭配 HTTP 503 Service Unavailable 狀態碼的時候,Retry-After 代表著服務預計還有多長的不可用時間。
  3. 當搭配 HTTP 3xx 系列狀態碼,Retry-After 代表指示客戶端再發出轉導請求前,需要等待的最短時間。
  4. Retry-After 可以是 HTTP-date,也可以是一個正整數十進制的秒數,例如 120 指的是兩分鐘。

以上都是正式釋出的 RFC 文件。再來可以看還在草案中的 RFC 文件

這個文件是由 Building Blocks for HTTP APIs 這個工作小組所定義的。HTTP 本身是很靈活的協議,能夠自由的擴充客製化的功能。而這個工作小組的任務是,以 HTTP 作為 API 使用的情境,將 HTTP 協議加以擴充與標準化,例如今天所提的限流情境。

這份 RFC 被提出的目的是把限流相關的名詞標準化,達到更好的操作性;另外客戶端也可以依此資訊來避免踩到 4xx 或 5xx 的回應;限流相關的資訊由回應即可知道,因此有機會減化文件撰寫的難度。但其他與業務邏輯或是服務本身性質相關的資訊則不在此 RFC 文件範圍內,例如授權、限流範圍或限流策略等。

裡面有定義四個 header 如下:

Header 說明
RateLimit-Limit 在時間區間內,客戶端請求的限額
RateLimit-Remaining 在時間區間內還剩下多少配額
RateLimit-Reset 要多久才會重設配額
RateLimit-Policy 配額策略,有點複雜,懶得思考了

文件有提到,Server 可以 加上這些 header,跟狀態碼是分開考慮的兩件事。只是用在 3xx 系列的時候要小心,因為如果 RateLimit-Remaining 太低的時候,有可能會阻止客戶端發出請求。例如,考慮下面的回應:

HTTP/1.1 301 Moved Permanently
Location: /foo/123
RateLimit-Remaining: 0
RateLimit-Limit: 10
RateLimit-Reset: 10

客戶端可能會依此資訊,判斷 10 秒後再發出請求,因為 RateLimit-Remaining 已經見底了,所以應該需要等待 RateLimit-Reset 的秒數後,才能再重新發出請求。

注意:Draft 6 的過期時間是 2023/6/25,再一個禮拜就到了,不知道接下來會更新還是定版。看過去這個小組所提出的東西是過期的居多,感到危險。