限流保护
限流的目的是保护系统不被大量请求冲垮,通过限制请求的速度来保护系统。在电商的秒杀活动中,限流是必不可少的一个环节。
计数器
比较简单的限流做法是维护一个单位时间内的计数器,每次允许请求计数器都加1,当单位时间内计数器累加到设定的阈值后,之后的请求都被拒绝,直到超过单位时间,再将计数器重置为零。此方式有一个弊端:如果在单位时间1s内允许100个请求,10ms已经通过了100个请求,那后面的990ms只能拒绝请求,我们把这种现象称为“突刺现象”。常用的更平滑的限流算法有两种:漏桶算法和令牌桶算法。
漏桶算法
漏桶算法的思路很简单,水(请求)先进入漏桶里,漏桶以一定的速度出水(接口有响应速度),当水流入的速度过大时(访问频率超过接口响应速度)会直接溢出,然后就拒绝请求。如下图所示,可以看出漏桶算法能强行限制数据的传输速度。因为漏桶的漏出速度是固定的,所以,即使网络中不存在资源冲突(没有发生拥塞),漏桶算法也不能增大流量。因此,漏桶算法对于存在突发特性的流量来说缺乏效率。
令牌桶算法
令牌桶算法和漏桶算法效果相似,令牌桶算法更加容易理解。随着时间的流逝,系统会按恒定的1/QPS时间间隔(如果QPS=100,则间隔是10ms)往桶里加入令牌(就像有个水龙头在不断地加水),如果桶已经满了就不再加了。新请求来临时,会拿走一个令牌,如果没有令牌可拿了,就阻塞或者拒绝请求,如下图所示。
令牌桶算法的另外一个好处是可以方便地改变速度。一旦需要提高速度,则按需提高放入桶中的令牌的速度即可。一般会定时(比如100ms)往桶中增加一定数量的令牌,有些变种算法则实时地计算应该增加的令牌的数量。
限流实现
Guava限流器RateLimiter是基于令牌桶算法实现的一个多线程限流器,它可以均匀地处理请求,当然它并不是一个分布式限流器,只是对单机进行限流。它可以定时拉取接口数据,下面是一个简单的限流功能的实例。
首选引入Maven依赖:
然后使用Guava限流,Java代码实现如下:
本文就是愿天堂没有BUG给大家分享的内容,大家有收获的话可以分享下,想学习更多的话可以到微信公众号里找我,我等你哦。