最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go官方限流器的用法詳解

 更新時間:2022年05月07日 10:12:18   作者:程序員王越  
限流器是提升服務(wù)穩(wěn)定性的非常重要的組件,本文主要介紹了Go官方限流器的用法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

限流器是提升服務(wù)穩(wěn)定性的非常重要的組件,可以用來限制請求速率,保護(hù)服務(wù),以免服務(wù)過載。限流器的實現(xiàn)方法有很多種,常見的限流算法有固定窗口、滑動窗口、漏桶、令牌桶

簡單來說,令牌桶就是想象有一個固定大小的桶,系統(tǒng)會以恒定速率向桶中放 Token,桶滿則暫時不放。在請求比較的少的時候桶可以先"攢"一些Token,應(yīng)對突發(fā)的流量,如果桶中有剩余 Token 就可以一直取。如果沒有剩余 Token,則需要等到桶中被放置了 Token 才行。

有的同學(xué)在看明白令牌桶的原理后就非常想去自己實現(xiàn)一個限流器應(yīng)用到自己的項目里,em... 怎么說呢,造個輪子確實有利于自己水平提高,不過要是應(yīng)用到商用項目里的話其實大可不必自己去造輪子,Golang官方已經(jīng)替我們造好輪子啦 ......~!

Golang 官方提供的擴(kuò)展庫里就自帶了限流算法的實現(xiàn),即 golang.org/x/time/rate。該限流器也是基于 Token Bucket(令牌桶) 實現(xiàn)的。

限流器的內(nèi)部結(jié)構(gòu)

time/rate包的Limiter類型對限流器進(jìn)行了定義,所有限流功能都是通過基于Limiter類型實現(xiàn)的,其內(nèi)部結(jié)構(gòu)如下:

type Limiter struct {
 mu     sync.Mutex
 limit  Limit
 burst  int // 令牌桶的大小
 tokens float64
 last time.Time // 上次更新tokens的時間
 lastEvent time.Time // 上次發(fā)生限速器事件的時間(通過或者限制都是限速器事件)
}

其主要字段的作用是:

  • limit:limit字段表示往桶里放Token的速率,它的類型是Limit,是int64的類型別名。設(shè)置limit時既可以用數(shù)字指定每秒向桶中放多少個Token,也可以指定向桶中放Token的時間間隔,其實指定了每秒放Token的個數(shù)后就能計算出放每個Token的時間間隔了。

  • burst: 令牌桶的大小。

  • tokens: 桶中的令牌。

  • last: 上次往桶中放 Token 的時間。

  • lastEvent:上次發(fā)生限速器事件的時間(通過或者限制都是限速器事件)

可以看到在 timer/rate 的限流器實現(xiàn)中,并沒有單獨(dú)維護(hù)一個 Timer 和隊列去真的每隔一段時間向桶中放令牌,而是僅僅通過計數(shù)的方式表示桶中剩余的令牌。每次消費(fèi)取 Token 之前會先根據(jù)上次更新令牌數(shù)的時間差更新桶中Token數(shù)

大概了解了time/rate限流器的內(nèi)部實現(xiàn)后,下面的內(nèi)容我們會集中介紹下該組件的具體使用方法:

構(gòu)造限流器

我們可以使用以下方法構(gòu)造一個限流器對象:

limiter := rate.NewLimiter(10, 100);

這里有兩個參數(shù):

  • 第一個參數(shù)是 r Limit,設(shè)置的是限流器Limiter的limit字段,代表每秒可以向 Token 桶中產(chǎn)生多少 token。Limit 實際上是 float64 的別名。

  • 第二個參數(shù)是 b int,b 代表 Token 桶的容量大小,也就是設(shè)置的限流器 Limiter 的burst字段。

那么,對于以上例子來說,其構(gòu)造出的限流器的令牌桶大小為 100, 以每秒 10 個 Token 的速率向桶中放置 Token。

除了給r Limit參數(shù)直接指定每秒產(chǎn)生的 Token 個數(shù)外,還可以用 Every 方法來指定向桶中放置 Token 的間隔,例如:

limit := rate.Every(100 * time.Millisecond);
limiter := rate.NewLimiter(limit, 100);

以上就表示每 100ms 往桶中放一個 Token。本質(zhì)上也是一秒鐘往桶里放 10 個。

使用限流器

Limiter 提供了三類方法供程序消費(fèi) Token,可以每次消費(fèi)一個 Token,也可以一次性消費(fèi)多個 Token。每種方法代表了當(dāng) Token 不足時,各自不同的對應(yīng)手段,可以阻塞等待桶中Token補(bǔ)充,也可以直接返回取Token失敗。

Wait/WaitN

func (lim *Limiter) Wait(ctx context.Context) (err error)
func (lim *Limiter) WaitN(ctx context.Context, n int) (err error)

Wait 實際上就是 WaitN(ctx,1)

當(dāng)使用 Wait 方法消費(fèi) Token 時,如果此時桶內(nèi) Token 數(shù)組不足 (小于 N),那么 Wait 方法將會阻塞一段時間,直至 Token 滿足條件。如果充足則直接返回。

這里可以看到,Wait 方法有一個 context 參數(shù)。我們可以設(shè)置 context 的 Deadline 或者 Timeout,來決定此次 Wait 的最長時間。

// 一直等到獲取到桶中的令牌
err := limiter.Wait(context.Background())
if err != nil {
 fmt.Println("Error: ", err)
}

// 設(shè)置一秒的等待超時時間
ctx, _ := context.WithTimeout(context.Background(), time.Second * 1)
err := limiter.Wait(ctx)
if err != nil {
 fmt.Println("Error: ", err)
}

Allow/AllowN

func (lim *Limiter) Allow() bool
func (lim *Limiter) AllowN(now time.Time, n int) bool

Allow 實際上就是對 AllowN(time.Now(),1) 進(jìn)行簡化的函數(shù)。

AllowN 方法表示,截止到某一時刻,目前桶中數(shù)目是否至少為 n 個,滿足則返回 true,同時從桶中消費(fèi) n 個 token。反之不消費(fèi)桶中的Token,返回false。

對應(yīng)線上的使用場景是,如果請求速率超過限制,就直接丟棄超頻后的請求。

if limiter.AllowN(time.Now(), 2) {
    fmt.Println("event allowed")
} else {
    fmt.Println("event not allowed")
}

Reserve/ReserveN

func (lim *Limiter) Reserve() *Reservation
func (lim *Limiter) ReserveN(now time.Time, n int) *Reservation

Reserve 相當(dāng)于 ReserveN(time.Now(), 1)。

ReserveN 的用法就相對來說復(fù)雜一些,當(dāng)調(diào)用完成后,無論 Token 是否充足,都會返回一個 *Reservation 對象。你可以調(diào)用該對象的Delay()方法,該方法返回的參數(shù)類型為time.Duration,反映了需要等待的時間,必須等到等待時間之后,才能進(jìn)行接下來的工作。如果不想等待,可以調(diào)用Cancel()方法,該方法會將 Token 歸還。

舉一個簡單的例子,我們可以這么使用 Reserve 方法。

r := limiter.Reserve()
f !r.OK() {
    // Not allowed to act! Did you remember to set lim.burst to be > 0 ?
    return
}
time.Sleep(r.Delay())
Act() // 執(zhí)行相關(guān)邏輯

動態(tài)調(diào)整速率和桶大小

Limiter 支持創(chuàng)建后動態(tài)調(diào)整速率和桶大?。?/p>

  • SetLimit(Limit) 改變放入 Token 的速率

  • SetBurst(int) 改變 Token 桶大小

有了這兩個方法,可以根據(jù)現(xiàn)有環(huán)境和條件以及我們的需求,動態(tài)地改變 Token 桶大小和速率。

總結(jié)

今天我們總結(jié)了 Golang 官方限流器的使用方法,它是一種令牌桶算實現(xiàn)的限流器。其中 Wait/WaitN,Allow/AllowN 這兩組方法在平時用的比較多,前者是消費(fèi)Token時如果桶中Token不足可以讓程序等待桶中新Token的放入(最好設(shè)置上等待時長)后者則是在桶中的Token不足時選擇直接丟棄請求。

除了Golang官方提供的限流器實現(xiàn),Uber公司開源的限流器uber-go/ratelimit也是一個很好的選擇,與Golang官方限流器不同的是Uber的限流器是通過漏桶算法實現(xiàn)的,不過對傳統(tǒng)的漏桶算法進(jìn)行了改良,有興趣的同學(xué)可以自行去體驗一下。

到此這篇關(guān)于Go官方限流器的用法詳解的文章就介紹到這了,更多相關(guān)Go 限流器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言中的通道channel詳情

    Go語言中的通道channel詳情

    這篇文章主要介紹了Go語言中的通道channel,在Go語言中管道類似于一個數(shù)據(jù)流,每次放入或者取出一部分?jǐn)?shù)據(jù),數(shù)據(jù)取出后原通道內(nèi)的數(shù)據(jù)就刪除掉,在linux操作系統(tǒng)中管道會將函數(shù)的返回結(jié)果作為下一個函數(shù)的參數(shù),下文詳細(xì)內(nèi)容需要的朋友可以參考下
    2022-02-02
  • Go語言運(yùn)行環(huán)境安裝詳細(xì)教程

    Go語言運(yùn)行環(huán)境安裝詳細(xì)教程

    這篇文章主要介紹了Go語言運(yùn)行環(huán)境安裝詳細(xì)教程,本文講解了Linux、MAC OS、Windows下的安裝方法,同時講解了驗證是否安裝成功、第三方工具安裝運(yùn)行環(huán)境的方法,需要的朋友可以參考下
    2014-10-10
  • 解決vscode中g(shù)olang插件依賴安裝失敗問題

    解決vscode中g(shù)olang插件依賴安裝失敗問題

    這篇文章主要介紹了解決vscode中g(shù)olang插件依賴安裝失敗問題,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-08-08
  • Golang二維切片初始化的實現(xiàn)

    Golang二維切片初始化的實現(xiàn)

    這篇文章主要介紹了Golang二維切片初始化的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Go語言atomic.Value如何不加鎖保證數(shù)據(jù)線程安全?

    Go語言atomic.Value如何不加鎖保證數(shù)據(jù)線程安全?

    這篇文章主要介紹了Go語言atomic.Value如何不加鎖保證數(shù)據(jù)線程安全詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • Go 函數(shù)返回nil遇到問題避坑分析

    Go 函數(shù)返回nil遇到問題避坑分析

    這篇文章主要為大家介紹了Go 函數(shù)返回nil遇到的避坑問題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • Go map排序的實現(xiàn)示例

    Go map排序的實現(xiàn)示例

    map默認(rèn)是無序的,不管是按照key還是按照value默認(rèn)都不排序,本文主要介紹了Go map排序的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • 一文帶你感受Go語言空結(jié)構(gòu)體的魔力

    一文帶你感受Go語言空結(jié)構(gòu)體的魔力

    在?Go?語言中,有一種特殊的用法可能讓許多人感到困惑,那就是空結(jié)構(gòu)體,本文將對Go空結(jié)構(gòu)體進(jìn)行詳解,準(zhǔn)備一杯你最喜歡的飲料或茶,隨著本文一探究竟吧
    2023-05-05
  • go-zero源碼閱讀之布隆過濾器實現(xiàn)代碼

    go-zero源碼閱讀之布隆過濾器實現(xiàn)代碼

    布隆過濾器可以用于檢索一個元素是否在一個集合中。它的優(yōu)點是空間效率和查詢時間都比一般的算法要好的多,缺點是有一定的誤識別率和刪除困難,這篇文章主要介紹了go-zero源碼閱讀-布隆過濾器,需要的朋友可以參考下
    2023-02-02
  • 詳解如何在Golang中實現(xiàn)CORS(跨域)

    詳解如何在Golang中實現(xiàn)CORS(跨域)

    很多時候,需要允許Web應(yīng)用程序在不同域之間(跨域)實現(xiàn)共享資源,本文將簡介跨域、CORS的概念,以及如何在Golang中如何實現(xiàn)CORS,文中有詳細(xì)的示例代碼,需要的朋友可以參考下
    2023-10-10

最新評論

桦川县| 洪湖市| 马鞍山市| 奉新县| 广水市| 金坛市| 大同市| 纳雍县| 张掖市| 东兴市| 儋州市| 台北县| 阿巴嘎旗| 南丰县| 蕉岭县| 宁城县| 万载县| 安远县| 木兰县| 泰和县| 遂昌县| 万年县| 江都市| 秀山| 客服| 策勒县| 惠水县| 万盛区| 大渡口区| 高青县| 定边县| 和硕县| 安泽县| 连城县| 樟树市| 子长县| 贺州市| 怀来县| 绍兴县| 枣庄市| 湖北省|