go-zero 如何扛住流量衝擊(一)
不管是在單體服務中還是在微服務中,開發者為前端提供的 API 介面都是有訪問上限的,當訪問頻率或者併發量超過其承受範圍時候,我們就必須考慮限流來保證介面的可用性或者降級可用性。即介面也需要安裝上保險絲,以防止非預期的請求對系統壓力過大而引起的系統癱瘓。
go-zero
整合了開箱即用的 限流器 。其中內建了兩種限流器,也對應兩類使用場景:
種類 | 原理 | 場景 |
---|---|---|
periodlimit |
單位時間限制訪問次數 | 需要強行限制資料的傳輸速率 |
tokenlimit |
令牌桶限流 | 限制資料的平均傳輸速率,同時允許某種程度的突發傳輸 |
本文就來介紹一下 periodlimit
。
使用
const (
seconds = 1
total = 100
quota = 5
)
// New limiter
l := NewPeriodLimit(seconds, quota, redis.NewRedis(s.Addr(), redis.NodeType), "periodlimit")
// take source
code, err := l.Take("first")
if err != nil {
logx.Error(err)
return true
}
// switch val => process request
switch code {
case limit.OverQuota:
logx.Errorf("OverQuota key: %v", key)
return false
case limit.Allowed:
logx.Infof("AllowedQuota key: %v", key)
return true
case limit.HitQuota:
logx.Errorf("HitQuota key: %v", key)
// todo: maybe we need to let users know they hit the quota
return false
default:
logx.Errorf("DefaultQuota key: %v", key)
// unknown response, we just let the sms go
return true
}
periodlimit
go-zero
採取 滑動視窗 計數的方式,計算一段時間內對同一個資源的訪問次數,如果超過指定的 limit
,則拒絕訪問。當然如果你是在一段時間內訪問不同的資源,每一個資源訪問量都不超過 limit
,此種情況是允許大量請求進來的。
而在一個分散式系統中,存在多個微服務提供服務。所以當瞬間的流量同時訪問同一個資源,如何讓計數器在分散式系統中正常計數? 同時在計算資源訪問時,可能會涉及多個計算,如何保證計算的原子性?
-
go-zero
藉助redis
的incrby
做資源訪問計數 - 採用
lua script
做整個視窗計算,保證計算的原子性
下面來看看 lua script
控制的幾個關鍵屬性:
argument | mean |
---|---|
key[1] | 訪問資源的標示 |
ARGV[1] | limit => 請求總數,超過則限速。可設定為 QPS |
ARGV[2] | window 大小 => 滑動視窗,用 ttl 模擬出滑動的效果 |
-- to be compatible with aliyun redis,
-- we cannot use `local key = KEYS[1]` to reuse thekey
local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
-- incrbt key 1 => key visis++
local current = redis.call("INCRBY", KEYS[1], 1)
-- 如果是第一次訪問,設定過期時間 => TTL = window size
-- 因為是隻限制一段時間的訪問次數
if current == 1 then
redis.call("expire", KEYS[1], window)
return 1
elseif current < limit then
return 1
elseif current == limit then
return 2
else
return 0
end
至於上述的 return code
,返回給呼叫方。由呼叫方來決定請求後續的操作:
return code | tag | call code | mean |
---|---|---|---|
0 | OverQuota | 3 | over limit |
1 | Allowed | 1 | in limit |
2 | HitQuota | 2 | hit limit |
下面這張圖描述了請求進入的過程,以及請求觸發 limit
時後續發生的情況:
後續處理
如果在服務某個時間點,請求大批量打進來,periodlimit
短期時間內達到 limit
閾值,而且設定的時間範圍還遠遠沒有到達。後續請求的處理就成為問題。
periodlimit
中並沒有處理,而是返回 code
。把後續請求的處理交給了開發者自己處理。
- 如果不做處理,那就是簡單的將請求拒絕
- 如果需要處理這些請求,開發者可以藉助
mq
將請求緩衝,減緩請求的壓力 - 採用
tokenlimit
,允許暫時的流量衝擊
所以下一篇我們就來聊聊 tokenlimit
總結
go-zero
中的 periodlimit
限流方案是基於 redis
計數器,通過呼叫 redis lua script
,保證計數過程的原子性,同時保證在分散式的情況下計數是正常的。
但是這種方案也存在缺點,因為它要記錄時間視窗內的所有行為記錄,如果這個量特別大的時候,記憶體消耗會變得非常嚴重。
參考
如果覺得文章不錯,歡迎 github 點個 star ? 。同時歡迎大家使用 go-zero
,https://github.com/tal-tech/go-zero
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- go-zero 如何扛住流量衝擊(二)Go
- 如何扛住遊戲流量高峰?Evil Dead 主創這樣說遊戲
- 特殊時期,釘釘如何透過單元化扛住流量高峰?
- 扛住阿里雙十一高併發流量,Sentinel是怎麼做到的?阿里
- 千萬級流量衝擊下,如何保證極致效能
- OceanBase X 成都有惠 | 扛住資料流量洪峰,找對 CP 是關鍵!
- CIO要頂住詞彙爆炸的衝擊(轉)
- 從步履蹣跚到舉重若輕,阿里基礎架構如何扛住全球最猛的流量洪峰?阿里架構
- “雙十一、二” 業務高峰如何扛住?韻達快遞選擇 TDengine
- 阿里P8面試官:如何設計一個扛住千萬級併發的架構?阿里面試架構
- 面試官:十問泛型,你能扛住嗎?面試泛型
- 淺談時序資料庫核心:如何用單機扛住億級資料寫入資料庫
- 阿里P8面試官:如何設計一個扛住千萬級併發的架構(超級詳細)-續阿里面試架構
- 如何應對AI帶來的衝擊AI
- 為什麼阿里巴巴這一次能扛得起 11 億的流量?阿里
- 網站被劫持攻擊以及流量攻擊如何解決網站
- 如何防禦惡意流量攻擊(CC、DDoS)?
- App 被刷影片流量如何防禦,DDoS攻擊一招解決APP
- GitHub 標星 11000+,阿里開源的微服務元件如何連續 10 年扛住雙十一大促?Github阿里微服務元件
- 大促活動如何抵禦大流量 DDoS 攻擊?
- CDN流量放大攻擊思路
- 疫情衝擊海外遊戲業:遊戲平臺流量劇增,一大波展會及線下活動取消遊戲
- 緩衝區溢位攻擊
- 超級休閒不是一個階段,而是一種文化衝擊
- 貝泰妮衝擊IPO:功能性護膚品生意如何?
- 全球晶片供應面臨衝擊晶片
- Go 對 Python 產生的衝擊GoPython
- 衝擊IPO,羅胖畫了一張終身教育大餅
- go-zero效率工具一覽圖Go
- go-zero 效率工具一覽圖Go
- go-zero之支付服務一Go
- 小米AIoT“第一”的紅旗能扛多久?AI
- 我是如何用go-zero 實現一箇中臺系統的Go
- 5種限流演算法,7種限流方式,擋住突發流量?演算法
- 流量劫持攻擊之鏈路劫持剖析
- Atom在Vscode衝擊下被淘汰 - githubVSCodeGithub
- 飽受衝擊,依舊迎風翱翔
- 居然之家擬衝擊千億市值,能行嗎?