应用限流实战-多解决方案(guava,redis,nginx+lua)

参考:https://blog.csdn.net/lzw_2006/article/details/51789859

一、简单的guava平滑限流方案

public class RateLimiterTest  {
    public static void main(String[] args) throws InterruptedException, Exception {
        RateLimiter rateLimiter = RateLimiter.create(2); //每秒往令牌桶投放2个令牌,每0.5s一个
        CountDownLatch countDownLatch = new CountDownLatch(2);
        for (int i = 0; i < 2; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        countDownLatch.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (rateLimiter.tryAcquire(1, 488, TimeUnit.MILLISECONDS)) { //tryAcquire检测有没有可用的令牌
                        System.out.println("处理请求");
                    } else {
                        System.out.println("拒绝请求");
                    }
                }
            }).start();
          countDownLatch.countDown();
        }
    }
}

分析:每秒往令牌桶投放2个令牌,即每0.5s 一个。两个线程同时获取令牌,第2个要0.5s才能获取到,但获取令牌超时时间为0.488s<0.5s不能获取到令牌。超时时间改为大于0.5s基本就能正常处理请求了。

二、基于Redis时间窗口分布式限流方案(自定义注解+aop)


@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessLimit {
     int expire() default 1;
     int limit() default 500;
}
@Aspect
@Component
public class AccessLimitAspect {
    @Autowired
    RedisTemplate redisTemplate;
    
    @Before("@annotation(AccessLimit)")
    public void deBefore(JoinPoint joinPoint) throws Throwable {
    MethodSignature sign = (MethodSignature) joinPoint.getSignature();
        Method method = sign.getMethod();
        String methodName = method.getName();
        AccessLimit annotation = method.getAnnotation(AccessLimit.class);
        int expire = annotation.expire();
        int limit = annotation.limit();
        Long methodLimit = redisTemplate.opsForValue().increment(methodName);
        if (methodLimit==1) {
          redisTemplate.expire(methodName,expire,TimeUnit.SECONDS);
        }
        if (methodLimit>limit) {
          throw  new RuntimeException(methodName+"接口访问人数过多!");
        }
    }
}

三、基于Nginx+lua脚本的接入层限流方案,lua脚本不会玩,暂时就这样了,请参考https://blog.csdn.net/lzw_2006/article/details/51789859

猜你喜欢

转载自blog.csdn.net/qq_39506978/article/details/89328629
今日推荐