Guava RateLimiter的限流机制详解

限流是保护高并发系统的三种有效方法之一。另外两个分别是缓存和降级。限流在很多场景中都会使用到限制并发数和请求数。例如,在限时抢购的情况下,限流可以保护您自己的系统和下游系统不被巨大的流量淹没。

限流的目的是通过限制并发访问或请求或者限制指定时间窗口的请求来保护系统。超过阈值后,会触发拒绝服务或流量整形。

常见的限流方法有: 1、限制总并发数。例如,您可以限制数据库连接池和线程池的大小。2.限制瞬时并发数。例如NGINX的limit_conn_module用于限制瞬时并发连接数。Java的Semaphore类可以实现同样的功能。3、限制一个时间窗口的平均访问速率。例如Guava的RateLimiter和NGINX的limit_req模块都可以用来限制每秒的平均访问速率。4. 限制远程API调用速率。5、限制MQ的消耗速率。另外,我们还可以根据网络连接数、网络流量以及CPU或内存负载来实现限流。

例如,如果我们需要限制一个方法同时调用的并发数小于100,我们可以通过Semaphore. 如果我们想将一个方法在一段时间内被调用的平均次数限制在 100 以内,我们需要使用RateLimiter.

节流算法
常用的限流算法有两种:漏桶算法和令牌桶算法。

从上图可以看出,水和访问流量一样,是先进入漏桶的。然后水就会从桶里滴出来,就像我们的系统处理请求的方式一样。当水(访问流量)流入太快时,水桶就会被填满,然后溢出。

漏桶算法的实现通常依赖于队列。如果您的系统收到新的访问请求并且队列未满,则会将该请求放入队列中。处理器从队列中提取请求并以固定频率处理它。如果入站访问请求量过大,队列已满,新的请求将被丢弃。

令牌桶算法的工作原理就像一个存储固定数量令牌的桶,令牌以固定的速率添加到其中。当桶中存储的令牌超过最大数量后,新的令牌将被丢弃或拒绝。当流量或网络请求到达时,每个请求都必须获取令牌。带有令牌的请求会被直接处理,并且每处理一个请求就会从桶中删除一个令牌。未能获取令牌的请求将受到限制:直接丢弃或在缓冲区等待。

令牌桶和漏桶的对比:

令牌以固定速率添加到令牌桶中。请求能否被处理取决于桶中是否有足够的可用令牌。当可用令牌的数量减少到零时,所有新请求都会被拒绝。漏桶以固定速率处理请求。入站请求的速率不受限制,但当入站请求的累计数量超过桶的最大容量时,新的入站请求将被拒绝。
令牌桶限制了平均流入速率,允许流量突然增加。只要有token就可以处理该请求。一次可以给予三到四个令牌。漏桶限制了恒定的流出速率,该流出速率被设置为固定值。例如,如果流出速率设置为每秒一个请求,则每秒无法处理两个请求。这确保了无论流入速率如何,流出速率始终稳定。
令牌桶在一定程度上允许流量突然增加,而漏桶主要用于保证流出速率的平滑。
番石榴速率限制器
Guava是一个优秀的开源Java项目。它包含 Google 在基于 Java 的项目中使用的几个核心库:集合、缓存、并发库、通用注释、字符串处理、I/O 等。

GuavaRateLimiter提供了令牌桶算法的实现:SmoothBursty 和 SmoothWarmingUp。

平滑突发
使用静态方法RateLimiter创建限制器,并将放入桶中的令牌数量设置为5。返回的RateLimiter对象确保每秒以固定速率放入桶中的令牌不超过5个,以平滑流出流量。

RateLimiter采用令牌桶算法,累加令牌。如果令牌消耗频率较低,请求可以直接获取令牌,无需等待。

你可能感兴趣的:(guava)