计数器算法是在一定的时间间隔里,记录请求次数,当请求次数超过该时间限制时,就把计数器清零,然后重新计算。当请求次数超过间隔内的最大次数时,拒绝访问。
`import java.util.concurrent.atomic.AtomicLong;
/**
- 计数器限流
*/
public class CountRateLimiter {
private AtomicLong counter = new AtomicLong(0);
private long timestamp = System.currentTimeMillis();
private long permitsPerSecond;
private static long MS = 1000;
public CountRateLimiter(long permitsPerSecond) {
this.permitsPerSecond = permitsPerSecond;
}
public boolean tryAcquire() {
long now = System.currentTimeMillis();
if (now - timestamp < MS) {
if (counter.get() < permitsPerSecond) {
counter.incrementAndGet();
return true;
} else {
return false;
}
}
return false;
}
}`
`package com.yonyou.iuap.dispatch.util;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.concurrent.TimeUnit;
/**
- 计数器限流工具类
*/
public class CountRateLimiterUtils {
final static Cache<String, CountRateLimiter> COUNT_RATE_LIMITER_CACHE = CacheBuilder.newBuilder().expireAfterWrite(2000, TimeUnit.MILLISECONDS).build();
private static final Object lock = new Object();
private static CountRateLimiter getCountRateLimter(String code, long permitsPerSecond) {
CountRateLimiter object = COUNT_RATE_LIMITER_CACHE.getIfPresent(code);
if (object == null) {
synchronized (lock) {
object = COUNT_RATE_LIMITER_CACHE.getIfPresent(code);
if (object == null) {
object = new CountRateLimiter(permitsPerSecond);
COUNT_RATE_LIMITER_CACHE.put(code, object);
}
}
}
return object;
}
public static boolean tryAcquire(String code, long permitsPerSecond) {
code = code + DateUtil.current() / 1000;
CountRateLimiter countRateLimiter = getCountRateLimter(code, permitsPerSecond);
return countRateLimiter.tryAcquire();
}
}`