通过计数器实现接口限流
- - 行业应用 - 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; } }