【如何】guava的RateLimiter使用

简介: 【如何】guava的RateLimiter使用

为什么要限流


在调用一些第三方的接口时,他们会有一些调用频率的限制,比如每秒不能超过多少次,这种时候,就需要用到限流的工具。


定义


还是给一个定义出来:


在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流


  • 缓存 缓存的目的是提升系统访问速度和增大系统处理容量


  • 降级 降级是当服务出现问题或者影响到核心流程时,需要暂时屏蔽掉,待高峰或者问题解决后再打开


  • 限流 限流的目的是通过对并发访问/请求进行限速,或者对一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理


如何限流


傻瓜方案


因为我们需要限流的地方是对第三方调用的时候,我们是在循环里调用的第三方,所以,简单粗暴的Thread.sleep(500) 其实也可以用。


正式方案


Guava的RateLimiter算是比较方便的限流工具。


Guava RateLimiter基于令牌桶算法,我们只需要告诉RateLimiter系统限制的QPS是多少,那么RateLimiter将以这个速度往桶里面放入令牌,然后请求的时候,通过acquire()方法向RateLimiter获取许可(令牌)。


来个例子


public static void main(String[] args) {
        // qps设置为2,代表一秒钟只允许处理2个并发请求
        RateLimiter rateLimiter = RateLimiter.create(2);
        StopWatch sw=new StopWatch();
        sw.start();
        int nTasks = 10;
        for (int i = 0; i < nTasks; i++) {
            rateLimiter.acquire(1);
            sw.split();
            System.out.println("job id is "+i+"sw: "+sw.getSplitTime());
            //sw.shortSummary();
        }
        sw.stop();
        System.out.println("finish,total time is "+sw.getTime());
    }


输出是这样的:


job id is 0sw: 0
job id is 1sw: 497
job id is 2sw: 998
job id is 3sw: 1499
job id is 4sw: 2002
job id is 5sw: 2498
job id is 6sw: 2997
job id is 7sw: 3497
job id is 8sw: 3998
job id is 9sw: 4502
finish,total time is 4502


注意


有一点需要注意,RateLimiter的这个令牌是会累积的,也就是说,就算令牌不使用,也会积攒下来,当需要使用的时候,一股脑的给出去。


RateLimiter rateLimiter = RateLimiter.create(2);
//追一下代码
    public static RateLimiter create(double permitsPerSecond) {
        return create(permitsPerSecond, RateLimiter.SleepingStopwatch.createFromSystemTimer());
    }
    @VisibleForTesting
    static RateLimiter create(double permitsPerSecond, RateLimiter.SleepingStopwatch stopwatch) {
        RateLimiter rateLimiter = new SmoothBursty(stopwatch, 1.0D);
        rateLimiter.setRate(permitsPerSecond);
        return rateLimiter;
    }


可以看到,默认情况下,最多累积1s钟的令牌。


测试一下,代码:


    @SneakyThrows
    public static void main(String[] args) {
        // qps设置为2,代表一秒钟只允许处理2个并发请求
        RateLimiter rateLimiter = RateLimiter.create(2);
        StopWatch sw=new StopWatch();
        sw.start();
        int nTasks = 10;
        Thread.sleep(3000);
        for (int i = 0; i < nTasks; i++) {
            rateLimiter.acquire(1);
            sw.split();
            System.out.println("job id is "+i+"sw: "+sw.getSplitTime());
            //sw.shortSummary();
        }
        sw.stop();
        System.out.println("finish,total time is "+sw.getTime());
    }


结果:


job id is 0sw: 3009
job id is 1sw: 3010
job id is 2sw: 3010
job id is 3sw: 3509
job id is 4sw: 4009
job id is 5sw: 4510
job id is 6sw: 5008
job id is 7sw: 5506
job id is 8sw: 6007
job id is 9sw: 6508
finish,total time is 6508


如果你想多累积几秒,那么创建的时候应该是:


        RateLimiter rateLimiter = RateLimiter.create(2);
        rateLimiter.setRate(3D);


高并发之API接口限流

相关文章
|
监控 算法
探秘Guava的RateLimiter:单机流量控制的黄金法宝
探秘Guava的RateLimiter:单机流量控制的黄金法宝
828 0
|
Java 测试技术 容器
SpringBoot单元测试报空指针异常解决方案
java.lang.NullPointerException空指针异常 1.测试类中产生空指针异常,可能不是你的逻辑代码写错了,而是因为获取容器失败,即没有使用正确的测试方法 2.在SpringBoot项目中我们一般可以使用两种Junit进行测试,在导入@Test包时,会出现两个选项
2013 0
SpringBoot单元测试报空指针异常解决方案
|
8月前
|
SQL Java 数据库连接
持久层框架MyBatisPlus
MyBatisPlus是MyBatis的增强工具,简化单表CRUD操作,通过继承BaseMapper即可实现增删改查。支持条件构造器、分页插件、代码生成等功能,提升开发效率,广泛应用于企业级项目中。
 持久层框架MyBatisPlus
|
机器学习/深度学习 人工智能 IDE
《全球机器学习技术大会:阿里云张玉明解密通义灵码AI程序员》
4月18日至19日,2025全球机器学习技术大会(ML-Summit)在上海成功举办。大会聚焦人工智能与机器学习前沿技术,吸引了众多行业精英参与。阿里巴巴高级技术专家张玉明以“通义灵码 AI 程序员解密”为主题发表演讲,分享了AI辅助编程工具如何重塑软件开发范式。通义灵码通过大模型和Agent技术,实现从辅助编码到对话式编程的跨越,未来将进入AI自主编程阶段。张玉明还介绍了通义灵码的核心技术架构及典型应用场景,并展望了智能编程的未来发展。
|
11月前
|
机器学习/深度学习 算法
Proximal SFT:用PPO强化学习机制优化SFT,让大模型训练更稳定
本文介绍了一种改进的监督微调方法——Proximal Supervised Fine-Tuning (PSFT),旨在解决传统SFT易过拟合、泛化能力差及导致“熵坍塌”的问题。受PPO强化学习算法启发,PSFT通过引入参数更新的稳定性机制,防止模型在训练中变得过于确定,从而提升探索能力与后续强化学习阶段的表现。实验表明,PSFT在数学推理、模型对齐及泛化能力方面均优于传统SFT。
1001 3
Proximal SFT:用PPO强化学习机制优化SFT,让大模型训练更稳定
|
Java Maven Spring
SpringBoot日志整合
SpringBoot日志整合
469 2
|
开发工具 git
成功解决 IDEA 2020 版本 代码报错不提示的几种方案
这篇文章提供了几种解决IntelliJ IDEA 2020版本中代码报错不提示问题的方案,包括通过修改文件夹权限、暂存本地更改后进行git pull,以及在git pull后应用暂存的更改并提交代码到远程仓库的方法。
|
消息中间件 算法 Java
一文详解 Java 限流接口实现
本文介绍的实现方式属于应用级限制,应用级限流方式只是单应用内的请求限流,不能进行全局限流。要保证系统的抗压能力,限流是一个必不可少的环节,虽然可能会造成某些用户的请求被丢弃,但相比于突发流量造成的系统宕机来说,这些损失一般都在可以接受的范围之内。
一文详解 Java 限流接口实现
|
监控 安全 算法
提升编程效率的利器: 解析Google Guava库之RateLimiter优雅限流(十)
提升编程效率的利器: 解析Google Guava库之RateLimiter优雅限流(十)
|
Java Spring
Spring的@Retryable实现方法重试
`@Retryable`注解用于配置异常重试,参数包括:指定异常类型`value`,额外包含异常`include`,排除异常`exclude`,最大尝试次数`maxAttempts`和回退策略`backoff`。可选地,可以用`retryExceptions`列表替换`value`。当重试失败,可使用`@Recover`注解定义恢复逻辑。
461 1

热门文章

最新文章