www1350 / javaweb

http://www1350.github.io/
31 stars 5 forks source link

限流算法 #104

Open www1350 opened 7 years ago

www1350 commented 7 years ago

1.总量限流

@Slf4j
@WebFilter(urlPatterns = "/*", filterName = "requestFilter")
public class LimitFilter implements Filter {
    private static final int MAX_COUNT = 20000;

    private final static AtomicInteger filterCount = new AtomicInteger(0);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info("before {}",filterCount);
        if (filterCount.get() > MAX_COUNT) {
            //请求个数太多,跳转到排队页面
            servletRequest.getRequestDispatcher("index.html").forward(servletRequest, servletResponse);
        } else {
            //请求个数加1
            filterCount.incrementAndGet();
            filterChain.doFilter(servletRequest, servletResponse);
            //访问结束,请求个数减1
            filterCount.decrementAndGet();
        }
    }

    @Override
    public void destroy() {
    }
}

使用guava cache控制某个时间窗请求

@Slf4j
public class GuavaLimiter {

    private static LoadingCache<Long,AtomicLong> counter;

    private static final  long limit = 1000;

    public static void main(String[] args) throws ExecutionException {
        counter = CacheBuilder.newBuilder()
                .expireAfterWrite(2, TimeUnit.SECONDS)
                .build(new CacheLoader<Long, AtomicLong>() {
                    @Override
                    public AtomicLong load(Long key) throws Exception {
                        return new AtomicLong(0);
                    }
                });

        work();
    }

    private static void work() throws ExecutionException {
        while (true){
            long current = System.currentTimeMillis() / 1000;
            if(counter.get(current).incrementAndGet()>limit){
                log.info("限流"+current);
                continue;
            }
            //TODO
            log.error("业务处理中");
        }
    }
}

基于guava limiter的平滑限流

        Long start = System.currentTimeMillis();
        RateLimiter limiter = RateLimiter.create(10.0); // 每秒不超过10个任务被提交
        for (int i = 0; i < 100; i++) {
            limiter.acquire(); // 请求RateLimiter, 超过permits会被阻塞
            System.out.println("call execute.." + i);
        }
        Long end = System.currentTimeMillis();
        System.out.println(end - start);