Go 基於令牌桶的限流器實現

2022-09-21 02:51:06 字數 2728 閱讀 5993

目錄

如果一般流量過大,下游系統反應不過來,這個時候就需要限流了,其實和上地鐵是一樣的,就是減慢上游訪問下游的速度。

限制訪問服務的頻次或者頻率,防止服務過載,被刷爆等。

golang 官方擴充套件包 time(golang.org/x/time/rate) 中,提供了乙個基於令牌桶等限流器實現。

具體使用

package limiter

import (

"fmt"

"testing"

"time"

"golang.org/x/time/rate"

)func testlimter(t *test程式設計客棧ing.t)

time.sleep(time.millisecond * 20)

fmt.p程式設計客棧rintln(ok, limiter.burst())

}}執行結果:

=== run   testlimter

true 2

true 2

true 2

false 2

true 2

true 2

false 2

tr 2

true 2

false 2

--- pass: testlimter (0.21s)

通過執行結果可以看到, 令牌桶開始是2個滿的,由於令牌的間隔比請求的間隔多了11ms(31-20), 所以每兩個請求會失敗一次。

先看下限流器的建立方法: newlimiter

func newlimiter(r limit, b int) *limiter

}檢視限流器資料結構 limiter

// the methods allown, reserven, and waitn consume n tokens.

type limiter struct

當令牌桶發放後,會保留在 reservation 物件中, 定義如下, reservation 物件,描述了乙個達到 timetoact 時間後,可以獲取到的令牌的數量 tokens 數。

type reservation struct

官方提供的限流器有阻塞等待, 也有直接判斷方式的, 還有提供維護預留式等。

如何實現限流的**,在 reserven 中。

使用時,每次都呼叫了 allow() 方法

// allow is shorthand for allown(time.now(), 1).

func (lim *limiter) allow() bool

// allown reports whether n events may happen at time now.

// use this method if you intend to drop / skip events that exceed the rate limit.

// otherwise use reserve or wait.

func (lim *limiter) allown(now time.time, n int) bool

繼續檢視 reservern  演算法

方法說明:

// maxfuturereserve specifies the maximum reservation wait duration allowed.

// reserven returns reservation, not *reservation, to **oid allocation in allown and waitn.

func (lim *limiter) reserven(now time.time, n int, maxfuturereserve time.duration) reservation

} // 拿到截止 now 時間時,可以獲取的令牌 tokens 數量,上一次拿走令牌的時間是last

now, last, tokens := lim.advance(now)

// calculate the remaining number of tokens resulting from the request.

// 更新 tokens數量,把需要拿走的去掉

tokens -= float64(n)

// calculate the wait duration

// 如果 tokens 數量為負數,說明需要等待,計算等待時間 waitduration

var waitduration time.duration

if tokens < 0

// decide result

// 計算是否滿足分配要求

// 1. 需要分配的大小不超過桶容量

// 2. 等待時間不超過設定的等待時長

ok := n <= lim.burst && waitduration <= maxfuturereserve

// prepare reservation

// 最後構造乙個 resvervation 物件

r := reservation

if ok

// update state

// 需要更新當前 limit 的值

if ok else

lim.mu.unlock()www.cppcns.com

return r

}從實現上看, limiter 並不是每隔一段時間更新當前桶的數量,而是記錄了上次訪問時和當前桶中令牌的數量,當再次訪問時,通過上次訪問時間計算出當前令牌的數量,決定是否可以發放令牌。

限流策略 令牌桶與漏斗桶的實現

redis 服務端和客戶端的安裝啟動 產看當前redis版本 redis server v bash usr local bin redis server no such file or directory redis cli v bash usr local bin redis cli no su...

php令牌桶演算法實現介面限流

前端每次請求從令牌桶取走令牌,後端勻速向桶內投遞令牌,如果前端取到令牌,則說明這次請求有效,否則讓前端再次請求或者等待。避免了大量請求下伺服器壓力過大導致的崩潰問題。令牌桶類 class token catch redi ception exception 令牌初始化 public function...

分布式限流實戰 redis實現令牌桶限流

這篇文章我們主要是分析一下分布式限流的玩法。因為限流也是乙個經典用法了。隨著微服務的流行,服務和服務之間的穩定性變得越來越重要。快取 降級和限流是保護微服務系統執行穩定性的三大利器。快取的目的是提公升系統訪問速度和增大系統能處理的容量,而降級是當服務出問題或者影響到核心流程的效能則需要暫時遮蔽掉,待...