## 一、漏桶算法
即一個水桶, 進水(接受請求)的速率不限, 出水(處理請求)的速率是一定的, 如果出水的速率小于進水的速率, 就會造成水桶溢出(也就是拒絕請求); 主要是從出口限制, 以固定的速率控制訪問速度, 缺點是難以應對突發請求;
依賴庫:[https://github.com/go-redis/redis_rate](https://github.com/go-redis/redis_rate)
實例:
下面是一個簡單的實現, 對`/v1/hello`接口進行每分鐘2次的速率限制
```
// RateLimitConf 速率配置, 允許多長時間通過多少次.
type RateLimitConf struct {
Limit int64
Timer time.Duration
}
// exampleLimiterMap 接口請求速率配置, 建議放入redis/數據庫同步本地緩存.
var exampleLimiterMap = map[string]RateLimitConf{
"/v1/hello": {Limit: 2, Timer: time.Minute},
}
// LimiterMiddle 分布式限流中間件.
func LimiterMiddle(ctx iris.Context) {
var (
uri = ctx.Request().RequestURI
client = redis.NewClusterClient()
key = uri
)
conf, ok := exampleLimiterMap[uri]
if ok {
limiter := redis_rate.NewLimiter(client)
if _, _, b := limiter.Allow(key, conf.Limit, conf.Timer); !b {
r, _ := httpcode.NewRequest(ctx, nil)
r.Code(httpcode.TooManyReq, fmt.Errorf("req rate limit"), nil)
return
}
}
ctx.Next()
}
```
## 二、令牌桶算法
即也是一個桶, 按照設定的速率往桶里放令牌, 10s二十次即1s放兩個令牌(允許處理兩次請求), 然后請求來之后必須從桶里取出來令牌才可以進行處理, 沒有令牌則選擇拒絕或等待; 主要是從入口限制, 允許一定量的突發請求(即桶內所有的令牌);
依賴庫:[https://golang.org/x/time/rate](https://golang.org/x/time/rate)
實例:
下面是一個簡單的實現, 對`/v1/hello`接口進行每分鐘2次的速率限制
```
// exampleStandAloneLimiterMap 單機接口請求速率配置.
var exampleStandAloneLimiterMap = map[string]*rate.Limiter{
"/v1/hello": rate.NewLimiter(rate.Every(time.Minute), 2),
}
// StandAloneLimiterMiddle 單機限流中間件.
func StandAloneLimiterMiddle(ctx iris.Context) {
var (
uri = ctx.Request().RequestURI
)
limiter, ok := exampleStandAloneLimiterMap[uri]
if ok {
if b := limiter.Allow(); !b {
r, _ := httpcode.NewRequest(ctx, nil)
r.Code(httpcode.TooManyReq, fmt.Errorf("req rate limit"), nil)
return
}
}
ctx.Next()
}
```