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"@Beanpublic RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactor){RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(redisConnectionFactor);// 设置key序列化方式StringredisTemplate.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 resourceString key() default "";// 最多访问限制次数long permitsPerSecond() default 2;// 过期时间 滑动窗空时间 单位秒 默认60秒long expire() default 60;// 得不到令牌提示语String msg() default "系统繁忙 点击太快请稍后重试";
}