快取、降級和限流是開發高併發系統的三把利器。
一般開發高併發系統常見的限流有:限制總併發數、限制瞬時併發數、限制時間視窗內的平均速率、限制遠端介面的呼叫速率、限制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....