高并发限流(二)——应用举例

1.对单个接口的总并发数进行限制

1.利用一个AtomicLong变量进行简单粗暴的限流

[java] view plain copy
 
print ? 在CODE上查看代码片 派生到我的代码片
  1. try {  
  2.     if(atomic.incrementAndGet() > 限流数) {  
  3.         //拒绝请求  
  4.     }  
  5.     //处理请求  
  6. finally {  
  7.     atomic.decrementAndGet();  
  8. }  
try {
    if(atomic.incrementAndGet() > 限流数) {
        //拒绝请求
    }
    //处理请求
} finally {
    atomic.decrementAndGet();
}

2.利用SHARED模式的ReentrantLock

[java] view plain copy
 
print ? 在CODE上查看代码片 派生到我的代码片
  1. try {  
  2.     if(lock.lock()) {  
  3.         //拒绝请求  
  4.     }  
  5.     //处理请求  
  6. finally {  
  7.     lock.unlock();  
  8. }  
try {
    if(lock.lock()) {
        //拒绝请求
    }
    //处理请求
} finally {
    lock.unlock();
}

这里可以根据需要采用完全阻塞的lock,立即返回的tryLock,以及带等待时间的lock(lockTime)等方法。

3.异步

对于异步需要注意,如果consumer方没有回调或者回调超时,要保证对应请求的decrement和unlock操作都要执行,否则计数就会有问题了。

2.限流某个接口的时间窗请求数

[java] view plain copy
 
print ? 在CODE上查看代码片 派生到我的代码片
  1. LoadingCache<Long, AtomicLong> counter =  
  2.         CacheBuilder.newBuilder()  
  3.                 .expireAfterWrite(2, TimeUnit.SECONDS)  
  4.                 .build(new CacheLoader<Long, AtomicLong>() {  
  5.                     @Override  
  6.                     public AtomicLong load(Long seconds) throws Exception {  
  7.                         return new AtomicLong(0);  
  8.                     }  
  9.                 });  
  10. long limit = 1000;  
  11. while(true) {  
  12.     //得到当前秒  
  13.     long currentSeconds = System.currentTimeMillis() / 1000;  
  14.     if(counter.get(currentSeconds).incrementAndGet() > limit) {  
  15.         System.out.println("限流了:" + currentSeconds);  
  16.         continue;  
  17.     }  
  18.     //业务处理  
  19. }  
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) {
        System.out.println("限流了:" + currentSeconds);
        continue;
    }
    //业务处理
}

这里统计每秒内的请求次数总和,过期时间设置为大于1s的时间即可,保证1s内的统计不会过期。

和上面段落实现功能的区别

上面限制总并发数的限制,如果业务流执行很快,很快就decrementAndGet或者unlock,那么1s内可以接收很多请求,比如业务处理消耗1ms,即使并发数最大是1,1s中也可以接收1000个请求。

本段落限制时间窗内的请求数就和业务执行快慢无关了,这里只统计1s钟内执行了多少次,即使业务处理消耗时间很少,比如1ms,但是如果在第一个ms内就来了1000个请求,那么剩余的999ms就一个请求也进不来了。

3.分布式限流

Redis实现的分布式限流,

[java] view plain copy
 
print ? 在CODE上查看代码片 派生到我的代码片
  1. int current = jedis.incr(key);  
  2. if (current + 1 > limit) //如果超出限流大小  
  3.    return 0;  
  4. else if (current == 1//只有第一次访问需要设置2秒的过期时间  
  5.    jedis.expire(key, "2");  
  6. return 1  

http://blog.csdn.net/xxcupid/article/details/52016370

猜你喜欢

转载自m635674608.iteye.com/blog/2339612
今日推荐