赞
踩
相信大家在工作中肯定都会遇到,随着业务的发展,需要不停的提升服务的性能,但是单台机器的性能终归是有限的!为防止服务器因为请求量过大而导致服务不可用的情况,都需要针对接口等维度进行限流控制,就引出了在服务中使用限流器。
Google开源的工具包Guava具备很多强大的功能,限流器就是其中之一,本文主要介绍限流器相关实现原理和使用。
除此之外,Guava还在字符串、集合、网络、文件、并发等各种方面提供了更加强大和方便操作的工具类。
Google开源的工具包Guava具备很多强大的功能,限流器就是其中之一。
常见的限流算法主要有固定窗口、滑动窗口、漏桶、令牌桶算法这几种(知道更多的可以评论补充下~)。
Guava的限流算法是基于令牌桶来实现的!下面为大家通俗介绍下令牌桶算法:
令牌桶算法核心就是一个维护一个固定容量令牌的容器(就是桶),按照固定速率往桶里添加令牌。
桶中最多存放N个令牌,当桶满时,新添加的令牌被丢弃;
当接收到请求时,去桶中获取一个令牌,获取到则继续执行,并删除对应的令牌;
未获取到令牌则丢弃请求(被限流)。
guava实现限流的主要类是RateLimiter,下图是RateLimiter的主要方法。
主要的方法有:
引入google.guava依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.0-android</version>
</dependency>
1.阻塞限流:acquire
public static void blockLimit() {
Long start = System.currentTimeMillis();
RateLimiter limiter = RateLimiter.create(1.0); // 限制每秒通过的数量
for (int i = 0; i < 20; i++) {
limiter.acquire(); // 限流,超过的部分会被阻塞,等待令牌后继续执行
Long end = System.currentTimeMillis();
System.out.println("call execute.." + i);
System.out.println("time: " + (end - start)/1000 + "s");
}
}
运行该段代码后的结果如下,可以看到后续的请求都被阻塞,每一秒钟会执行一次。
call execute…0
time: 0s
call execute…1
time: 1s
call execute…2
time: 2s
call execute…3
time: 3s
call execute…4
time: 4s
…
2.非阻塞限流:tryAcquire
public static void nonBlockLimit() {
Long start = System.currentTimeMillis();
RateLimiter limiter = RateLimiter.create(100.0); // 限制每秒通过的数量
for (int i = 0; i < 20; i++) {
boolean b = limiter.tryAcquire(); // 限流,返回布尔值,非阻塞
if (b) {
System.out.println("execute.." + i);
} else {
System.out.println("request too frequently" );
}
}
}
运行该段代码后的结果如下,可以看到只有第一次执行,后续都是请求过于频繁,因为请求都是在1s内完成的。一般来说都是使用tryAcquire方法。
execute…0
request too frequently
request too frequently
request too frequently
request too frequently
request too frequently
…
综上,Guava在针对单机或者在集群中对单台机器进行qps、tps进行限制时表现的非常可靠和稳定,是个不错的选择。但是无法满足在分布式系统中进行分布式限流!后续会再进行分布式限流的介绍。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。