Go 一個兼具單機和集羣模式的輕量級限流器:throttle
大家好,我是漁夫子。本號新推出「go 工具箱」系列,意在給大家分享使用 go 語言編寫的、實用的、好玩的工具。
今天給大家推薦的工具是一個輕量級的限流器,star:1.2k。該工具實現了對資源的訪問速率限制,資源可以是特定的 URL、用戶或者任何自定義的形式。比如針對 HTTP API 接口。該包基於通用信源速率算法(generic cell rate algorithm)實現的。其底層存儲是內置了內存存儲(memstore)和 redis 兩種存儲方式。可以根據具體的使用場景實現單機限流和集羣限流。
基本使用
下面代碼是實現了一個按請求 path 進行限流的 http 服務,允許同一個 path 每分鐘 20 次請求,並支持最多 5 個併發請求的 burst:
package main
import (
"fmt"
"log"
"net/http"
"github.com/throttled/throttled/v2"
"github.com/throttled/throttled/v2/store/memstore"
)
func main() {
// 在 store 中添加 key 的數量限制
store, err := memstore.New(65536)
if err != nil {
log.Fatal(err)
}
// 配置限流規則
quota := throttled.RateQuota{
MaxRate: throttled.PerMin(20),
MaxBurst: 5,
}
rateLimiter, err := throttled.NewGCRARateLimiter(store, quota)
if err != nil {
log.Fatal(err)
}
httpRateLimiter := throttled.HTTPRateLimiter{
RateLimiter: rateLimiter,
// 根據 path 進行限流
VaryBy: &throttled.VaryBy{Path: true},
}
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello, world\n")
})
http.ListenAndServe(":8080", httpRateLimiter.RateLimit(handler))
}
多種形式的資源定義
此外,我們也可以通過指定 VaryBy 的方式對資源進行更多的定義。在 VaryBy 中我們可以通過 Cookie、IP、HTTP 的請求方法、HEADER 頭、請求查詢參數等來更細粒度的定義資源。例如,若想對請求的來源 IP 進行訪問限制,則可以進行如下配置:
httpRateLimiter := throttled.HTTPRateLimiter{
RateLimiter: rateLimiter,
VaryBy: &throttled.VaryBy{Path:true, RemoteAddr:true}
}
自定義超限處理
資源訪問超過限額後,HTTPRateLimiter 默認提供了一個處理器是 DefaultDeniedHandler。同時我們也可以通過自定義 HTTPRateLimiter 中的 DeniedHandler 屬性來自定義超限後的輸出。如下:
httpRateLimiter := throttled.HTTPRateLimiter{
RateLimiter: rateLimiter,
VaryBy: &throttled.VaryBy{Path:true, RemoteAddr:true}
}
httpRateLimiter.DeniedHandler = http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Error(w, "超過限額了", 429)
}))
集羣模式限流**
throttled 包中內置了 memstore 和 redis 存儲模式。通過 memstore 存儲限流配額 就是單機版的限流模式。如果想對集羣進行統一限流則需要使用 redis 的存儲模式。
實現原理
該包是基於 GCRA 算法實現的。該算法本質上是根據設置的速率來計算每一個請求的理論達到時間,如果該理論達到時間在最大允許通過的時間窗口之內,則允許該請求通過,否則直接丟棄掉。該算法兼具令牌桶的最大容量特性來適應突增的流量,同時也具有漏桶的勻速消耗的特性。
更多項目詳情請查看如下鏈接 :
開源項目地址:https://github.com/throttled/throttled
參考資料:https://baike.baidu.com/item/通用信元速率算法/2083527
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/MN4wsITSVYHNMPoFRpRZFQ