Redis实现接口限流

  • A+
所属分类:系统文档

:欢迎您的到来! 如果您遇到任何问题,请联系博主 qq:180181332 , 微信:eerrffaa

:欢迎您的到来! 如果您遇到任何问题,请联系博主 qq:180181332 , 微信:eerrffaa

Redis实现接口限流

发表于 2023-08-25 | 更新于 2023-08-25 | 字数统计: 5.9k | 阅读时长: 15分钟 | 阅读量: 16 | 后端笔记 |评论数: 0

准备

  1. 自定一个redis接口限流注解

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface AccessLimit {
    
        /**
         * 单位时间(秒)
         *
         * @return int
         */
        int seconds();
    
        /**
         * 单位时间最大请求次数
         *
         * @return int
         */
        int maxCount();
    }
    
    java
  2. 标记在你想要限流的接口上

    @AccessLimit(seconds = 6, maxCount = 1)
    @ApiOperation(value = "发送邮箱验证码")
    @ApiImplicitParam(name = "username", value = "用户名", required = true, dataType = "String")
    @GetMapping("/users/code")
    public Result<?> sendCode(String username) {
        userAuthService.sendCode(username);
        return Result.ok();
    }
    java

拦截

  1. 自定义限流拦截器AccessLimitHandler

    /**
     * @author: ladidol
     * @date: 2022/11/28 12:25
     * @description: 限流拦截器
     */
    @Log4j2
    public class AccessLimitHandler implements HandlerInterceptor {
        @Autowired
        private RedisService redisService;
    
        @Override
        public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
            // 如果请求输入方法
            if (handler instanceof HandlerMethod) {
                HandlerMethod hm = (HandlerMethod) handler;
                // 获取方法中的注解,看是否有该注解
                AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);
                if (accessLimit != null) {
                    long seconds = accessLimit.seconds();
                    int maxCount = accessLimit.maxCount();
                    // 关于key的生成规则可以自己定义 本项目需求是对每个方法都加上限流功能,如果你只是针对ip地址限流,那么key只需要只用ip就好
                    String key = IpUtils.getIpAddress(httpServletRequest) + hm.getMethod().getName();
                    // 从redis中获取用户访问的次数
                    try {
                        // 此操作代表获取该key对应的值自增1后的结果
                        long q = redisService.incrExpire(key, seconds);
                        if (q > maxCount) {
                            render(httpServletResponse, Result.fail("请求过于频繁,请稍候再试"));
                            log.warn(key + "请求次数超过每" + seconds + "秒" + maxCount + "次");
                            return false;
                        }
                        return true;
                    } catch (RedisConnectionFailureException e) {
                        log.warn("redis错误: " + e.getMessage());
                        return false;
                    }
                }
            }
            return true;
        }
    
        /**
         * 作者:Ladidol
         * 描述:将不通过的结果返回给前端
         */
        private void render(HttpServletResponse response, Result<?> result) throws Exception {
            response.setContentType(APPLICATION_JSON);
            OutputStream out = response.getOutputStream();
            String str = JSON.toJSONString(result);
            out.write(str.getBytes(StandardCharsets.UTF_8));
            out.flush();
            out.close();
        }
    
    }
    java
  2. 在WebMvcConfigurer的实现类中注册拦截器

    /** <p>
        * 作者:Ladidol
        * 描述:WebMvc注册拦截器
        */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
    
        //注册限流拦截器
        registry.addInterceptor(getAccessLimitHandler());
    }
    java

另一种实现方式:[我司用了 6 年的 Redis 分布式限流器,可以说是非常厉害了! (qq.com)](

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明文章出处。

注意:本站用户发帖仅代表本站用户个人观点,并不代表本站赞同其观点和对其真实性负责。

本站资源多为网络收集,如涉及版权问题请及时与站长联系,我们会在第一时间内删除资源。

相关推荐

Redis实现接口限流

Redis实现接口限流

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin