限流总结

最近回顾了一下限流的一些方法,这里做一下记录

限流解决的问题

避免过多的流量 进入后端,导致服务不可用。

限流算法总结

漏桶算法

思路: 平均的每隔一段时间释放一个请求。

比如, 现在限速是 每秒 10个请求,那么,在该算法下, 每一个请求之间必须间隔100ms

存在的问题: 比如当前秒同时过来 2个 请求,如果每个请求耗时 1ms, 再不计算网络耗时的情况下, 那么第一个请求1ms 就能返回, 而第二个请求 必须 101ms 后才能返回。

该算法适合 那种严格限速的场景, 但如果业务上希望既能限速,又能快速返回的场景下就显得不太合适。

令牌桶算法

思路: 抽象了一个桶的概念,每一个请求需要消耗一个令牌,而令牌会按照一定的速度增加。

存在的问题: 同漏桶一样, 没令牌的话必须得阻塞

优点,令牌的生成速度可以动态修改。

基于统计

统计是一种上面两种算法的实现, 好处的话, 一是代码可以节藕,二是可以仅使用cas锁。

写atomic: 实现方法一般为,每一次调用后的统计纪录到一个滑动窗口内的 atomic变量內。

读无锁: 获取当前窗口的数据作为当前的调用量。

缺点: 会存在实际qps 超过预计 qps(超出非常少的量)

业界现成的限流方案

nginx 限流

  1. 默认的实现是 针对不同sourceIP 以漏桶算法实现。
  2. 支持添加一个标示符 burst, 给超过限流流速的请求存储到一个内存队列。
  3. 支持添加一个标示符 nodelay, 让存储道队列的请求,立即发送到内部处理。

可见,2,3都是为了解决漏桶算法在限速下又能尽快返回的情况。

java 应用级别限流 Sentinel

  1. 底层限流实现基于统计的方式,底层是一个高性能滑动窗口
  2. 基于每次调用后写入窗口的数据,配合插件实现各种限流功能

https://github.com/alibaba/Sentinel/wiki/Sentinel%E5%B7%A5%E4%BD%9C%E4%B8%BB%E6%B5%81%E7%A8%8B

reference

https://legolasng.github.io/2017/08/27/nginx-rate-limiting/

https://colobu.com/2014/11/13/rate-limiting/

https://github.com/farmerjohngit/myblog/issues/18

https://www.nginx.com/blog/rate-limiting-nginx/

avatar

lelouchcr's blog