springboot做接口限流
目录
- 1. 依赖+全局配置
- 2. 注解配置
1. 依赖+全局配置
-
引入依赖
<dependency> <groupId>com.github.taptap</groupId> <artifactId>ratelimiter-spring-boot-starter</artifactId> <version>1.2</version> </dependency>
-
application.yml基础配置
taptap.ratelimiter 是一个基于 Redis 的分布式限流组件,它确实会将 API key 存入缓存,并进行计数,当超出了限制就会抛出异常。spring: ratelimiter: enabled: true redis-address: redis://ip:port redis-password: password redis-database: 2 # 下面两个配置可选择性配置,一般是通过 @RateLimit 给具体的接口进行限流 rate: 10 # 每秒允许10次请求 window: 60 # 限流窗口为60秒
-
AOP配置限流,全局限流(这一步可选,一般用注解限流)@Aspect @Component public class RateLimitAspect { @Autowired private RateLimiterService rateLimiterService; @Around("execution(* com.yourpackage.controller..*(..))") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); RateLimit rateLimit = method.getAnnotation(RateLimit.class); if (rateLimit != null) { RateLimiterInfo limiterInfo = rateLimiterService.getRateLimiterInfo(joinPoint, rateLimit); // 执行限流逻辑 if (!rateLimiterService.isAllowed(limiterInfo)) { throw new RateLimitException("Too Many Requests"); } } return joinPoint.proceed(); } }
2. 注解配置
可通过@RateLimit
注解给具体的接口进行限流配置。
@ApiOperation("医保订单结算结果查询并通知到his")
@PostMapping("/queryOrderInfo")
@RateLimit(rate = 5, rateInterval = 10, keys = {"#queryOrderPmcDTO.payOrdId"})
public ResultBean queryOrderInfo(@RequestBody QueryOrderPmcDTO queryOrderPmcDTO) {
...
}
上面的限流配置策略就是:10秒内,只能请求5次,通过queryOrderPmcDTO.payOrdId作为计数标准,queryOrderPmcDTO.payOrdId相同的请求就计数+1。
当超过了窗口期(rateInterval = 10)之后,Redis中的key就会被清除。
可以使用三目表达式:
@ApiOperation("医保订单结算结果查询并通知到his")
@PostMapping("/queryOrderInfo")
@RateLimit(rate = RATE, rateInterval = RATE_INTERVAL, keys = {"#queryOrderPmcDTO.payOrdId != null ? #queryOrderPmcDTO.payOrdId : #queryOrderPmcDTO.medOrgOrd"})
public ResultBean queryOrderInfo(@RequestBody QueryOrderPmcDTO queryOrderPmcDTO) {
...
}
上面的限流配置策略就是:10秒内,只能请求5次,通过queryOrderPmcDTO.payOrdId作为计数标准(如果payOrdId为空,就用medOrgOrd作为计数标准),queryOrderPmcDTO.payOrdId相同的请求就计数+1。