限流算法
并发数限流
- 计数器并发数限流:使用共享变量实现
- 信号量:使用java中的Semaphore
QPS限流
- 计数器法:实现简单,精度不高,重置节点时无法处理突发请求
- 滑动窗口:滑动窗口的窗口越小,则精度越高,相应的资源消耗也更高。
- 漏桶算法 : 限制的是流出速率,突发请求要排队,对服务保护较好;流入随机,流出固定
- 令牌桶算法 :限制的是平均流入速率,允许一定程度突发请求(无需排队)。
限流方法对比
计数器 VS 滑动窗口
计数器算法是最简单的算法,可以看成是滑动窗口的低精度实现。滑动窗口由于需要存储多份的计数器(每一个格子存一份),所以滑动窗口在实现上需要更多的存储空间。也就是说,如果滑动窗口的精度越高,需要的存储空间就越大。
令牌桶和漏桶对比:
- 令牌桶是按照固定速率往桶中添加令牌,请求是否被处理需要看桶中令牌是否足够,当令牌数减为零时则拒绝新的请求;漏桶则是按照常量固定速率流出请求,流入请求速率任意,当流入的请求数累积到漏桶容量时,则新流入的请求被拒绝;
- 令牌桶限制的是平均流入速率,允许一定的突发请求;而漏桶主要目的是平滑流出速率;
限流降级实现
redis
Guava RateLimiter
Hystrix
Sentinel
- 并发数/线程数:
共享变量:不同版本用了不同实现
- v1.6实现:
private AtomicInteger curThreadNum = new AtomicInteger(0);
- v1.7实现:
private LongAdder curThreadNum = new LongAdder();
- QPS限流/降级:
滑动窗口:Sentinel 底层采用高性能的滑动窗口数据结构来统计实时的秒级指标数据。
最大不同点:
Hystrix通过不同业务逻辑使用不同线程池来隔离业务自身之间的资源争抢(线程池隔离)。这种隔离方案虽然隔离性比较好,但是代价就是线程数目太多,线程上下文切换的 overhead 比较大,特别是对低延时的调用有比较大的影响。Sentinel 并发线程数限流不负责创建和管理线程池,而是简单统计当前请求上下文的线程数目,如果超出阈值,新的请求会被立即拒绝,效果类似于信号量隔离。
动态配置支持:
Hystrix只提供了配置修改的入口,没有将配置界面化,如果想在页面上动态调整配置,还需要自己实现。
网友评论