🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 一、漏桶算法 即一个水桶, 进水(接受请求)的速率不限, 出水(处理请求)的速率是一定的, 如果出水的速率小于进水的速率, 就会造成水桶溢出(也就是拒绝请求); 主要是从出口限制, 以固定的速率控制访问速度, 缺点是难以应对突发请求; 依赖库:[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() } ```