一、应用背景
在当前微服务的大环境下,大部分的服务一般都是通过接入分布式限流框架来实现限流、熔断、降级,但大型的分布式框架有时显得过于”重量”,在一些小型系统或单机Demo级别的应用开发中,其实可以考虑单机型的限流框架,例如今天的主角——RateLimiter。
RateLimiter是Google Guava下的一款单机轻量级别的小框架、小工具。
二、算法介绍
一般聊到限流算法,最常见的莫过于两种:漏桶算法和令牌桶算法
-
漏桶算法:也就是有一个桶,底部有一个小洞,当有水不断地从上面加入进来时,底部出水的速率都是一样的,当加水速度持续大于漏水速度时,就会有一个时刻,桶满了,此时就不再允许往桶里加水了(再加就溢出来了)。
特点:不管上面加水快还是加水慢,漏水速率会一致保持不变
-
令牌桶算法:有一个桶,有人以一定的速率一直往里面放令牌,所以被叫做令牌桶,此时如果有人需要这个令牌了,就会从桶里拿一个,如果又来人了就会又被拿一个,拿到了令牌的人就可以进站了,没有拿到的人就要在外面等。
特点:令牌桶算法只固定了放令牌的速度,而不会限制拿令牌的人,拿的人有就能拿到,没有就拿不到了,所以令牌桶有个优点就是可以有一定的峰值,一次性发很多令牌(如果有的话)
三、应用实践
-
RateLimiter使用的就是令牌桶算法
-
常用API介绍
- RateLimiter.create(permitsPerSecond):设置当前接口的QPS
- rateLimiter.tryAcquire(timeout, timeUnit):尝试在一定时间内获取令牌,超时则退出
-
代码实践
-
工具类封装
public class GuavaRateLimiterUtils { private final static GuavaRateLimiterUtils INSTANCE = new GuavaRateLimiterUtils(); private ConcurrentHashMap<String, RateLimiter> RATE_LIMITER_MAP = new ConcurrentHashMap<>(); private GuavaRateLimiterUtils() { } /** * 单例 * @return 返回单例对象 */ public static GuavaRateLimiterUtils getInstance() { return INSTANCE; } /** * 设置限流值 * @param path 请求路径 * @param permitsPerSecond 一秒内的限流数 */ public void setPermits(String path, Double permitsPerSecond) { if (<
-