赞
踩
分布式系统中,由于接口API无法控制上游调用方的行为,因此当瞬时请求量突增时,会导致服务器占用过多资源,发生响应速度降低、超时、乃至宕机,甚至引发雪崩造成整个系统不可用。
限流,Rate Limiting,就是对API的请求量进行限制,对于超出限制部分的请求作出快速拒绝、快速失败、丢弃处理,以保证本服务以及下游资源系统的稳定。
哪些原因会带来瞬时请求量突增?
1,热点业务、突发热点数据带来的激增。例如微博热搜的爆点。
2,上游系统的bug导致。
3,恶意的攻击流量。
实现限流的方法很多,一句话来讲,就是限制每秒钟内API可处理的请求量。常见的有以下几种算法:固定窗口计数法、滑动窗口计数法、漏桶算法、令牌桶算法。
固定窗口计数法的思路是:
固定窗口计数法是最简单、也最直观的限流算法。但在最坏的情况下,会让通过的请求量是限制数量的两倍,例如,假设限制的是每个窗口5个请求:
滑动窗口计数法的思路是:
漏桶算法的思路是:
1,每个请求看作“水滴” 一样,放入漏桶中暂存。
2,漏桶以固定的速率,漏出请求来执行;如果漏桶空了,则停止漏水。3,如果漏桶满了,则新来的请求会被丢弃。
很明显,漏桶算法在实现的数据结构会选择有容量限制的队列,请求执行者定期定点从队列取出请求来执行,新来的请求会被暂存在队列中或者被丢弃。
漏桶算法的缺点是,不论当前系统的负载压力如何,所有请求都得进行排队,即便此时服务器负载处于低位。
令牌桶算法:
1,令牌按固定速率发放,生成的令牌放入令牌桶中。2,令牌桶有容量限制,当桶满时,新生成的令牌会被丢弃。
3,请求到来时,先从令牌桶中获取令牌,如果取得,则执行请求;如果令牌桶为空,则丢弃该请求。
令牌桶算法可以把请求平均分散在时间段内,是使用较为广发的限流算法。
单点应用下,对应用进行限流,既能满足本服务的需求,又可以很好的保护好下游资源。在选型上,可以采用Google Guava的RateLimiter即可。
而在多机部署场景下,对单点的限流,则不能达到最好效果,需要引入分布式限流。分布式限流的算法,依然可以采用令牌桶算法,只不过将令牌桶的发放、存储改为全局的模型。真正实现中,可以采用redis+lua的方式,通过把逻辑放在redis端,来减少调用次数。
lua的逻辑如下:
1,redis中存储剩余令牌的数量cur_token,和上次获取令牌的时间last_time。
2,在每次申请令牌时,可以根据(当前时间cur_time - last_time)的时间差 乘以 令牌发放速率,算出当前可用令牌数。
3,如果有剩余令牌,则准许请求通过;否则不通过。
不论出于什么风险,要保证系统的抗压能力,限流是不可缺少的一个环节。
单点应用场景下,常用的算法有固定窗口计数法、滑动窗口计数法、漏桶法、令牌桶法。分布式场景下,需要将限流算法的存储信息全局化,而为了性能和一致性,需要进行深度优化。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。