通过计数器实现接口限流

如果接口可能会有突发访问情况,但又担心访问量大而导致系统崩溃,这个时候就需要对接口的请求并发数进行限制了。可以为相应的接口设置对应的阈值,超过则拒绝请求或者排队等待。

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;
	}

}

猜你喜欢

转载自hbxflihua.iteye.com/blog/2381021