Java教程

Springboot使用Redis-Cell实现限流

本文主要是介绍Springboot使用Redis-Cell实现限流,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、Redis-Cell安装如下

Redis-Cell限流插件安装(Centos)_毅呀毅呀哟-CSDN博客一、下载wget https://github.com/brandur/redis-cell/releases/download/v0.3.0/redis-cell-v0.3.0-x86_64-unknown-linux-gnu.tar.gz二、解压tar -zxvf redis-cell-v0.3.0-x86_64-unknown-linux-gnu.tar.gz三、得到如下四、复制.so文件的地址,在redis.conf文件中添加如下配置loadmodule /usr/l.https://blog.csdn.net/qq_39648029/article/details/121245348二、Redis-Cell指令介绍

CL.THROTTLE user123 15 30 60 1

 

 三、返回值

127.0.0.1:6379> CL.THROTTLE user123 15 30 60
1) (integer) 0     # 0允许,1拒绝
2) (integer) 16    # 容量,等于指令第二个参数 +1 
3) (integer) 15    # 剩余量
4) (integer) -1    #-1表示正常放入,0表示已满,正数表示几秒可放入(单位:秒)
5) (integer) 2     # 多长时间漏斗完全漏空(单位:秒)

四、spring boot代码

package com.zyweb.admin.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
 * redis 工具类
 * @Author ZhangYi
 */
@Component
public class RedisUtil {

    private final Logger logger = LoggerFactory.getLogger(RedisUtil.class);

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * lua 脚本
     */
    public static final String LUA_SCRIPT = "return redis.call('cl.throttle',KEYS[1], ARGV[1], ARGV[2], ARGV[3], ARGV[4])";
    
    /**
     * 测试
     *
     * @param key
     * @param maxBurst
     * @param countPerPeriod
     * @param period
     * @param quantity
     * @return
     */
    public boolean redisCellDemo(String key, int maxBurst, int countPerPeriod, int period, int quantity) {
        try {
            DefaultRedisScript<List> script = new DefaultRedisScript<>(LUA_SCRIPT, List.class);
            /**
             * KEYS[1]需要设置的key值,可以结合业务需要
             * ARGV[1]参数是漏斗的大小 最大爆发
             * ARGV[2]频率次数,结合ARGV[3]一起使用
             * ARGV[3]周期(秒),结合ARGV[2]一起使用
             *      最后的速率就是ARGV[2]次/ARGV[3]秒
             * ARGV[4]申请令牌数,默认是1
             */
            List<Long> rst = redisTemplate.execute(script, Arrays.asList(key), maxBurst, countPerPeriod, period, quantity);
            logger.info("限流{}返回:{}", key, rst);
            /**
             * 1. 动作是否受限:
             *   0 表示允许该操作。
             *   1 表示该操作受到限制/阻止。
             * 2. 密钥的总限制 (max_burst+1)。这相当于常见的X-RateLimit-Limit HTTP返回头。
             * 3. 密钥的剩余限制。相当于X-RateLimit-Remaining。
             * 4. 用户应重试之前的秒数,-1如果允许操作,则始终如此。相当于Retry-After。
             * 5. 限制将重置为其最大容量之前的秒数。相当于X-RateLimit-Reset。
             */
            //这里只关注第一个元素0表示正常,1表示过载
            return rst.get(0) == 0;
        } catch (Exception e) {
            logger.error("限流{}获取抛错:", key, e);
            return false;
        }
    }
}

 五、测试

    @GetMapping("/redisCell")
    public void redisCell(){
        // 模拟30次请求
        for (int i = 0; i < 30; i++) {
            boolean rst = redisUtil.redisCellDemo("user123 ", 5, 10, 30, 1);
            if (!rst) {
                logger.info("访问{}过于频繁,请稍后再试",i);
            } else {
                logger.info("访问{}通过",i);
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

六、demo表示,每秒有1个请求进入,漏斗最大容量为5,漏水速率为10个/30秒,也就是3秒钟漏掉一个

 

这篇关于Springboot使用Redis-Cell实现限流的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!