Golang 限流器 time rate 使用介紹

2021-10-02 09:23:04 字數 2508 閱讀 4441

本主題為系列文章,分上下兩篇。本文主要介紹 time/rate 的具體使用方法,另外一篇文章 《golang 限流器 time/rate 實現剖析》 則著重介紹其內部實現原理。

限流器是後台服務中的非常重要的元件,可以用來限制請求速率,保護服務,以免服務過載。

限流器的實現方法有很多種,例如滑動視窗法、token bucket、leaky bucket 等。

其實 golang 標準庫中就自帶了限流演算法的實現,即 golang.org/x/time/rate。該限流器是基於token bucket(令牌桶)實現的。

簡單來說,令牌桶就是想象有乙個固定大小的桶,系統會以恆定速率向桶中放 token,桶滿則暫時不放。

而使用者則從桶中取 token,如果有剩餘 token 就可以一直取。如果沒有剩餘 token,則需要等到系統中被放置了 token 才行。

我們可以使用以下方法構造乙個限流器物件:

limiter :=

newlimiter(10

,1);

這裡有兩個引數:

那麼,對於以上例子來說,其構造出的限流器含義為,其令牌桶大小為 1, 以每秒 10 個 token 的速率向桶中放置 token。

除了直接指定每秒產生的 token 個數外,還可以用 every 方法來指定向 token 桶中放置 token 的間隔,例如:

limit :=

every

(100

* time.millisecond)

;limiter :=

newlimiter

(limit,1)

;

以上就表示每 100ms 往桶中放乙個 token。本質上也就是一秒鐘產生 10 個。

limiter 提供了三類方法供使用者消費 token,使用者可以每次消費乙個 token,也可以一次性消費多個 token。而每種方法代表了當 token 不足時,各自不同的對應手段。

func

(lim *limiter)

wait

(ctx context.context)

(err error

)func

(lim *limiter)

waitn

(ctx context.context, n int

)(err error

)

wait 實際上就是 waitn(ctx,1)。

當使用 wait 方法消費 token 時,如果此時桶內 token 陣列不足 (小於 n),那麼 wait 方法將會阻塞一段時間,直至 token 滿足條件。如果充足則直接返回。

這裡可以看到,wait 方法有乙個 context 引數。

我們可以設定 context 的 deadline 或者 timeout,來決定此次 wait 的最長時間。

func

(lim *limiter)

allow()

bool

func

(lim *limiter)

allown

(now time.time, n int

)bool

allow 實際上就是 allown(time.now(),1)。

allown 方法表示,截止到某一時刻,目前桶中數目是否至少為 n 個,滿足則返回 true,同時從桶中消費 n 個 token。反之返回不消費 token,false。

通常對應這樣的線上場景,如果請求速率過快,就直接丟掉某些請求。

func

(lim *limiter)

reserve()

*reservation

func

(lim *limiter)

reserven

(now time.time, n int

)*reservation

reserve 相當於 reserven(time.now(), 1)。

reserven 的用法就相對來說複雜一些,當呼叫完成後,無論 token 是否充足,都會返回乙個 reservation * 物件。

你可以呼叫該物件的 delay() 方法,該方法返回了需要等待的時間。如果等待時間為 0,則說明不用等待。

必須等到等待時間之後,才能進行接下來的工作。

或者,如果不想等待,可以呼叫 cancel() 方法,該方法會將 token 歸還。

舉乙個簡單的例子,我們可以這麼使用 reserve 方法。

r := lim.

reserve()

f !r.ok(

)time.

sleep

(r.delay()

)act()

// 執行相關邏輯

limiter 支援可以調整速率和桶大小:

有了這兩個方法,可以根據現有環境和條件,根據我們的需求,動態的改變 token 桶大小和速率。

golang 限流控制

限流 日常開發中,一般會遇到幾種場景需要限流,比如有個api server,需要限制單個使用者的呼叫頻率,避免使用者惡意刷介面或者突發大流量導致服務不可用等,這邊記錄幾個常用的限流方法。併發控制 簡單的併發控制,使用者的所有請求丟到乙個channel裡,再指定乙個帶緩衝區的channel為併發池,緩...

MSP430 TIMER A定時器設定示例

先記下來,以後看,說不定就會了呢 問題很多,咱啥都不懂,能看出歡迎討論哈 直接設定 ta0cctl0 ccie ccr0 interrupt enabled ta0ccr0 1000 意思是週期為1000ms 1hz ta0ctl tassel 2 mc 1 taclr 選擇時鐘源smclk,遞增模...

RedisTemplate 實現通用限流器

乙個安全的介面限流肯定少不了,登入尤其如此。比如驗證碼傳送,驗證碼驗證試錯,密碼登入試錯,這些雖然是不同的業務,但是目的都是乙個就是,對於某些使用者的某種行為在一段時間內的的允許次數進行限制 對於此我們抽象出來四個東西 接下來我們借助redis來實現這功能 redis中有一種資料型別 zset 簡單...