利用spring如何实现接口限流

Valencia ·
更新时间:2024-09-21
· 568 次阅读

利用spring如何实现接口限流 1.创建自定义注解 ** * 限流注解 */ @Inherited @Documented @Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface AccessLimit { //限流唯一标识 String key() default ""; //限流时间 int time(); //限流次数 int count(); } 创建限流配置类 /** * 注解拦截 */ @Slf4j @Aspect @Configuration public class AccessLimitConfig { @Autowired private RedisTemplate redisTemplate; @Autowired private DefaultRedisScript redisScript; /** * 执行redis的具体方法,限制method,保证没有其他的东西进来 * * @return */ @Around("execution(* com.mayday.auth.controller ..*(..) )") public Object interceptor(ProceedingJoinPoint joinPoint) throws Throwable { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); Class targetClass = method.getDeclaringClass(); AccessLimit accessLimit = method.getAnnotation(AccessLimit.class); if (accessLimit != null) { //获取request对象 HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); String ipAddr = IpUtils.getIpAddr(request); String string = ipAddr + "-" + targetClass.getName() + "- " + method.getName() + "-" + accessLimit.key(); List keys = Collections.singletonList(string); Number number = redisTemplate.execute(redisScript, keys, accessLimit.count(), accessLimit.time()); if (number != null && number.intValue() != 0 && number.intValue() <= accessLimit.count()) { return joinPoint.proceed(); } } else { return joinPoint.proceed(); } return new Result(false, StatusCode.REPEAT_OPERATE); } } 3. 创建切面类 /** * 限流配置 */ @Slf4j @Component public class AccessLimitAspect { /** * 读取限流脚本 * * @return */ @Bean public DefaultRedisScript redisLuaScript() { DefaultRedisScript redisScript = new DefaultRedisScript(); redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("redisLimit.lua"))); //返回类型 redisScript.setResultType(Number.class); return redisScript; } /** * RedisTemplate * * @return */ @Bean public RedisTemplate limitRedisTemplate(LettuceConnectionFactory redisConnectionFactory) { RedisTemplate template = new RedisTemplate(); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setConnectionFactory(redisConnectionFactory); return template; } } Lua脚本 --Lua脚本 --IP限流Lua脚本 --- 限流KEY资源唯一标识 local key = "rate.limit:" .. KEYS[1] --- 时间窗最大并发数 local limit = tonumber(ARGV[1]) --- -过期时间 local expire_time = ARGV[2] local is_exists = redis.call("EXISTS", key) if is_exists == 1 then if redis.call("INCR", key) > limit then return 0 else return 1 end else redis.call("SET", key, 1) redis.call("EXPIRE", key, expire_time) return 1 end
作者:flame灬温柔



实现接口 spring 接口

需要 登录 后方可回复, 如果你还没有账号请 注册新账号