【Guava】RateLimiter注解版实现限流

之前有个RateLimiter代码实现限流的文章,这里附带一下,感兴趣的童鞋可以看一下下面的这个链接【Guava】使用RateLimiter限制用户操作频率_阿小冰的博客-CSDN博客【Guava】使用RateLimiter限制用户操作频率https://blog.csdn.net/qq_38377525/article/details/125053866

下面我们提供一个注解版的,个人推荐使用注解版,因为上面链接提到的这一版代码太冗余了,所以不太推荐


代码演示

1、创建一个SpringBoot工程

2、添加依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>27.0.1-jre</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.9.6</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.3.11</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
            <version>2.3.6.RELEASE</version>
        </dependency>

 2、编写注解类

@Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyRateLimiter {
    //向令牌桶放入令牌的速率
    double rate();
    //从令牌桶获取令牌的超时时间
    long timeout() default 0;
}

3、编写切面实现类

@Aspect
@Component
@Configuration
public class MyRateLimiterAspect {
    private RateLimiter rateLimiter = RateLimiter.create(2);

    @Pointcut("@annotation(MyRateLimiter注解类全路径com.xxx)")
    public void pointcut() {
    }

    /*** 核心切面方法 */
    @Around("pointcut()")
    public Object process(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        //使用反射获取方法上是否存在@MyRateLimiter注解
        MyRateLimiter myRateLimiter = signature.getMethod().getDeclaredAnnotation(MyRateLimiter.class);
        if (myRateLimiter == null) {
            //程序正常执行,执行目标方法
            return proceedingJoinPoint.proceed();
        }
        //获取注解上的参数
        // 获取配置的速率
        double rate = myRateLimiter.rate();
        //获取客户端等待令牌的时间
        long timeout = myRateLimiter.timeout();
        //设置限流速率
        rateLimiter.setRate(rate);
        //判断客户端获取令牌是否超时
        boolean tryAcquire = rateLimiter.tryAcquire(timeout, TimeUnit.MILLISECONDS);
        if (!tryAcquire) {
            //服务降级
            fullback();
            return null;
        }
        //获取到令牌,直接执行

        return proceedingJoinPoint.proceed();
    }

    /*** 降级处理 */
    private void fullback() {
        ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletResponse response=attributes.getResponse();
        response.setHeader("Content-type", "text/html;charset=UTF-8");
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
            writer.println("当前访问人数过多,请稍后再试!");
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }
}

4、编写接口

@RestController
public class TestController {

    @MyRateLimiter(rate = 1.0, timeout = 500)
    @RequestMapping("/pay")
    public String pay() {
        //记录返回接口
        return "支付成功!";
    }
}

5、验证接口是否限流

频繁访问接口,会发现返回结果会在"支付成功"或"当前访问人数过多,请稍后再试!"来回切换,这就达到了限流的效果

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值