有彩蛋哦!!!(或者公众号内点击网赚获取彩蛋)
在调用第三方接口的时候一般都会有接口调用频率限制,如果一般的不频繁的业务情况我们不需要业务处理,但是如果遇到批量调用的情况就需要考虑怎么做限制了。谷歌guava工具的RateLimiter提供了限流,采用的是令牌桶算法
@Slf4j
public class RateLimitService {
private static final ExecutorService rateLimitPool = Executors.newFixedThreadPool(30);
private static final RateLimiter rateLimiter = RateLimiter.create(20);
private static final int ALL_TASK = 100;
public static void testRateLimit(){
for (int i = 0;i < ALL_TASK;i++){
rateLimitPool.execute(()->{
rateLimiter.acquire();
try {
log.info("take a token");
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
public static void main(String[] args) {
testRateLimit();
}
}
结果:
33 13次 34 20次
21:33:33.458 [pool-1-thread-2] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:33.458 [pool-1-thread-8] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:33.465 [pool-1-thread-5] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:33.515 [pool-1-thread-4] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:33.565 [pool-1-thread-1] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:33.615 [pool-1-thread-24] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:33.664 [pool-1-thread-9] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:33.715 [pool-1-thread-12] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:33.765 [pool-1-thread-6] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:33.814 [pool-1-thread-7] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:33.865 [pool-1-thread-13] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:33.914 [pool-1-thread-16] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:33.965 [pool-1-thread-17] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.014 [pool-1-thread-10] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.064 [pool-1-thread-11] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.115 [pool-1-thread-20] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.164 [pool-1-thread-21] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.215 [pool-1-thread-3] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.264 [pool-1-thread-25] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.314 [pool-1-thread-28] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.364 [pool-1-thread-14] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.414 [pool-1-thread-15] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.465 [pool-1-thread-18] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.515 [pool-1-thread-19] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.563 [pool-1-thread-22] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.614 [pool-1-thread-23] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.664 [pool-1-thread-26] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.714 [pool-1-thread-27] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.764 [pool-1-thread-30] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.815 [pool-1-thread-29] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.865 [pool-1-thread-2] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.914 [pool-1-thread-8] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:34.964 [pool-1-thread-5] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.014 [pool-1-thread-4] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.064 [pool-1-thread-1] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.115 [pool-1-thread-24] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.165 [pool-1-thread-9] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.215 [pool-1-thread-12] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.265 [pool-1-thread-6] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.315 [pool-1-thread-7] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.365 [pool-1-thread-13] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.414 [pool-1-thread-16] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.465 [pool-1-thread-17] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.515 [pool-1-thread-10] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.565 [pool-1-thread-11] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.615 [pool-1-thread-20] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.665 [pool-1-thread-21] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.715 [pool-1-thread-3] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.764 [pool-1-thread-25] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.814 [pool-1-thread-28] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.865 [pool-1-thread-14] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.914 [pool-1-thread-15] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:35.965 [pool-1-thread-18] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.015 [pool-1-thread-19] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.067 [pool-1-thread-22] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.115 [pool-1-thread-23] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.164 [pool-1-thread-26] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.214 [pool-1-thread-27] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.264 [pool-1-thread-30] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.314 [pool-1-thread-29] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.365 [pool-1-thread-2] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.415 [pool-1-thread-8] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.465 [pool-1-thread-5] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.514 [pool-1-thread-4] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.564 [pool-1-thread-1] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.614 [pool-1-thread-24] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.664 [pool-1-thread-9] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.715 [pool-1-thread-12] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.765 [pool-1-thread-6] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.815 [pool-1-thread-7] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.865 [pool-1-thread-13] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.914 [pool-1-thread-16] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:36.964 [pool-1-thread-17] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.014 [pool-1-thread-10] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.065 [pool-1-thread-11] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.115 [pool-1-thread-20] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.165 [pool-1-thread-21] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.215 [pool-1-thread-3] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.264 [pool-1-thread-25] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.314 [pool-1-thread-28] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.364 [pool-1-thread-14] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.414 [pool-1-thread-15] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.464 [pool-1-thread-18] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.515 [pool-1-thread-19] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.565 [pool-1-thread-22] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.615 [pool-1-thread-23] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.664 [pool-1-thread-26] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.714 [pool-1-thread-27] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.764 [pool-1-thread-30] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.815 [pool-1-thread-29] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.865 [pool-1-thread-2] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.915 [pool-1-thread-8] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:37.965 [pool-1-thread-5] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:38.014 [pool-1-thread-4] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:38.065 [pool-1-thread-1] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:38.114 [pool-1-thread-24] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:38.164 [pool-1-thread-9] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:38.215 [pool-1-thread-12] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:38.265 [pool-1-thread-6] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
21:33:38.315 [pool-1-thread-7] INFO com.zzh.rocket.serverall.service.RateLimitService - take a token
返回睡的毫秒数
@CanIgnoreReturnValue
public double acquire() {
return acquire(1);
}
@CanIgnoreReturnValue
public double acquire(int permits) {
获取需要等待多少秒
long microsToWait = reserve(permits);
如果等待毫秒数 > 0 就调用Thread.sleep
stopwatch.sleepMicrosUninterruptibly(microsToWait);
返回等待的毫秒数
return 1.0 * microsToWait / SECONDS.toMicros(1L);
}
-----判断sleep代码
@Override
protected void sleepMicrosUninterruptibly(long micros) {
if (micros > 0) {
Uninterruptibles.sleepUninterruptibly(micros, MICROSECONDS);
}
}
public static void sleepUninterruptibly(long sleepFor, TimeUnit unit) {
boolean interrupted = false;
try {
long remainingNanos = unit.toNanos(sleepFor);
long end = System.nanoTime() + remainingNanos;
while (true) {
try {
// TimeUnit.sleep() treats negative timeouts just like zero.
NANOSECONDS.sleep(remainingNanos);
return;
} catch (InterruptedException e) {
interrupted = true;
remainingNanos = end - System.nanoTime();
}
}
} finally {
if (interrupted) {
Thread.currentThread().interrupt();
}
}
}
public void sleep(long timeout) throws InterruptedException {
if (timeout > 0) {
long ms = toMillis(timeout);
int ns = excessNanos(timeout, ms);
Thread.sleep(ms, ns);
}
}
只大致看了一下流程,RateLimiter还有很多细节,比如实现类有两个,还有tryAcquire方法返回是否拿到令牌,后面还需要分析源码