国产精品嫩草99av在线_一区在线视频观看_欧美高清一区_欧美 日韩 国产 一区_99精品欧美一区二区三区_久久大香伊蕉在人线观看热2_一色屋精品视频在线观看网站_在线亚洲国产精品网站_亚洲区一区二区三区_你懂的视频一区二区

當前位置:首頁 > 科技  > 軟件

Go-Zero 是如何實現令牌桶限流的?

來源: 責編: 時間:2023-08-14 22:01:53 3424觀看
導讀上一篇文章介紹了 如何實現計數器限流。主要有兩種實現方式,分別是固定窗口和滑動窗口,并且分析了 go-zero 采用固定窗口方式實現的源碼。但是采用固定窗口實現的限流器會有兩個問題:會出現請求量超出限制值兩倍的情況無

上一篇文章介紹了 如何實現計數器限流。主要有兩種實現方式,分別是固定窗口和滑動窗口,并且分析了 go-zero 采用固定窗口方式實現的源碼。jWY28資訊網——每日最新資訊28at.com

但是采用固定窗口實現的限流器會有兩個問題:jWY28資訊網——每日最新資訊28at.com

  1. 會出現請求量超出限制值兩倍的情況
  2. 無法很好處理流量突增問題

這篇文章來介紹一下令牌桶算法,可以很好解決以上兩個問題。jWY28資訊網——每日最新資訊28at.com

工作原理

算法概念如下:jWY28資訊網——每日最新資訊28at.com

  • 令牌以固定速率生成;
  • 生成的令牌放入令牌桶中存放,如果令牌桶滿了則多余的令牌會直接丟棄,當請求到達時,會嘗試從令牌桶中取令牌,取到了令牌的請求可以執行;
  • 如果桶空了,那么嘗試取令牌的請求會被直接丟棄。

圖片圖片jWY28資訊網——每日最新資訊28at.com

令牌桶算法既能夠將所有的請求平均分布到時間區間內,又能接受服務器能夠承受范圍內的突發請求,因此是目前使用較為廣泛的一種限流算法。jWY28資訊網——每日最新資訊28at.com

源碼實現

源碼分析我們還是以 go-zero 項目為例,首先來看生成令牌的部分,依然是使用 Redis 來實現。jWY28資訊網——每日最新資訊28at.com

// core/limit/tokenlimit.go// 生成 token 速率script = `local rate = tonumber(ARGV[1])// 通容量local capacity = tonumber(ARGV[2])// 當前時間戳local now = tonumber(ARGV[3])// 請求數量local requested = tonumber(ARGV[4])// 需要多少秒才能把桶填滿local fill_time = capacity/rate// 向下取整,ttl 為填滿時間 2 倍local ttl = math.floor(fill_time*2)// 當前桶剩余容量,如果為 nil,說明第一次使用,賦值為桶最大容量local last_tokens = tonumber(redis.call("get", KEYS[1]))if last_tokens == nil then    last_tokens = capacityend// 上次請求時間戳,如果為 nil 則賦值 0local last_refreshed = tonumber(redis.call("get", KEYS[2]))if last_refreshed == nil then    last_refreshed = 0end// 距離上一次請求的時間跨度local delta = math.max(0, now-last_refreshed)// 距離上一次請求的時間跨度能生成的 token 數量和桶內剩余 token 數量的和// 與桶容量比較,取二者的小值local filled_tokens = math.min(capacity, last_tokens+(delta*rate))// 判斷請求數量和桶內 token 數量的大小local allowed = filled_tokens >= requested// 被請求消耗掉之后,更新剩余 token 數量local new_tokens = filled_tokensif allowed then    new_tokens = filled_tokens - requestedend// 更新 redis tokenredis.call("setex", KEYS[1], ttl, new_tokens)// 更新 redis 刷新時間redis.call("setex", KEYS[2], ttl, now)return allowed`

Redis 中主要保存兩個 key,分別是 token 數量和刷新時間。jWY28資訊網——每日最新資訊28at.com

核心思想就是比較兩次請求時間間隔內生成的 token 數量 + 桶內剩余 token 數量,和請求量之間的大小,如果滿足則允許,否則則不允許。jWY28資訊網——每日最新資訊28at.com

限流器初始化:jWY28資訊網——每日最新資訊28at.com

// A TokenLimiter controls how frequently events are allowed to happen with in one second.type TokenLimiter struct {    // 生成 token 速率    rate           int    // 桶容量    burst          int    store          *redis.Redis    // 桶 key    tokenKey       string    // 桶刷新時間 key    timestampKey   string    rescueLock     sync.Mutex    // redis 健康標識    redisAlive     uint32    // redis 健康監控啟動狀態    monitorStarted bool    // 內置單機限流器    rescueLimiter  *xrate.Limiter}// NewTokenLimiter returns a new TokenLimiter that allows events up to rate and permits// bursts of at most burst tokens.func NewTokenLimiter(rate, burst int, store *redis.Redis, key string) *TokenLimiter {    tokenKey := fmt.Sprintf(tokenFormat, key)    timestampKey := fmt.Sprintf(timestampFormat, key)    return &TokenLimiter{        rate:          rate,        burst:         burst,        store:         store,        tokenKey:      tokenKey,        timestampKey:  timestampKey,        redisAlive:    1,        rescueLimiter: xrate.NewLimiter(xrate.Every(time.Second/time.Duration(rate)), burst),    }}

其中有一個變量 rescueLimiter,這是一個進程內的限流器。如果 Redis 發生故障了,那么就使用這個,算是一個保障,盡量避免系統被突發流量拖垮。jWY28資訊網——每日最新資訊28at.com

圖片圖片jWY28資訊網——每日最新資訊28at.com

提供了四個可調用方法:jWY28資訊網——每日最新資訊28at.com

// Allow is shorthand for AllowN(time.Now(), 1).func (lim *TokenLimiter) Allow() bool {    return lim.AllowN(time.Now(), 1)}// AllowCtx is shorthand for AllowNCtx(ctx,time.Now(), 1) with incoming context.func (lim *TokenLimiter) AllowCtx(ctx context.Context) bool {    return lim.AllowNCtx(ctx, time.Now(), 1)}// AllowN reports whether n events may happen at time now.// Use this method if you intend to drop / skip events that exceed the rate.// Otherwise, use Reserve or Wait.func (lim *TokenLimiter) AllowN(now time.Time, n int) bool {    return lim.reserveN(context.Background(), now, n)}// AllowNCtx reports whether n events may happen at time now with incoming context.// Use this method if you intend to drop / skip events that exceed the rate.// Otherwise, use Reserve or Wait.func (lim *TokenLimiter) AllowNCtx(ctx context.Context, now time.Time, n int) bool {    return lim.reserveN(ctx, now, n)}

最終調用的都是 reverveN 方法:jWY28資訊網——每日最新資訊28at.com

func (lim *TokenLimiter) reserveN(ctx context.Context, now time.Time, n int) bool {    // 判斷 Redis 健康狀態,如果 Redis 故障,則使用進程內限流器    if atomic.LoadUint32(&lim.redisAlive) == 0 {        return lim.rescueLimiter.AllowN(now, n)    }    // 執行限流腳本    resp, err := lim.store.EvalCtx(ctx,        script,        []string{            lim.tokenKey,            lim.timestampKey,        },        []string{            strconv.Itoa(lim.rate),            strconv.Itoa(lim.burst),            strconv.FormatInt(now.Unix(), 10),            strconv.Itoa(n),        })    // redis allowed == false    // Lua boolean false -> r Nil bulk reply    if err == redis.Nil {        return false    }    if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {        logx.Errorf("fail to use rate limiter: %s", err)        return false    }    if err != nil {        logx.Errorf("fail to use rate limiter: %s, use in-process limiter for rescue", err)        // 如果有異常的話,會啟動進程內限流        lim.startMonitor()        return lim.rescueLimiter.AllowN(now, n)    }    code, ok := resp.(int64)    if !ok {        logx.Errorf("fail to eval redis script: %v, use in-process limiter for rescue", resp)        lim.startMonitor()        return lim.rescueLimiter.AllowN(now, n)    }    // redis allowed == true    // Lua boolean true -> r integer reply with value of 1    return code == 1}

最后看一下進程內限流的啟動與恢復:jWY28資訊網——每日最新資訊28at.com

func (lim *TokenLimiter) startMonitor() {    lim.rescueLock.Lock()    defer lim.rescueLock.Unlock()    // 需要加鎖保護,如果程序已經啟動了,直接返回,不要重復啟動    if lim.monitorStarted {        return    }    lim.monitorStarted = true    atomic.StoreUint32(&lim.redisAlive, 0)    go lim.waitForRedis()}func (lim *TokenLimiter) waitForRedis() {    ticker := time.NewTicker(pingInterval)    // 更新監控進程的狀態    defer func() {        ticker.Stop()        lim.rescueLock.Lock()        lim.monitorStarted = false        lim.rescueLock.Unlock()    }()    for range ticker.C {        // 對 redis 進行健康監測,如果 redis 服務恢復了        // 則更新 redisAlive 標識,并退出 goroutine        if lim.store.Ping() {            atomic.StoreUint32(&lim.redisAlive, 1)            return        }    }}

參考文章:jWY28資訊網——每日最新資訊28at.com

  • https://juejin.cn/post/7052171117116522504
  • https://www.infoq.cn/article/Qg2tX8fyw5Vt-f3HH673

本文鏈接:http://m.rrqrq.com/showinfo-26-5770-0.htmlGo-Zero 是如何實現令牌桶限流的?

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 「Go面經」算法 并發模型 緩存落盤 etcd actor模型

下一篇: 阿里云還會繼續降價嗎?

標簽:
  • 熱門焦點
  • 一加Ace2 Pro官宣:普及16G內存 引領24G

    一加官方今天繼續為本月發布的新機一加Ace2 Pro帶來預熱,公布了內存方面的信息。“淘汰 8GB ,12GB 起步,16GB 普及,24GB 引領,還有呢?#一加Ace2Pro#,2023 年 8 月,敬請期待。”同時
  • 小米官宣:2023年上半年出貨量中國第一!

    今日早間,小米電視官方微博帶來消息,稱2023年小米電視上半年出貨量達到了中國第一,同時還表示小米電視的巨屏風暴即將開始。“公布一個好消息2023年#小米電視上半年出貨量中國
  • 中興AX5400Pro+上手體驗:再升級 雙2.5G網口+USB 3.0這次全都有

    2021年11月的時候,中興先后發布了兩款路由器產品,中興AX5400和中興AX5400 Pro,從產品命名上就不難看出這是隸屬于同一系列的,但在外觀設計上這兩款產品可以說是完全沒一點關系
  • 企業采用CRM系統的11個好處

    客戶關系管理(CRM)軟件可以為企業提供很多的好處,從客戶保留到提高生產力。  CRM軟件用于企業收集客戶互動,以改善客戶體驗和滿意度。  CRM軟件市場規模如今超過580
  • Flowable工作流引擎的科普與實踐

    一.引言當我們在日常工作和業務中需要進行各種審批流程時,可能會面臨一系列技術和業務上的挑戰。手動處理這些審批流程可能會導致開發成本的增加以及業務復雜度的上升。在這
  • 三萬字盤點 Spring 九大核心基礎功能

    大家好,我是三友~~今天來跟大家聊一聊Spring的9大核心基礎功能。話不多說,先上目錄:圖片友情提示,本文過長,建議收藏,嘿嘿嘿!一、資源管理資源管理是Spring的一個核心的基礎功能,不
  • 使用LLM插件從命令行訪問Llama 2

    最近的一個大新聞是Meta AI推出了新的開源授權的大型語言模型Llama 2。這是一項非常重要的進展:Llama 2可免費用于研究和商業用途。(幾小時前,swyy發現它已從LLaMA 2更名為Lla
  • 虛擬鍵盤 API 的妙用

    你是否在遇到過這樣的問題:移動設備上有一個固定元素,當激活虛擬鍵盤時,該元素被隱藏在了鍵盤下方?多年來,這一直是 Web 上的默認行為,在本文中,我們將探討這個問題、為什么會發生
  • 網紅炒股不為了賺錢,那就是耍流氓!

    來源:首席商業評論6月26日高調宣布入市,網絡名嘴大v胡錫進居然進軍了股市。在一次財經媒體峰會上,幾個財經圈媒體大佬就“胡錫進炒股是否知道認真報道”展開討論。有
Top 国产精品嫩草99av在线_一区在线视频观看_欧美高清一区_欧美 日韩 国产 一区_99精品欧美一区二区三区_久久大香伊蕉在人线观看热2_一色屋精品视频在线观看网站_在线亚洲国产精品网站_亚洲区一区二区三区_你懂的视频一区二区
中文字幕乱码亚洲精品一区| 亚洲免费成人| 一区在线播放| 在线日韩国产精品| 精品国产乱码久久久久久夜甘婷婷 | 精品久久一区二区| 亚洲欧美成aⅴ人在线观看| 蜜臀av性久久久久蜜臀aⅴ流畅| 成人综合激情网| 校园激情久久| 久久午夜免费电影| 日本不卡的三区四区五区| 91麻豆自制传媒国产之光| 久久精品成人| 中文字幕一区二区三区在线播放 | 精品国产乱码久久久久久免费 | 欧美日本一区二区| 一区二区三区国产精华| 不卡视频在线看| 日本黄色一区二区| 亚洲欧美欧美一区二区三区| 成人免费视频免费观看| 在线视频中文字幕一区二区| 亚洲天堂免费在线观看视频| 国产91在线观看丝袜| 色丁香久综合在线久综合在线观看| 国产精品视频在线看| 国产成人免费视频一区| 一本一道综合狠狠老| 亚洲男同1069视频| 欧美一区免费| 91麻豆精品国产无毒不卡在线观看| 亚洲一区二区免费视频| 午夜精彩国产免费不卡不顿大片| 欧美片网站yy| 美女在线视频一区| 久久久久久夜| 亚洲欧美一区二区久久| 欧美日韩福利| 久久蜜桃av一区二区天堂| 国产精品18久久久久久久久| 欧美网站一区二区| 免费成人在线视频观看| 久久伊人亚洲| 亚洲成人激情av| 国产亚洲在线| 亚洲精品伦理在线| 伊人久久综合| 国产精品不卡在线观看| 欧美特黄一区| 国产精品三级电影| 国内自拍亚洲| 自拍av一区二区三区| 在线国产精品一区| 国产精品的网站| 日韩亚洲欧美高清| 日韩影院精彩在线| 久久综合电影| 免费不卡在线观看| 欧美日韩精品一区二区| 国产乱淫av一区二区三区| 欧美日本在线视频| 国产成人av一区二区三区在线 | 99视频超级精品| 久久午夜老司机| 国产尤物精品| 夜夜嗨av一区二区三区四季av| 国产精品免费看| 肉肉av福利一精品导航| 在线观看国产91| 国产原创一区二区三区| 欧美zozo另类异族| 欧美区国产区| 亚洲精品五月天| 色综合久久久久久久| 久久国产乱子精品免费女| 欧美一区二区三区系列电影| 成人18视频日本| 国产精品灌醉下药二区| 国产一级一区二区| 美女免费视频一区二区| 欧美不卡视频一区| 国产精品国产亚洲精品看不卡15 | 欧美久久一区二区| 不卡av在线免费观看| 亚洲欧洲精品天堂一级| 老鸭窝亚洲一区二区三区| 久久97超碰国产精品超碰| 精品日韩在线一区| 亚洲三级电影在线观看| 人禽交欧美网站| 欧美一区二区成人| 亚洲午夜一级| 奇米精品一区二区三区四区| 欧美mv日韩mv国产| 影音欧美亚洲| 美女精品一区二区| 久久精品视频在线看| 国产日本精品| 国产精品中文欧美| 最新国产の精品合集bt伙计| 欧洲在线/亚洲| 91视视频在线直接观看在线看网页在线看| 亚洲人成在线播放网站岛国| 在线观看91精品国产入口| 91麻豆免费视频| 午夜精品视频在线观看| 精品久久一区二区| 免费不卡亚洲欧美| 成a人片亚洲日本久久| 亚洲午夜一区二区| 精品日韩欧美在线| 午夜在线a亚洲v天堂网2018| 国产精品正在播放| 一区二区三区丝袜| 亚洲精品一区二区精华| 噜噜噜躁狠狠躁狠狠精品视频 | 亚洲精品菠萝久久久久久久| 欧美福利视频一区| 日韩欧美国产综合在线一区二区三区| 欧美不卡福利| 精一区二区三区| 1024国产精品| 日韩免费观看2025年上映的电影 | 免费高清在线视频一区·| 日本一区免费视频| 欧美男同性恋视频网站| 午夜一级在线看亚洲| 欧美一区二区三区在线免费观看 | 久久欧美中文字幕| 欧美日韩在线电影| 亚洲一区免费看| 欧美网站在线| 成人午夜av电影| 美女一区二区在线观看| 一区二区三区在线播放| 久久精品综合网| 欧美一区二区三区日韩视频| 久久一综合视频| 99精品国产在热久久下载| 99久久久无码国产精品| 韩国女主播成人在线| 日韩在线一区二区三区| 一二三区精品福利视频| 国产精品久久久久久妇女6080| 日韩欧美国产高清| 欧美日韩国产另类一区| 91福利在线播放| 国产精品综合| 在线亚洲自拍| 亚洲精品男同| 极品中文字幕一区| 午夜视频久久久| 成人动漫视频在线| 国产a级毛片一区| 国产一区二区三区香蕉| 蜜臀久久久99精品久久久久久| 亚洲午夜视频在线| 一区二区久久久久| 亚洲一区二区三区小说| 一区二区三区在线免费| 亚洲精品欧美在线| 一区二区三区欧美| 亚洲精品一卡二卡| 夜夜精品视频一区二区| 亚洲一区二区影院| 亚洲成av人在线观看| 亚洲大尺度视频在线观看| 亚洲精品久久久久久国产精华液| 亚洲欧美自拍偷拍色图| 亚洲欧美视频在线观看视频| 亚洲欧美另类小说| 亚洲综合在线电影| 午夜欧美电影在线观看| 午夜视频在线观看一区二区三区| 亚洲第一久久影院| 麻豆精品精品国产自在97香蕉 | 亚洲精品一区二区三区四区高清 | 国产农村妇女毛片精品久久莱园子| 最新国产乱人伦偷精品免费网站| 亚洲日韩视频| 亚洲欧美日韩精品久久久| 久久免费99精品久久久久久| 91福利在线观看| 欧美一区二区三区在线观看视频 | 狠狠爱综合网| 国产精品久久国产愉拍| 久久亚洲国产精品日日av夜夜| 91成人免费在线| 欧美一区二区三区在| 久久精品一区四区| 专区另类欧美日韩| 日韩精品国产精品| 国产精品一区在线观看乱码 | 亚洲国产精品久久一线不卡| 蜜桃av噜噜一区| 成人va在线观看| 伊人成人网在线看| 日本韩国欧美国产| 精品国产伦一区二区三区观看方式|