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