參考:
- https://i4t.com/19399.html
- https://github.com/apache/apisix/issues/9193
- https://github.com/apache/apisix/issues/9830
- https://apisix.apache.org/docs/apisix/plugins/limit-conn/
- https://blog.frankel.ch/different-rate-limits-apisix/
在 Apache APISIX 中,限流共提供了三種方式,下面說一下
- limit-req 外掛使用漏桶演算法限制單個客戶端對服務的請求速率
- limit-conn 外掛用於限制客戶端對單個服務的併發請求數。當客戶端對路由的併發請求數達到限制時,可以返回自定義的狀態碼和響應資訊。
- limit-count 件使用固定時間視窗演算法,主要用於限制單個客戶端在指定的時間範圍內對服務的總請求數,並且會在 HTTP 響應頭中返回剩餘可以請求的個數。該外掛原理與 GitHub API 的速率限制類似
請求的限制引數
key_type
- ["var", "var_combination"]
- var就是一個變更,不需要加$字首
- var_combination是一組變更的組合,如key為:
$http_sub $http_x_forwarded_for
key
- ["remote_addr", "server_addr", "http_x_real_ip", "http_x_forwarded_for", "consumer_name"]
- 如果限流標識是在請求頭裡,如請求頭是sub,那麼key可以配置為
http_sub
var和var_combination型別對應的配置
- var_combination
"plugins": {
"limit-req": {
"burst": 10,
"key": "$consumer_name $remote_addr",
"key_type": "var_combination",
"rate": 2,
"rejected_code": 502
}
}
- var
"plugins": {
"limit-req": {
"burst": 2,
"key": "remote_addr",
"key_type": "var",
"rate": 3,
"rejected_code": 502
},
"limit-count": {
"allow_degradation": false,
"count": 5,
"key": "http_sub",
"key_type": "var",
"policy": "local",
"rejected_code": 429,
"rejected_msg": "請求太多了",
"show_limit_quota_header": true,
"time_window": 60
}
}
配置redis
- redis中key的組成
plugin-limit-countroute540160115966214871
:2389086815
:347c9e9e-076c-45e3-be74-c482fffcc6e5
- plugin-外掛名route路由id::limit裡的key值
- 單節點
"plugins": {
"limit-count": {
"count": 2,
"time_window": 60,
"rejected_code": 503,
"key": "remote_addr",
"policy": "redis",
"redis_host": "127.0.0.1",
"redis_port": 6379,
"redis_password": "password",
"redis_database": 1,
"redis_timeout": 1001
}
}
- 叢集模式
"plugins": {
"limit-count": {
"count": 2,
"time_window": 60,
"rejected_code": 503,
"key": "remote_addr",
"policy": "redis-cluster",
"redis_cluster_nodes": [
"127.0.0.1:5000",
"127.0.0.1:5001"
]
}
}
外掛的解釋
- limit-req
rate:
含義:每秒允許的請求數量。
示例:rate: 3 表示每個客戶端(根據配置的 key)每秒最多可以傳送 3 個請求。
burst:
含義:突發請求的最大數量。
示例:burst: 2 表示在短時間內,客戶端可以突發額外的 2 個請求,即在正常速率為 3 的情況下,可以在某些時刻達到 5 個請求(3 + 2)。
- limit-count
count:
含義:在指定的時間視窗內允許的最大請求次數。
示例:count: 2 表示每個客戶端(根據配置的 key)在 time_window 指定的時間段內最多可以傳送 2 個請求。
time_window:
含義:時間視窗的長度,以秒為單位。
示例:time_window: 60 表示時間視窗為 60 秒。在這 60 秒內,客戶端最多可以傳送 2 個請求。
對redis-key的解釋
在 APISIX 中使用 limit-count
外掛時,生成的 Redis 鍵通常包含多個部分,這些部分用來標識具體的限流策略和相關資訊。你提到的鍵示例是:
plugin-limit-countroute540160115966214871:2389086815:347c9e9e-076c-45e3-be74-c482fffcc6e5
我們可以將這個鍵分解為幾個部分以便理解:
鍵的組成部分
-
plugin-limit-count
:- 這是固定的字首,表示該鍵是由
limit-count
外掛生成的。
- 這是固定的字首,表示該鍵是由
-
route540160115966214871
:- 這一部分通常表示與特定路由(route)相關的資訊。
540160115966214871
是路由的唯一識別符號(ID),它對應於 APISIX 中配置的某個具體路由。這使得限流策略能夠應用於特定的路由。
-
2389086815
:- 這一部分通常表示限流的維度或時間視窗的識別符號,可能是一個時間戳或者是請求計數的某一部分。
- 具體含義取決於你的限流配置,比如它可能是用於區分不同時間段內的請求計數。
-
347c9e9e-076c-45e3-be74-c482fffcc6e5
:- 這一部分一般是使用者識別符號(如客戶端 ID 或者其他唯一識別符號),用於在限流策略中區分不同的使用者或客戶端。
- 這種設計允許對不同的使用者或客戶端分別進行限流控制。
總結
整個鍵的結構是為了確保每個限流例項都是唯一的,並且能夠精確地與特定的路由和使用者關聯。透過這樣的設計,APISIX 可以高效地管理和應用限流策略,以保障系統的穩定性和效能。
redis-count和redis-req的使用場景
漏桶演算法(Leaky Bucket)和固定視窗限流(Fixed Window)是兩種常見的限流策略,它們適用於不同的使用場景。以下是這兩種限流策略的特點及其適用場景:
漏桶演算法(Leaky Bucket)
特點:
- 平滑輸出:漏桶演算法允許請求以固定速率被處理,儘管輸入請求可以是不規則的。
- 水位限制:桶內有一個容量限制,當達到上限時,多餘的請求將被丟棄或拒絕。
- 時間延遲:由於請求是以固定速率“漏出”的,因此可能會引入一定的延遲。
使用場景:
- 網路流量控制:適合需要平穩流量輸出的場景,如影片流、音訊流等。
- API呼叫限制:在需要防止
突發流量
對後端服務造成影響的情況下,可以使用漏桶演算法來平衡請求量。 - 實時資料處理:適合處理實時資料流的場景,例如訊息佇列中的訊息消費。
- 使用者行為限制:例如限制使用者在一定時間內的操作次數,以防止刷票、刷單等行為。
固定視窗限流(Fixed Window)
特點:
- 時間視窗:將時間劃分為固定長度的視窗,在每個視窗內允許一定數量的請求。
- 突發性:在視窗開始時,所有請求都可以瞬間進入,但在視窗結束前不會再接受新的請求,直到下一個視窗開始。
- 簡單易實現:相對其他限流演算法,固定視窗的實現較為簡單。
使用場景:
- 日常訪問控制:適合控制使用者在特定時間段內的訪問頻率,比如限制使用者每天的登入次數。
- API介面呼叫:用於限制外部系統對內部API的呼叫頻率,確保系統穩定性。
- 短時間高併發場景:如電商促銷活動期間,可以快速處理大量請求,但需要限制每個使用者的請求頻率。
- 統計分析:適合進行簡單的統計計算,如記錄某一時間視窗內的訪問量。
總結
- 漏桶演算法更適合需要平滑流量控制的場景,能夠有效防止突發流量造成的系統壓力。
- 固定視窗限流則適合短時間內的請求控制,簡單易用,適合一些對時間視窗要求不嚴格的應用。
根據具體的業務需求和系統架構,可以選擇合適的限流策略來保障系統的穩定性和可用性。