SpringCloudGateway限流原理與實踐

2021-10-08 13:21:09 字數 2559 閱讀 7640

快取、降級和限流是開發高併發系統的三把利器。

一般開發高併發系統常見的限流有:限制總併發數、限制瞬時併發數、限制時間視窗內的平均速率、限制遠端介面的呼叫速率、限制mq的消費速率,或根據網路連線數、網路流量、cpu或記憶體負載等來限流。

本文主要就分布式限流方法,對spring cloud gateway的限流原理進行分析。

分布式限流最關鍵的是要將限流服務做成原子化,常見的限流演算法有:令牌桶、漏桶等,spring cloud gateway使用redis+lua技術實現高併發和高效能的限流方案。

令牌桶演算法是乙個存放固定容量令牌的桶,按照固定速率往桶裡新增令牌。

令牌桶演算法的描述如下:

假如使用者配置的平均速率為r,則每隔1/r秒乙個令牌被加入到桶中;

假設桶最多可以存b個令牌。如果令牌到達時令牌桶已經滿了,那麼這個令牌會被丟棄;

當乙個n個位元組大小的資料報到達,將從桶中刪除n個令牌,接著資料報被傳送到網路上;

如果令牌桶中少於n個令牌,那麼不會刪除令牌,並且認為這個資料報在流量限制之外;

演算法允許最長b個位元組的突發,但從長期執行結果看,資料報的速率被限制成常量r。對於在流量限制外的資料報可以以不同的方式處理:

漏桶作為計量工具(the leaky bucket algorithm as a meter)時,可以用於流量整形(traffic shaping)和流量控制(traffic policing),漏桶演算法的描述如下:

乙個固定容量的漏桶,按照常量固定速率流出水滴;

如果桶是空的,則不需流出水滴;

可以以任意速率流入水滴到漏桶;

如果流入水滴超出了桶的容量,則流入的水滴溢位了(被丟棄),而漏桶容量是不變的。

spring cloud gateway 預設實現 redis限流,如果擴充套件只需要實現ratelimter介面即可,同時也可以通過自定義keyresolver來指定限流的key,比如我們需要根據使用者、ip、uri來做限流等等,通過exchange物件可以獲取到請求資訊,比如:

使用者限流

@bean

public keyresolver ipkeyresolver()

springcloudgateway預設提供的redisratelimter 的核心邏輯為判斷是否取到令牌的實現,通過呼叫 meta-inf/scripts/request_rate_limiter.lua 指令碼實現基於令牌桶演算法限流,**如下 :

1: local tokens_key = keys1

2: local timestamp_key = keys2

3:4: local rate = tonumber(ar**1)

5: local capacity = tonumber(ar**2)

6: local now = tonumber(ar**3)

7: local requested = tonumber(ar**4)

8:9: local fill_time = capacity/rate

10: local ttl = math.floor(fill_time*2)

11:12: local last_tokens = tonumber(redis.call(「get」, tokens_key))

13: if last_tokens == nil then

14: last_tokens = capacity

15: end

16:17: local last_refreshed = tonumber(redis.call(「get」, timestamp_key))

18: if last_refreshed == nil then

19: last_refreshed = 0

20: end

21:22: local delta = math.max(0, now-last_refreshed)

23: local filled_tokens = math.min(capacity, last_tokens+(delta*rate))

24: local allowed = filled_tokens >= requested

25: local new_tokens = filled_tokens

26: local allowed_num = 0

27: if allowed then

28: new_tokens = filled_tokens - requested

29: allowed_num = 1

30: end

31:32: redis.call(「setex」, tokens_key, ttl, new_tokens)

33: redis.call(「setex」, timestamp_key, ttl, now)

34:35: return

mySql與oracle分頁技術原理與實現

如果我們是通過jdbc的方式訪問資料庫,那麼就有必要根據資料庫型別採取不同的sql分頁語句,對於mysql資料庫,我們可以採用limit語句進行分頁,對於oracle資料庫,我們可以採用rownum的方式進行分頁.1 mysql的limit m,n語句 limit後的兩個引數中,引數m是起始下標,它...

Bumblebee之負載 限流和故障處理實踐

bumblebee作為標準http 1.1應用協議的閘道器,它能作為任何基於http 1.1構建webapi服務的前置閘道器。以下通過示例講述如何用bumblebee來製作乙個asp.net core webapi的前置閘道器,並演示閘道器的一些基礎功能如 負載,限流和故障遷移等相關基礎功能。bum...

K means和ISODATA 演算法 原理與實現

k means演算法 原理 對於給定的樣本集,按照樣本之間的距離大小,將樣本集劃分為k個簇。讓簇內的點盡量緊密的連在一起,而讓簇間的距離盡量的大。如果用資料表示式表示,假設簇劃分為 c1,c2,ck 則我們的目標是最小化平方誤差e 其中 i是簇ci的均值向量,有時也稱為質心,表示式為 一般步驟 1....