通过计数器实现接口限流
- - 行业应用 - ITeye博客如果接口可能会有突发访问情况,但又担心访问量大而导致系统崩溃,这个时候就需要对接口的请求并发数进行限制了. 可以为相应的接口设置对应的阈值,超过则拒绝请求或者排队等待. 1、使用java自带的concurrent包下的类进行限流,示例代码如下:. 2、使用guava的Cache来限流,示例代码如下:.
如果接口可能会有突发访问情况,但又担心访问量大而导致系统崩溃,这个时候就需要对接口的请求并发数进行限制了。可以为相应的接口设置对应的阈值,超过则拒绝请求或者排队等待。
1、使用java自带的concurrent包下的类进行限流,示例代码如下:
private static final AtomicLong atomic = new AtomicLong(0);
public static void limitByAtomic(String hello)throws Exception{
try{
if(atomic.incrementAndGet() > 2){
//拒绝请求
}
//处理请求
}finally{
atomic.decrementAndGet();
}
}
2、使用guava的Cache来限流,示例代码如下:
public static void limitByCounter(String hello)throws Exception{
LoadingCache<Long, AtomicLong> counter =
CacheBuilder.newBuilder()
.expireAfterWrite(2, TimeUnit.SECONDS)
.build(new CacheLoader<Long, AtomicLong>(){
@Override
public AtomicLong load(Long seconds) throws Exception {
return new AtomicLong(0);
}
});
long limit = 1000;
while(true){
long currentSeconds = System.currentTimeMillis() / 1000;
if(counter.get(currentSeconds).incrementAndGet() > limit){
//拒绝请求
continue;
}
//处理业务
}
}
以下是Guava的Cache实现的一个简易版超限计数器
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
/**
* guava计数器工具类
*
* @author lh
* @version 2.0
* @since 2017-06-22
*
*/
public class GuavaCounterUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(GuavaCounterUtil.class);
private static final LoadingCache<String, AtomicLong> counter = CacheBuilder.newBuilder()
.expireAfterWrite(2, TimeUnit.SECONDS)// 每两秒清除一次
.build(new CacheLoader<String, AtomicLong>() {
@Override
public AtomicLong load(String seconds) throws Exception {
return new AtomicLong(0);
}
});
/**
* 请求是否超限
*
* @param uri
* 请求地址(接口地址或其他可标识字符)
* @param limit
* 每秒请求限制数
* @return
*/
public static final boolean overLimit(String uri, long limit) {
long currentSeconds = System.currentTimeMillis() / 1000;
try {
return counter.get(uri + currentSeconds).incrementAndGet() > limit;
} catch (ExecutionException e) {
LOGGER.warn(e.getMessage(), e);
}
return false;
}
}