限流总结
最近回顾了一下限流的一些方法,这里做一下记录
限流解决的问题
避免过多的流量 进入后端,导致服务不可用。
限流算法总结
漏桶算法
思路: 平均的每隔一段时间释放一个请求。
比如, 现在限速是 每秒 10个请求,那么,在该算法下, 每一个请求之间必须间隔100ms
存在的问题: 比如当前秒同时过来 2个
请求,如果每个
请求耗时 1ms, 再不计算网络耗时的情况下, 那么第一个请求1ms 就能返回, 而第二个请求 必须 101ms 后才能返回。
该算法适合 那种严格限速的场景, 但如果业务上希望既能限速,又能快速返回的场景下就显得不太合适。
令牌桶算法
思路: 抽象了一个桶的概念,每一个请求需要消耗一个令牌,而令牌会按照一定的速度增加。
存在的问题: 同漏桶一样, 没令牌的话必须得阻塞
优点,令牌的生成速度可以动态修改。
基于统计
统计是一种上面两种算法的实现, 好处的话, 一是代码可以节藕,二是可以仅使用cas锁。
写atomic: 实现方法一般为,每一次调用后的统计纪录到一个滑动窗口内的 atomic变量內。
读无锁: 获取当前窗口的数据作为当前的调用量。
缺点: 会存在实际qps 超过预计 qps(超出非常少的量)
业界现成的限流方案
nginx 限流
- 默认的实现是 针对不同sourceIP 以漏桶算法实现。
- 支持添加一个标示符
burst
, 给超过限流流速的请求存储到一个内存队列。 - 支持添加一个标示符
nodelay
, 让存储道队列的请求,立即发送到内部处理。
可见,2,3都是为了解决漏桶算法在限速下又能尽快返回的情况。
java 应用级别限流 Sentinel
- 底层限流实现基于统计的方式,底层是一个高性能滑动窗口
- 基于每次调用后写入窗口的数据,配合插件实现各种限流功能
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/