redis限流

计数器限流,时间段一个计数器,超过指定值,就返回错误。
lua保证操作原子性。
zuul网关中,使用过滤器限流。


/**
 * 限流
 * @author lipo
 * @version v1.0
 * @date 2019-10-25 10:34
 */
@Slf4j
@Component
public class LimitFilter extends OncePerRequestFilter {
    /**
     * 1。查询key,如果不存在,就创建key
     * 2。计数器+1,查出来
     * 3。计数器>限定值,返回true,限流;否则,返回false,不限流
     */

    private static final String LUA_SCRIPT = "local count = redis.call('GET', KEYS[1])\n" +
                    "if not count then\n" +
                    "   redis.call('SET', KEYS[1], 1, 'EX', ARGV[1])\n" +
                    "   return false\n" +
                    "end\n" +

                    "redis.call('INCR', KEYS[1])\n" +
                    "if (count + 1 > tonumber(ARGV[2])) then\n" +
                    "   return true\n" +
                    "end\n" +

                    "return false\n"
            ;

    private final RedisScript<Boolean> redisScript = new DefaultRedisScript<>(LUA_SCRIPT, Boolean.class);

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //过滤图标请求
        String requestUri = request.getRequestURI();
        if ("/favicon.ico".equals(requestUri)) {
            return;
        }

        RequestWrapper requestWrapper = new RequestWrapper(request);
        ResponseWrapper responseWrapper = new ResponseWrapper(response);

        boolean b = limitFlow();
        if (b) {
            String result = "请求繁忙,已限流";
            log.error(result);
            responseWrapper.responseMessage(result);
            return;
        }

        filterChain.doFilter(requestWrapper, responseWrapper);
    }

    private boolean limitFlow() {
        Boolean limit10 = stringRedisTemplate.execute(redisScript, Collections.singletonList("LIMIT10"), "10", "3");
        if (Boolean.TRUE.equals(limit10)) {
            return true;
        }

        Boolean limit100 = stringRedisTemplate.execute(redisScript, Collections.singletonList("LIMIT100"), "100", "5");
        return Boolean.TRUE.equals(limit100);
    }

}

项目https://github.com/mingwulipo/cloud-demo.git

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值