前言
当前负责一个社区项目的开发,所以总结一下当前项目的一些缺失的功能点。其中有一个便是限流,限流主要是通过对并发访问/请求进行限制或者一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务或者排队等待。
为什么需要限流
按照服务的调用方,可以分为以下几种类型服务
1.与用户打交道的服务
比如web服务、对外API,这种类型的服务有以下几种可能导致机器被拖垮:
用户增长过快(这是好事)
因为某个热点事件(微博热搜)
竞争对象爬虫
恶意的刷单
这些情况都是无法预知的,不知道什么时候会有10倍甚至20倍的流量打进来,如果真碰上这种情况,扩容是根本来不及的。
2.对内的RPC服务
一个服务A的接口可能被BCDE多个服务进行调用,在B服务发生突发流量时,直接把A服务给调用挂了,导致A服务对CDE也无法提供服务。
这种情况时有发生,解决方案有两种:
1、每个调用方采用线程池进行资源隔离
2、使用限流手段对每个调用方进行限流
限流算法实现
常见的限流算法有:计数器算法、漏桶算法、令牌桶算法等。
1.计数器算法
图片.png计数器算法主要是通过统计一段时间内的请求次数,当达到上限之后,剩下的请求则被丢弃或者做其他处理,当周期结束时则计数清零。例如:限制一分钟内请求次数60次,则在一分钟之内,每次请求,计数加一,当计数达到60之后的请求做其他处理。一分钟之后计数清零。
计数器算法的实现比较简单,但这个算法有时会让通过请求量允许为限制的两倍。就说上面那个列子,假如在第一个一分钟的最后1秒收到了60个请求,之后计数清零,下一个一分钟的第一秒又收到了60个请求,这样看来就是在 2 秒中收到了120个请求。
2.漏桶算法
图片.png漏桶算法这个名字就很形象,算法内部有一个容器,类似生活用到的漏斗,当请求进来时,相当于水倒入漏斗,然后从下端小口慢慢匀速的流出。不管上面流量多大,下面流出的速度始终保持不变。不管服务调用方多么不稳定,通过漏桶算法进行限流,每10毫秒处理一次请求。因为处理的速度是固定的,请求进来的速度是未知的,可能突然进来很多请求,没来得及处理的请求就先放在桶里,既然是个桶,肯定是有容量上限,如果桶满了,那么新进来的请求就丢弃。
在算法实现方面,可以准备一个队列,用来保存请求,另外通过一个线程池来定期从队列中获取请求并执行,可以一次性获取多个并发执行。
漏桶算法的缺陷也很明显,当短时间内有大量的突发请求时,即便此时服务器没有任何负载,每个请求也都得在队列中等待一段时间才能被响应。
3.令牌桶算法
图片.png令牌桶算法和漏桶算法效果一样但方向相反的算法。系统会按固定的时间往桶里面添加令牌,如果桶已经满了就不再加。新请求来临时,会各自拿走一个令牌,如果没有令牌可拿了就阻塞或者做其他处理。这样即使短时间内突然访问量增加,也会在令牌用完之后才会做其他处理。
令牌桶算法既能够将所有的请求平均分布到时间区间内,又能接受服务器能够承受范围内的突发请求,因此是目前使用较为广泛的一种限流算法。
4.简单实现
当前的社区项目有redis,简单点实现,例如限制1秒请求1000次,则可以通过redis的incr命令,key则为当前的时间(到秒),计算一秒内的请求次数,当value大于1000时,其余的请求丢弃。
网友评论