说说限流那些事

限流就是限制流量。原来是物理名词。限流是通过限流电阻使得电路中的某一段电流不超过一个上限。


后面限流使用到多个场景,道路限流、接口限流、景区限流等。直观理解,就是控制流量,那么其它流量如何处理呢?常见的处理方式就是拒绝请求。比如道路限流,超过限流值的车辆就不允许上路;接口限流,超过限流值的请求就直接丢弃返回失败;景区限流,超过限流值的人就阻挡在景区外。


一般来说,限流更为关注如何限制流量,至于超过限流的处理方式一般不在限流范围内讨论。基本上可以根据具体业务选择丢弃或者降级处理。


一个雪崩的问题产生

一个生产推送系统,除了正向的推送外,超过一定员工数量的组织变无法全员推达,涉及到一个写扩散的问题,即一次无法推达所有用户,此时需要有另外的策略来实现数据推送。


写扩散,即通过写入的方式将数据存储到用户的存储空间中,不再依赖服务提供方的数据。比如邮箱就是一种写扩散的模式,公司老板给全员写了一封邮件,全员每个人的收件箱都会收到一封信,无论老板或者其他员工对信件如何处理,不影响用户自己的信件数据。


那么问题来了,写扩散对于任何系统来说都有一个上限,如果一封邮件同时发给100万的员工,相信哪个系统也顶不住。对于邮箱来说,可以做一些异步的优化。但是对于实际推送系统来说,往往还依赖很多的系统,比如100万的用户名就不大可能能查出来。


那么这里可以使用一个非常常见也经典的模式,就是推拉结合。那就是利用用户客户端上线等时机来调用服务端数据增量计算,然后下发到客户端。


开始跑的正常,但是突然某一天业务量暴涨,系统就崩溃了,正向推送成功率极具下跌

说说限流那些事


问题排查

开始排查成功率为什么会抖动如此严重,从表象上来看,是推送依赖的取数据接口大量限流或者超时。和底层系统同学沟通,流量无法继续扩大,否则会影响其他正常核心调用。

那么根本问题再哪里,是因为总体流量上涨,导致超过取数依赖的接口吗?至少表象看起来是这样的。流量也确实翻倍了,但是真正的根源是哪里呢?


说说限流那些事


正向接口确实也翻倍了。但是这个是引起对取数流量剧增的原因吗? 想知道到底为何,就必须对下游取数的接口做分析,分析每个场景对取数调用接口的比例,经过打点观察,惊人的发现,客户端上线的调用量居然占用了60%以上的取数接口,也就是说,而且当时客户端上线上涨了N倍。N倍的调用量占据了取数接口的主要调用,进而引起取数接口限流,进而导致正向流量受影响,正向受影响后又依赖客户端上线来恢复数据,形成了一个恶性循环。


问题解决

正常情况下,不需要依赖客户端上线来恢复数据,只有员工数超大的情况下需要,因此需要对客户端上线取数做校验,普通的员工数不做任何处理,另外增加限流逻辑,严控客户端上线的请求量,防止高峰和毛刺压垮数据源。上线后,发现实际效果良好,正向推送接口成功率基本100%。


限流问题思考

限流是对无法承受外部压力的自我保护最简单的一个措施。限流也是有技巧的,是否需要限流、限流值多少、对谁限流等是几个非常重要的TOPIC。


毛主席说过,革命的首要问题,就是识别谁是敌人,谁是朋友。


限流三要素


对于系统来说,也是一样,要识别关键调用方,一般来说一个接口80%的能力是被20%的业务调用了,只要识别出这个20%,并对20%的业务方做限流处理,即可达到系统自我保护。限流了一个调用量1%的接口,哪怕限流到0了,依然避免不了系统风险。


因此,识别核心调用接口,是设置限流的首要问题


仅仅是限流吗?不是的,强行限流,系统是保护了,那对业务的影响是什么,是否导致核心用户不可用了?因此需要对限流造成的影响做评估。评估限流会导致何种问题,是导致用户侧失败,还是导致异步接口处理延时,是否需要被调用方降级处理?


因此,评估限流影响,是设置限流的第二个问题


影响也评估了,那么剩下了唯一一个问题,就是限流值该如何设置的问题了。设置低了,天天限流告警无法提供正常服务;限流高了,还没命中限流值,系统已经崩溃了。那么如何设置最佳的限流值?答案是:经验水位+压测。

经验水位是指按照往常的调用的最高峰,设置阈值,防止突然的流量突增导致系统过载。另外要结合的就是压测,压测系统的最佳水位值。根据经验水位+压测报告,可以得出限流值。


因此,经验水位+压测,是设置限流值的最佳实践


限流方法

常用的限流有计数法和桶法。”计数”又有:固定计数法、滑动窗口计数法,“桶”:漏桶算法、令牌桶算法。这里简单介绍一下每个限流方法的原理。

固定计数法

统计1秒内的请求数,超过了指定阈值则丢弃请求,1s后清零处理。这种方法缺点很明显,就是秒级统计单位,毫秒级别如果超过限流值了,则1秒内都是拒绝请求的,存在极大的资源浪费。


说说限流那些事


滑动窗口计数法

相对固定计数法来说,滑动窗口把1秒分成了若干小分段,比如200毫秒一段,统计某个时间点的限流值是把当前1秒内的小窗流量全部相加。


说说限流那些事

漏痛算法

漏桶算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水,当水流入速度过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。


说说限流那些事


漏桶算法具体实现见文章:https://www.ctolib.com/topics-134605.html


关于漏桶算法做个解释,漏桶算法的一个缺点,就是出水速度是被强行限制的,也就是说,外部流量被桶的容量限制,放行流量是均匀的,比如漏水速度控制在10qps,那么不管底层系统提供的能力是多少,调用值会限定在10qps。


令牌桶算法

令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。


说说限流那些事


Google开源工具包Guava提供了限流工具类RateLimiter,该类基于令牌桶算法来完成限流,非常易于使用。RateLimiter类的接口描述请参考:RateLimiter接口描述,具体使用请参考:RateLimiter使用实践。具体教程参考:https://www.baeldung.com/guava-rate-limiter


说说限流那些事


相对漏桶算法来说,是在桶容量前提下,保持固定的调用速率,而令牌桶则允许在桶容量前提下,可以任意的调用速率。因此令牌桶的实际适用更好一些。


总结


限流是保护系统的一个非常直接的办法。阿里开源的setinel是一个非常好的限流项目,项目地址:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D

sentinel的具体限流核心算法,我们将在另外一篇文章进行分析,读读阿里巴巴优雅的代码设计。


分享到:


相關文章: