Redis+AOP+自定义注解实现限流

Redis+AOP+自定义注解实现限流

目录

Redis安装

下载

解压

准备编译

编译

测试编译

安装

配置

运行

检查端口是否在使用中

查看redis的当前版本:

使redis可以用systemd方式启动和管理

查看本地centos的版本:

客户端连接redis

Redis限流

1、引入依赖

2、application.yml配置

3、创建redisConfig,引入redisTemplate

自定义注解和拦截器

1、自定义注解

2、创建拦截器

3、将自定义拦截器加入到拦截器列表中

Redis安装

一提到Redis,相信大家都不会感到陌生吧。今天就让我们在阿里云上安装一下Redis,为以后使用它做个准备。

下载

1,下载页面

2,下载

解压

tar -xzvf redis-5.0.7.tar.gz

准备编译

1, 请在操作前确认gcc是否已安装,gcc -v

如未安装,可以执行这个命令安装:yum install gcc

2,请在操作前确认tcl是否已安装如未安装,可以执行这个命令安装:yum install tcl

编译 [root@localhost source]# cd redis-5.0.7/ [root@localhost redis-5.0.7]# make MALLOC=libc

make 后加 MALLOC的参数的原因:

避免提示找不到 jemalloc/jemalloc.h

测试编译 [root@localhost redis-5.0.7]# make test

如果看到以下字样:表示无错误:\o/ All tests passed without errors!

安装 [root@localhost redis-5.0.7]# mkdir /usr/local/soft/redis5 可分步创建 [root@localhost redis-5.0.7]# cd /usr/local/soft/redis5/ [root@localhost redis5]# mkdir bin [root@localhost redis5]# mkdir conf [root@localhost redis5]# cd bin/

find / -name redis-cli 查找文件位置

[root@localhost bin]# cp /root/redis-5.0.7/src/redis-cli ./ [root@localhost bin]# cp /root/redis-5.0.7/src/redis-server ./ [root@localhost bin]# cd …/conf/ [root@localhost conf]# cp /root/redis-5.0.7/redis.conf ./ 配置 [root@localhost conf]# vi redis.conf

设置以下两个地方:

# daemonize no daemonize yes # maxmemory <bytes> maxmemory 128MB

说明:分别是以daemon方式独立运行 / 内存的最大使用限制

运行 [root@localhost conf]# /usr/local/soft/redis5/bin/redis-server /usr/local/soft/redis5/conf/redis.conf 检查端口是否在使用中 [root@localhost conf]# netstat -anp | grep 6379 ​​​​​​​tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 16073/redis-server 查看redis的当前版本: [root@localhost conf]# /usr/local/soft/redis5/bin/redis-server -v ​​​​​​​Redis server v=5.0.7 sha=00000000:0 malloc=libc bits=64 build=8e31d2ed9a4c9593 使redis可以用systemd方式启动和管理

1,编辑service文件

[root@localhost liuhongdi]# vim /lib/systemd/system/redis.service

2,service文件内容:

[Unit]Description=RedisAfter=network.target [Service]Type=forkingPIDFile=/var/run/redis_6379.pidExecStart=/usr/local/soft/redis5/bin/redis-server /usr/local/soft/redis5/conf/redis.confExecReload=/bin/kill -s HUP $MAINPIDExecStop=/bin/kill -s QUIT $MAINPIDPrivateTmp=true [Install]WantedBy=multi-user.target

3.重载系统服务

[root@localhost liuhongdi]# systemctl daemon-reload

4,用来管理redis

启动

systemctl start redis

查看状态

systemctl status redis

使开机启动

systemctl enable redis

查看本地centos的版本: [root@localhost lib]# cat /etc/redhat-release CentOS Linux release 8.1.1911 (Core) 客户端连接redis

1、阿里云得设置redis.conf中的bind 后跟着的127.0.0.1修改为0.0.0.0,重启redis

2、开放端口:开放服务器的端口号,步骤如下:

打开实例列表,点击“ 更多”按钮,选择“ 网络和安全组 ”中的“安全组配置”,选择 “安全组列表”tab页面,点击 “配置规则”按钮,点击 “快速添加”按钮,勾选“Redis(6379)”,点击 “确定”之后就可以正常连接了。

3、给redis设置连接密码:

查找到# requirepass foobared 注释去掉并写入要设置的密码,例如:requirepass 123456

redis启动之后测试是否可以连接命令

./redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> auth 123456//此处是你的密码

注意: 如果是阿里云的话一定要设置密码,否则很可能被矿机程序注入定时任务,用你的服务器挖矿,阿里云一直会有信息提示你。

Redis限流

服务器上的Redis已经安装完成了(安装步骤见上文),今天就让我们使用Redis来做个小功能:自定义拦截器限制访问次数,也就是限流。

首先我们要在项目中引入Redis

1、引入依赖 <dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- redis依赖commons-pool 这个依赖一定要添加 --> <dependency>   <groupId>org.apache.commons</groupId>   <artifactId>commons-pool2</artifactId> </dependency> 2、application.yml配置 server: port: 8181 spring: redis:   host: 127.0.0.1   port: 6379   timeout: 10s   lettuce:     pool:     # 连接池中的最小空闲连接 默认0       min-idle: 0       # 连接池中的最大空闲连接 默认8       max-idle: 8       # 连接池最大连接数 默认8 ,负数表示没有限制       max-active: 8       # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认-1       max-wait: -1ms   #选择哪个库存储,默认是0   database: 0   password: 123456 3、创建redisConfig,引入redisTemplate @Configuration public class RedisConfig {    @Bean    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();        redisTemplate.setKeySerializer(new StringRedisSerializer());        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());        redisTemplate.setHashKeySerializer(new StringRedisSerializer());        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());        redisTemplate.setConnectionFactory(redisConnectionFactory);        return redisTemplate;   } } 自定义注解和拦截器 1、自定义注解 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented public @interface AccessLimit {    int seconds(); //秒数    int maxCount(); //最大访问次数    boolean needLogin()default true;//是否需要登录 } 2、创建拦截器 @Component public class FangshuaInterceptor extends HandlerInterceptorAdapter {    @Autowired    private RedisTemplate redisTemplate;    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        //判断请求是否属于方法的请求        if(handler instanceof HandlerMethod){            HandlerMethod hm = (HandlerMethod) handler;            //获取方法中的注解,看是否有该注解            AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);            if(accessLimit == null){                return true;           }            int seconds = accessLimit.seconds();            int maxCount = accessLimit.maxCount();            boolean login = accessLimit.needLogin();            String key = request.getRequestURI();            //如果需要登录            if(login){                //获取登录的session进行判断,此处只是例子,不写具体的业务                //.....                key+=""+"1";  //这里假设用户是1,项目中是动态获取的userId           }            //从redis中获取用户访问的次数            Integer count;            if(Objects.isNull(redisTemplate.opsForValue().get(key))){                count = 0;           }else{                count = (Integer) redisTemplate.opsForValue().get(key);           }            if(count == 0){                redisTemplate.opsForValue().set(key,1,seconds, TimeUnit.SECONDS);           }else if(count<maxCount){                //key的值加1                redisTemplate.opsForValue().increment(key);           }else{                //超出访问次数                Map<String,Object> errMap=new HashMap<>();                errMap.put("code",400);                errMap.put("msg","请求超时,请稍后再试");                render(response,errMap); //这里的CodeMsg是一个返回参数                return false;           }       }        return true;   }    private void render(HttpServletResponse response, Map<String,Object> errMap) throws Exception {        response.setContentType("application/json;charset=UTF-8");        OutputStream out = response.getOutputStream();        String str = JSON.toJSONString(errMap);        out.write(str.getBytes("UTF-8"));        out.flush();        out.close();   } } 3、将自定义拦截器加入到拦截器列表中 @Configuration public class WebConfig extends WebMvcConfigurerAdapter {    @Autowired    private FangshuaInterceptor interceptor;    @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(interceptor);   } }

最后做一下简单的测试

@RestController @RequestMapping("test") public class TestController {    //每三十秒最多可以请求三次,不需要登录    @AccessLimit(seconds=30, maxCount=3, needLogin=false)    @PostMapping("/fangshua")    public String fangshua(){        return "成功";   } }

以上就是Redis+AOP+自定义注解实现限流的详细内容,更多关于Redis限流的资料请关注易知道(ezd.cc)其它相关文章!

推荐阅读