当前位置: 首页 > news >正文

java Redisson 实现限流每秒/分钟/小时限制N个

1.引入maven包:

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.11.1</version></dependency>

2.代码实现:

a.RedissonConfig 初始化

package com.hanyc.demo.config;import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.ArrayList;
import java.util.List;/*** redisson** @author hanyc* @date 2024/12/31 13:30* @company: */
@Configuration
public class RedissonConfig {@Autowiredprivate RedisProperties redisProperties;@Beanpublic RedissonClient redissonClient() {Config config = new Config();if (redisProperties.getCluster() != null && !redisProperties.getCluster().getNodes().isEmpty()) {RedisProperties.Cluster cluster = redisProperties.getCluster();List<String> nodes = cluster.getNodes();List<String> newNodes = new ArrayList<>();nodes.forEach(index -> newNodes.add(index.startsWith("redis://") ? index : "redis://" + index));config.useClusterServers().addNodeAddress(newNodes.toArray(new String[0])).setPassword(redisProperties.getPassword());} else {String address = "redis://" + redisProperties.getHost() + ":" + redisProperties.getPort();config.useSingleServer().setAddress(address).setPassword(redisProperties.getPassword());}RedissonClient redisson = Redisson.create(config);return redisson;}
}

b.UserRateLimiterInterceptor  用户请求限流拦截器

package com.hanyc.demo.config;import cn.hutool.extra.servlet.ServletUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** @Description: 用户请求限流拦截器* @Author hanyc* @Date 2024/12/12**/
@Component
@Slf4j
public class UserRateLimiterInterceptor implements HandlerInterceptor {@Autowiredprivate RedissonClient redissonClient;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 假设这个方法能够从请求中解析出用户IDString userIdStr = "";String userIp = ServletUtil.getClientIP(request);// 假设用户ID 为 1String userId = "1";if (userId == null) {// 所有未登录账号 不需要验证的请求,都使用userId=10000userIdStr = userIp;} else {userIdStr = userId.toString();}// 为每个用户生成唯一的限流键String rateLimiterKey = "USER_RATE_LIMITER" + userIdStr;// 删除 Redis 中存储的限流器状态(清除缓存)// RRateLimiter 在内部将配置保存在 Redis 中,并且这些配置是持久化的。删除该键后,Redis 会丢失之前存储的限流配置,从而确保新的配置能够被应用。redissonClient.getBucket(rateLimiterKey).delete();// 获取分布式的 RRateLimiter 实例RRateLimiter rateLimiter = redissonClient.getRateLimiter(rateLimiterKey);// 初始化限流器,限制每两秒最多 10 次请求// 参数说明: // RateType.OVERALL 全局// rate 时间限制内可以请求多少次// rateInterval 多少时间内限制// 时间单位 可以秒/分钟/小时等rateLimiter.trySetRate(RateType.OVERALL, 10, 2, RateIntervalUnit.SECONDS);log.info("当前路由为:{} userIdStr:{} userIp:{}", request.getRequestURI(), userIdStr, userIp);// 尝试获取令牌,如果获取不到说明超过请求限制if (rateLimiter.tryAcquire()) {// 允许继续处理请求return true;} else {// 如果获取不到令牌,则说明请求超过了限制,可以在这里抛出异常或者返回错误信息log.warn("当前异常的路由为:{} userIdStr:{} userIp :{}", request.getRequestURI(), userIdStr, userIp);return false;}}}

c. WebMvcConfig 添加自定义拦截器

package com.hanyc.demo.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** MVC自定义配置** @author hanyc*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Beanpublic UserRateLimiterInterceptor userRateLimiterInterceptor() {return new UserRateLimiterInterceptor();}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(userRateLimiterInterceptor()).addPathPatterns("/**");}
}

3.测试

使用JMeter 发送请求. 每秒15个.

查看打印结果:

前10个请求正常响应. 后五个请求被拦截

http://www.lryc.cn/news/512854.html

相关文章:

  • 【漫话机器学习系列】029.累积分布函数(Cumulative Distribution Function)
  • 设计模式之访问者模式:一楼千面 各有玄机
  • AI 编程的世界:用Cursor编写评分项目
  • Cesium教程(二十三):Cesium实现下雨场景
  • SpringCloudAlibaba技术栈-Higress
  • uniapp 微信小程序开发使用高德地图、腾讯地图
  • Springboot:后端接收数组形式参数
  • Postman[2] 入门——界面介绍
  • 1月第四讲:Java Web学生自习管理系统
  • 【Redis】Redis 典型应用 - 缓存 (cache)
  • HTML——38.Span标签和字符实体
  • ROS2+OpenCV综合应用--10. AprilTag标签码追踪
  • python Celery 是一个基于分布式消息传递的异步任务队列系统
  • 嵌入式硬件杂谈(七)IGBT MOS管 三极管应用场景与区别
  • 麒麟信安云在长沙某银行的应用入选“云建设与应用领航计划(2024)”,打造湖湘金融云化升级优质范本
  • 好用的随机生成图片的网站
  • 添加 env 配置,解决import路径问题
  • Go work stealing 机制
  • 基础数据结构--二叉树
  • 《C++设计模式》策略模式
  • JavaScript学习记录6
  • 如何在没有 iCloud 的情况下将数据从 iPhone 传输到 iPhone
  • Doris安装部署
  • [服务器][教程]Ubuntu24.04 Server开机自动挂载硬盘教程
  • io多路复用, select, poll, epoll
  • k8s-1.28.2 部署prometheus
  • 记录第一次跑YOLOV8做目标检测
  • 使用Python爬取BOSS直聘职位数据并保存到Excel
  • node.js之---集群(Cluster)模块
  • SSM-Spring-IOC/DI对应的配置开发