Java限流——RateLimiter使用

本文深入解析了令牌桶算法的工作原理,包括令牌的生成与消费机制,以及如何通过RateLimiter进行流量控制。通过示例代码展示了如何在Guava库中应用此算法实现请求限流。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

令牌桶算法:

在 Wikipedia 上,令牌桶算法是这么描述的:

  1. 每秒会有 r 个令牌放入桶中,或者说,每过 1/r 秒桶中增加一个令牌
  2. 桶中最多存放 b 个令牌,如果桶满了,新放入的令牌会被丢弃
  3. 当一个 n 字节的数据包到达时,消耗 n 个令牌,然后发送该数据包
  4. 如果桶中可用令牌小于 n,则该数据包将被缓存或丢弃

 RateLimiter已经帮我们封装好了,我们使用就行

jar引入

<dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>23.0</version>
        </dependency>

简单代码(限流之缓存):

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class PoolTest {
    private static RateLimiter rateLimiter;
    @Test
    public void pools(){
        ExecutorService exxc = Executors.newFixedThreadPool(5);
        RateLimiter rateLimiter =RateLimiter.create(1);
        List<Runnable> tasks = new ArrayList<Runnable>();
        for (int i = 0; i < 10; i++) {
            tasks.add(new UserRequest(i));
        }
        for (Runnable runnable : tasks) {
            System.out.println("等待时间:" + rateLimiter.acquire());
            exxc.execute(runnable);
        }
    }
}
class UserRequest implements Runnable {
    private int id;

    public UserRequest(int id) {
        this.id = id;
    }
    public void run() {
        System.out.println(id);
    }
}

 

 

### Java 中实现请求限流的方法和工具 在 Java 中,可以通过多种方法和工具来实现请求限流功能。以下是常见的几种方式及其特点: #### 1. 使用 Guava 的 `RateLimiter` 类 Guava 提供了一个成熟的限流工具——`RateLimiter`,它通过令牌算法实现了速率限制的功能。以下是一个简单的示例代码[^1]: ```java import com.google.common.util.concurrent.RateLimiter; public class TokenBucketDemo { private final RateLimiter rateLimiter = RateLimiter.create(10); // 每秒最多发放10个令牌 public void doRequest() { if (rateLimiter.tryAcquire()) { // 尝试获取一个令牌 System.out.println("正常处理请求"); } else { System.out.println("限流"); } } public static void main(String[] args) throws InterruptedException { TokenBucketDemo tokenBucketDemo = new TokenBucketDemo(); for (int i = 0; i < 20; i++) { Thread.sleep(1000); tokenBucketDemo.doRequest(); } } } ``` 上述代码展示了如何利用 `RateLimiter` 来控制每秒钟的最大请求数量。需要注意的是,该工具适用于单机环境下的限流场景[^3]。 为了引入 Guava 库,可以在项目的 Maven 配置文件中添加如下依赖项[^4]: ```xml <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>31.0.1-jre</version> </dependency> ``` --- #### 2. 基于 Redis 实现分布式限流 对于分布式系统而言,仅依靠单机版的 `RateLimiter` 是不够的。可以借助 Redis 这样的内存数据库来实现跨节点的限流逻辑。常用的算法有滑动窗口计数器、漏算法以及令牌算法等。 以下是一段基于 Redis 和令牌算法的伪代码示例: ```java import redis.clients.jedis.Jedis; public class DistributedRateLimiter { private Jedis jedis; private String keyPrefix = "ratelimit:"; public boolean tryAcquire(String resource, int maxTokensPerSecond) { String key = keyPrefix + resource; long currentTimeMillis = System.currentTimeMillis(); double tokensAvailable = jedis.get(key); // 获取当前剩余令牌数量 if (tokensAvailable >= 1) { jedis.decrByFloat(key, 1); // 减少一个令牌 return true; } else { return false; } } } ``` 此方案能够很好地支持高并发访问,并且具备良好的扩展性和性能表现[^2]。 --- #### 3. Spring Cloud Gateway 内置限流组件 如果项目采用了微服务架构并集成了 Spring Cloud,则可以直接使用其内置的支持模块完成 API 层面的流量管理任务。例如,在网关层配置 Nacos 或者 Sentinel 插件即可轻松达成目标。 具体操作步骤可参考官方文档说明链接地址待补充。 --- ### 总结 综上所述,针对不同规模的应用程序可以选择合适的策略来进行有效的资源保护措施。如果是小型应用或者内部调用的话,那么采用本地化的解决方案会更加简便高效;而当面对复杂的生产环境下多实例部署的需求时,则应该考虑结合外部存储介质如Redis构建全局一致性的防护机制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值