为什么有这篇文章
在负责某个项目开发过程中,在定时任务(job)里面调用了公司的内部某个微服务,进行财务流水生成,在被调用方能力处理不及时的时候,引发被调用方宕机奔溃,故此在客户端,即Job做简单的限流,于是针对此场景进行调研,发现Guava RateLimiter在此种场景下,简单且高效。
模拟调用示例
public static void main(String[] args) {
// 模拟10次调用
int a = 10;
while (true) {
// 调用的当前时间
LocalTime now = LocalTime.now();
System.out.println("模拟调用三方微服务,当前时间为:" + now.toString());
a--;
if (a == 0) {
break;
}
}
}
模拟调用三方微服务,当前时间为:10:16:22.088
模拟调用三方微服务,当前时间为:10:16:22.089
模拟调用三方微服务,当前时间为:10:16:22.089
模拟调用三方微服务,当前时间为:10:16:22.089
模拟调用三方微服务,当前时间为:10:16:22.089
模拟调用三方微服务,当前时间为:10:16:22.089
模拟调用三方微服务,当前时间为:10:16:22.089
模拟调用三方微服务,当前时间为:10:16:22.089
模拟调用三方微服务,当前时间为:10:16:22.089
模拟调用三方微服务,当前时间为:10:16:22.089
由本示例可以了解到,在 10:16:22 内完成了 10次调用,本次调用过程中对于调用方的并发处理能力要求很高,如果调用方没有做限流等操作的话,在业务高峰期,调用方很容易崩溃,当然我们如果作为调用方的话,也需要做简单的限流操作:推荐使用 sentine https://sentinelguard.io/zh-cn/docs/open-source-framework-integrations.html
客户端调用按照RateLimiter限流限流示例
public static void main(String[] args) {
//初始化 每秒1个令牌
RateLimiter rateLimiter = RateLimiter.create(1);
int a = 10;
while (true) {
//每次需要1个令牌
rateLimiter.acquire(1);
LocalTime now = LocalTime.now();
System.out.println("模拟调用三方微服务,当前时间为:" + now.toString());
a--;
if (a == 0) {
break;
}
}
}
模拟调用三方微服务,当前时间为:10:24:10.257
模拟调用三方微服务,当前时间为:10:24:11.176
模拟调用三方微服务,当前时间为:10:24:12.177
模拟调用三方微服务,当前时间为:10:24:13.177
模拟调用三方微服务,当前时间为:10:24:14.180
模拟调用三方微服务,当前时间为:10:24:15.180
模拟调用三方微服务,当前时间为:10:24:16.175
模拟调用三方微服务,当前时间为:10:24:17.180
模拟调用三方微服务,当前时间为:10:24:18.179
模拟调用三方微服务,当前时间为:10:24:19.177
我们可以看到限流后的服务调用记录,在10-19秒内,每秒调用一次,服务调用平稳,并无瞬时的高峰,缓解了调用方的服务压力,不会无缘无故背锅。
RateLimiter源码分析
持续更新中....