1.开发自定义限流注解给全团队赋能共用,一个注解搞定
2.可配置【时间窗口内可以随意灵活调整时间和次数】 + 可拔插
3.支持高并发【redis下干的】且满足事务一致性要求,lua脚本
注意!限流是在Controller层做的,不要干到Service层【做业务逻辑的】
1.自定义注解RedisLimitAnnotation实现业务解耦
2.高并发实时配置下的LuaScript处理
3.自定义AOP切面类
RedisLimitController
@Slf4j
@RestController
public class RedisLimitController{
@GetMapping("/redis/limit/test")
public String redisLimit(){
return "业务正常返回,订单流水:" + IdUtil.fastUUID();
}
}
限流后
时间窗口在这等价于redis 的 key的过期时间
@Slf4j
@RestController
// 1秒内只允许2个人点击
@RedisLimitAnnotation(key = "redis-limit:test" , permitsPerSecond = 2,expire = 1, msg = "当前排队人数过多,请稍后再试!")
public class RedisLimitController{
@GetMapping("/redis/limit/test")
public String redisLimit(){
return "业务正常返回,订单流水:" + IdUtil.fastUUID();
}
}
RedisConfig
redis序列化的工具配置类【一定要开启】
public class RedisConfig{
// 执行 keys *
// 野生:"\xac\xed\x00\aord:102" 序列化后:"ord:102"
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactor){
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactor);
// 设置key序列化方式String
redisTemplate.setKeySerializer(new StringRedisSerializer());
// 设置value的序列化方式json,使用GenericJackson2JsonRedisSerializer替换默认序列化
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
RedisLimitAnnotation
@Retentiom(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Document
public @interface RedisLimitAnnotation{
// 资源key唯一,不同接口不同流量控制 模拟Sentinel资源key resource
String key() default "";
// 最多访问限制次数
long permitsPerSecond() default 2;
// 过期时间 滑动窗空时间 单位秒 默认60秒
long expire() default 60;
// 得不到令牌提示语
String msg() default "系统繁忙 点击太快请稍后重试";
}