Guava RateLimiter限流器使用示例
Guava中的RateLimiter可以限制单进程中某个方法的速率,本文主要介绍如何使用,实现原理请参考文档:推荐:超详细的Guava RateLimiter限流原理解析和推荐:RateLimiter 源码分析(Guava 和 Sentinel 实现)。
1 基于spring-mvc的controller测试限流
完整代码可参考:https://github.com/sxpujs/spring-cloud-examples/tree/master/rest-service
1.1 增加Maven依赖:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
1.2 AccessLimitService 限流Service类
@Service
public class AccessLimitService {
// 每秒发出5个令牌
RateLimiter rateLimiter = RateLimiter.create(5.0);
/**
* 尝试获取令牌
*/
public boolean tryAcquire() {
return rateLimiter.tryAcquire();
}
}
1.3 控制器类
@RestController
@Slf4j
public class HelloController {
@Autowired
private AccessLimitService accessLimitService;
@RequestMapping("/access")
public String access() {
if (accessLimitService.tryAcquire()) {
log.info("start");
// 模拟业务执行500毫秒
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "access success [" + LocalDateTime.now() + "]";
} else {
//log.warn("限流");
return "access limit [" + LocalDateTime.now() + "]";
}
}
}
1.4 使用wrk工具模拟客户端发起多个请求
我们使用HTTP基准工具wrk来生成大量HTTP请求。在终端输入如下命令来测试:
wrk -t1 -c10 -d2s http://127.0.0.1:8080/access
服务端日志如下所示(稍做简化),可以看出前6行的执行时间是一样的,这是因为RateLimiter的默认实现SmoothBursty会缓存1秒的许可,在定义RateLimiter实例时,每秒5个许可,加上新占用的1个许可,一共有6个。从第7行开始,每0.2秒执行1次,符合预期。
2020-07-05 15:46:16.605 INFO --- [nio-8080-exec-2] HelloController : start
2020-07-05 15:46:16.605 INFO --- [nio-8080-exec-3] HelloController : start
2020-07-05 15:46:16.605 INFO --- [nio-8080-exec-7] HelloController : start
2020-07-05 15:46:16.605 INFO --- [nio-8080-exec-8] HelloController : start
2020-07-05 15:46:16.605 INFO --- [nio-8080-exec-9] HelloController : start
2020-07-05 15:46:16.605 INFO --- [nio-8080-exec-4] HelloController : start
2020-07-05 15:46:16.804 INFO --- [nio-8080-exec-1] HelloController : start
2020-07-05 15:46:17.005 INFO --- [io-8080-exec-11] HelloController : start
2020-07-05 15:46:17.204 INFO --- [nio-8080-exec-9] HelloController : start
2020-07-05 15:46:17.404 INFO --- [nio-8080-exec-5] HelloController : start
2020-07-05 15:46:17.604 INFO --- [nio-8080-exec-8] HelloController : start
2020-07-05 15:46:17.804 INFO --- [nio-8080-exec-2] HelloController : start
2020-07-05 15:46:18.004 INFO --- [nio-8080-exec-7] HelloController : start
2020-07-05 15:46:18.204 INFO --- [nio-8080-exec-6] HelloController : start
2020-07-05 15:46:18.404 INFO --- [nio-8080-exec-5] HelloController : start
2 基于单个类的main方法测试限流
package com.demo.guava;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;
@Slf4j
public class RateLimiterDemo {
static void submitTasks1() {
ExecutorService pool = Executors.newFixedThreadPool(10);
RateLimiter rateLimiter = RateLimiter.create(5); // rate is "5 permits per second"
IntStream.range(0, 10).forEach(i -> pool.submit(() -> {
if (rateLimiter.tryAcquire()) {
try {
log.info("start");
Thread.sleep(500);
} catch (InterruptedException e) {
}
} else {
log.warn("限流");
}
}));
pool.shutdown();
/*
16:18:18.784 [pool-1-thread-1] INFO RateLimiterDemo - start
16:18:18.784 [pool-1-thread-7] WARN RateLimiterDemo - 限流
16:18:18.784 [pool-1-thread-2] WARN RateLimiterDemo - 限流
16:18:18.784 [pool-1-thread-4] WARN RateLimiterDemo - 限流
16:18:18.784 [pool-1-thread-5] WARN RateLimiterDemo - 限流
16:18:18.784 [pool-1-thread-6] WARN RateLimiterDemo - 限流
16:18:18.784 [pool-1-thread-9] WARN RateLimiterDemo - 限流
16:18:18.784 [pool-1-thread-3] WARN RateLimiterDemo - 限流
16:18:18.784 [pool-1-thread-10] WARN RateLimiterDemo - 限流
16:18:18.784 [pool-1-thread-8] WARN RateLimiterDemo - 限流
*/
}
static void submitTasks2() {
ExecutorService pool = Executors.newFixedThreadPool(10);
RateLimiter rateLimiter = RateLimiter.create(5); // rate is "5 permits per second"
IntStream.range(0, 10).forEach(i -> pool.submit(() -> {
rateLimiter.acquire();
log.info("start");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
pool.shutdown();
/*
16:18:56.030 [pool-1-thread-1] INFO RateLimiterDemo - start
16:18:56.227 [pool-1-thread-10] INFO RateLimiterDemo - start
16:18:56.428 [pool-1-thread-9] INFO RateLimiterDemo - start
16:18:56.627 [pool-1-thread-8] INFO RateLimiterDemo - start
16:18:56.827 [pool-1-thread-7] INFO RateLimiterDemo - start
16:18:57.028 [pool-1-thread-6] INFO RateLimiterDemo - start
16:18:57.226 [pool-1-thread-5] INFO RateLimiterDemo - start
16:18:57.426 [pool-1-thread-4] INFO RateLimiterDemo - start
16:18:57.629 [pool-1-thread-3] INFO RateLimiterDemo - start
16:18:57.826 [pool-1-thread-2] INFO RateLimiterDemo - start
*/
}
static void submitTasks3() {
RateLimiter r = RateLimiter.create(5);
log.info("start");
for (;;) {
log.info("get 1 tokens: " + r.acquire() + "s");
}
/*
16:15:46.310 [main] INFO RateLimiterDemo - start
16:15:46.315 [main] INFO RateLimiterDemo - get 1 tokens: 0.0s
16:15:46.513 [main] INFO RateLimiterDemo - get 1 tokens: 0.193752s
16:15:46.709 [main] INFO RateLimiterDemo - get 1 tokens: 0.194875s
16:15:46.911 [main] INFO RateLimiterDemo - get 1 tokens: 0.199033s
16:15:47.113 [main] INFO RateLimiterDemo - get 1 tokens: 0.197833s
16:15:47.312 [main] INFO RateLimiterDemo - get 1 tokens: 0.195898s
*/
}
static void submitTasks4() {
RateLimiter r = RateLimiter.create(5);
log.info("start");
for (;;) {
if (r.tryAcquire()) {
log.info("run");
}
}
/*
16:17:17.098 [main] INFO RateLimiterDemo - start
16:17:17.100 [main] INFO RateLimiterDemo - run
16:17:17.296 [main] INFO RateLimiterDemo - run
16:17:17.496 [main] INFO RateLimiterDemo - run
16:17:17.696 [main] INFO RateLimiterDemo - run
*/
}
public static void main(String[] args) throws InterruptedException {
//submitTasks1();
submitTasks2();
//submitTasks3();
//submitTasks4();
}
}
参考文档:
- 官方API:Class RateLimiter
- Baeldung: Quick Guide to the Guava RateLimiter
- Guava-RateLimiter详解
- 并发编程网:Guava官方文档-RateLimiter类
- 推荐:超详细的Guava RateLimiter限流原理解析
- 推荐:RateLimiter 源码分析(Guava 和 Sentinel 实现)
- 阿里巴巴Sentinel框架
Guava RateLimiter限流器使用示例的更多相关文章
- ☕【Java技术指南】「并发编程专题」针对于Guava RateLimiter限流器的入门到精通(含实战开发技巧)
并发编程的三剑客 在开发高并发系统时有三剑客:缓存.降级和限流. 缓存 缓存的目的是提升系统访问速度和增大系统处理容量. 降级 降级是当服务出现问题或者影响到核心流程时,需要暂时屏蔽掉,待高峰或者问题 ...
- Java技术开发专题系列之【Guava RateLimiter】针对于限流器的入门到精通(针对于源码分析介绍)
Guava包中限流实现分析 RateLimiter 之前的文章中已经介绍了常用的限流算法,而google在Java领域中使用Guava包中的限流工具进行服务限流. 回顾使用案例 Google开源工具包 ...
- 超详细的Guava RateLimiter限流原理解析
超详细的Guava RateLimiter限流原理解析 mp.weixin.qq.com 点击上方“方志朋”,选择“置顶或者星标” 你的关注意义重大! 限流是保护高并发系统的三把利器之一,另外两个是 ...
- 常用限流算法与Guava RateLimiter源码解析
在分布式系统中,应对高并发访问时,缓存.限流.降级是保护系统正常运行的常用方法.当请求量突发暴涨时,如果不加以限制访问,则可能导致整个系统崩溃,服务不可用.同时有一些业务场景,比如短信验证码,或者其它 ...
- 使用Guava RateLimiter限流入门到深入
前言 在开发高并发系统时有三把利器用来保护系统:缓存.降级和限流 缓存: 缓存的目的是提升系统访问速度和增大系统处理容量 降级: 降级是当服务出现问题或者影响到核心流程时,需要暂时屏蔽掉,待高峰或者问 ...
- 限流 - Guava RateLimiter
2019独角兽企业重金招聘Python工程师标准>>> 限流 限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统,一旦并发访问/请求达到限制速率或者 ...
- Guava RateLimiter实现接口API限流
一.简介 Guava提供的RateLimiter可以限制物理或逻辑资源的被访问速率.RateLimit二的原理类似与令牌桶,它主要由许可发出的速率来定义,如果没有额外的配置,许可证将按每秒许可证规定的 ...
- 限流神器之-Guava RateLimiter 实战
前段时间,项目中需要对某些访问量较高的路径进行访问并发数控制,以及有些功能,比如Excel导出下载功能,数据量很大的情况下,用户不断的点击下载按钮,重复请求数据库,导致线上数据库挂掉.于是在这样的情况 ...
- Guava之FluentIterable使用示例
FluentIterable 是guava集合类中常用的一个类,主要用于过滤.转换集合中的数据:FluentIterable是一个抽象类,实现了Iterable接口,大多数方法都返回FluentIte ...
随机推荐
- java实现找素数
** 找素数** 素数就是不能再进行等分的整数.比如:7,11.而9不是素数,因为它可以平分为3等份.一般认为最小的素数是2,接着是3,5,- 请问,第100002(十万零二)个素数是多少? 请注意: ...
- java实现第六届蓝桥杯星系炸弹
星系炸弹 题目描述 在X星系的广袤空间中漂浮着许多X星人造"炸弹",用来作为宇宙中的路标. 每个炸弹都可以设定多少天之后爆炸. 比如:阿尔法炸弹2015年1月1日放置,定时为15天 ...
- PAT 说反话
给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出. 输入格式: 测试输入包含一个测试用例,在一行内给出总长度不超过 80 的字符串.字符串由若干单词和若干空格组成,其中单词是由英文字母(大小 ...
- (数据科学学习手札86)全平台支持的pandas运算加速神器
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 随着其功能的不断优化与扩充,pandas已然成为 ...
- 设计模式系列之建造者模式(Builder Pattern)——复杂对象的组装与创建
说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...
- HDU - 2546 饭卡 题解
题目大意 电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额.如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够) ...
- 【 转】百度地图Canvas实现十万CAD数据秒级加载
Github上看到: https://github.com/lcosmos/map-canvas 这个实现台风轨迹,这个数据量非常庞大,当时打开时,看到这么多数据加载很快,感到有点震惊,然后自己研究了 ...
- Jupyter notebook中的Cell and Line Magics
参考资料: https://www.jianshu.com/p/81ada9234788 https://my.oschina.net/u/2306127/blog/832510 首先,Cell an ...
- LaTeX实时预览中文
参考资料:http://blog.sina.com.cn/s/blog_6ea58f530101aizw.html 功夫不负有心人,终于在经过艰苦卓绝的寻找之后,让我的Texpad实现了实时预览.此时 ...
- Jmeter(十一) - 从入门到精通 - JMeter逻辑控制器 - 下篇(详解教程)
1.简介 Jmeter官网对逻辑控制器的解释是:“Logic Controllers determine the order in which Samplers are processed.”. 意思 ...