Guava的RateLimiter在单机限流中的正确用法

错误使用

在实现限流时,网上的各种文章基本都会提到Guava的RateLimiter,用于实现单机的限流,并给出类似的代码:

public void method() {
    RateLimiter rateLimiter = RateLimiter.create(10);
    if(rateLimiter.tryAcquire()){
        // do business
        ......
    }
}

可是上面的代码真的能限流吗?

首先,从代码逻辑角度来讲,方法在每次被调用是都new一个RateLimiter,不同请求之间毫无关联,怎么能起到限流的作用呢?

其次,经过本人实际验证,上面的方法运行结果表明,根本没有限流的作用。

正确使用

在SpringMVC项目中,controller、service等对应的bean都是单例,因此将RateLimiter作为bean的属性并初始化,再加上RateLimiter的注释中表示RateLimiter是并发安全的:

RateLimiter is safe for concurrent use: It will restrict the total rate of calls from all threads. Note, however, that it does not guarantee fairness.

因此,正确的写法如下:

private RateLimiter rateLimiter = RateLimiter.create(10);

public void method() {
    if(rateLimiter.tryAcquire()){
        // do business
        ......
    }
}

转载于:https://www.cnblogs.com/acode/p/9260068.html

### 使用 RateLimiter 进行限流控制 Google 开源工具包 Guava 提供了 `RateLimiter` 类来实现限流功能,该类基于“令牌桶算法”。通过这种方式可以有效地限制应用程序请求的速度。 #### 创建并配置 RateLimiter 实例 为了创建一个每秒发放指定数量许可的速率控制器实例: ```java // 创建一个新的 RateLimiter,它将以每秒 5 个许可证的速度发放 RateLimiter rateLimiter = RateLimiter.create(5.0); ``` 此代码片段定义了一个新的 `RateLimiter` 对象,其设置为每秒钟最多处理五个请求[^4]。 #### 控制访问频率 当需要确保某些操作不会超过设定的最大速率时,可以在执行这些操作之前调用 `tryAcquire()` 方法检查是否有足够的可用资源(即令牌)。如果有足够多的令牌,则返回 true 并减少相应的计数;否则返回 false 表明当前无法获取更多令牌。 ```java if (rateLimiter.tryAcquire()) { // 执行受保护的操作... } else { // 处理被拒绝的情况... } ``` 这段逻辑展示了如何安全地尝试获得一次性的权限去完成特定的任务。如果没有成功得到授权,则可以选择等待一段时间再重试或者直接放弃此次请求[^3]。 对于更复杂的场景,比如希望在一定时间内累积多个令牌以便一次性消耗掉它们,还可以传递参数给 `tryAcquire(int permits)` 来指定期望获取的数量以及最大允许等待的时间间隔 `tryAcquire(long timeout, TimeUnit unit)`。 #### 应用于实际项目中的建议 考虑到 `RateLimiter` 主要针对单机环境下的流量管理,在分布式系统里可能还需要借助 Redis 或者 Sentinel 等外部组件来进行全局范围内的协调工作[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值