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

news2025/1/4 19:13:38

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 {

    @Autowired
    private RedisProperties redisProperties;

    @Bean
    public 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 {

    @Autowired
    private RedissonClient redissonClient;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 假设这个方法能够从请求中解析出用户ID
        String userIdStr = "";
        String userIp = ServletUtil.getClientIP(request);
        // 假设用户ID 为 1
        String userId = "1";
        if (userId == null) {
            // 所有未登录账号 不需要验证的请求,都使用userId=10000
            userIdStr = 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 {

    @Bean
    public UserRateLimiterInterceptor userRateLimiterInterceptor() {
        return new UserRateLimiterInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(userRateLimiterInterceptor()).addPathPatterns("/**");
    }
}

3.测试

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

查看打印结果:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2269469.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2D图像测量到3D点云之物体三维尺寸测量!!!!

0&#xff0c;引言 本文将从双目采集的2D图像到3D点云进行转化&#xff0c;并进行物体尺寸测量&#xff0c;旨在为读者展示2D图像如何关联3D点云&#xff0c;并进行相关工业应用。 将2D图像转化为3D点云&#xff0c;并进行物体尺寸测量的技术&#xff0c;在工业领域有着广泛的…

【专题】2024年出口跨境电商促销趋势白皮书报告汇总PDF洞察(附原数据表)

原文链接&#xff1a;https://tecdat.cn/?p38722 在当今全球化加速演进、数字经济蓬勃发展的大背景下&#xff0c;跨境电商行业正以前所未有的态势重塑国际贸易格局&#xff0c;成为各方瞩目的焦点领域。 根据亚马逊发布的《2024年出口跨境电商促销趋势白皮书》&#xff0c;…

【亚马逊云】基于Amazon EC2实例部署 NextCloud 云网盘并使用 Docker-compose 搭建 ONLYOFFICE 企业在线办公应用软件

文章目录 1. 部署EC2实例2. 安装 Docker 服务3. 安装docker-compose4. 创建Docker-compose文件5. 创建nginx.conf文件6. 运行docker-compose命令开始部署7. 访问ONLYOFFICE插件8. 访问NextCloud云盘9. 下载并启用ONLYOFFICE插件10. 上传文件测试11. 所遇问题12. 参考链接 1. 部…

Flutter:打包apk,详细图文介绍

困扰了一天&#xff0c;终于能正常打包apk安装了&#xff0c;记录下打包的流程。建议参考我这篇文章时&#xff0c;同时看下官网的构建说明。 官网构建并发布 Android 应用详情 1、AS创建Flutter项目 2、cmd执行命令 生成一个sunluyi.jks的文件&#xff0c;可以自行把sunluyi替…

k8s部署nginx+sshd实现文件上传下载

要通过 nginx 和 sshd 实现文件的上传和下载&#xff0c;通常的做法是结合 SSH 协议和 HTTP 协议&#xff0c;使用 nginx 提供 Web 服务器功能&#xff0c;同时使用 sshd&#xff08;即 SSH 服务&#xff09;来处理通过 SSH 协议进行的文件传输。 SSH 实现文件的上传和下载&…

Java开发生态2024年度总结报告

1 关键要点 尽管数据显示 Java 17 是最常用 JDK&#xff0c;但其用户占比并未超过半数。根据 New Relic 2024 Java 生态系统状态报告&#xff0c;Java 17、11 和 8 的用户比例分别为 35%、33% 和 29%。New Relic 数据中所谓“快速采用”指 Java 21 的采用率仅为 1.4%。虽相较 J…

电路仿真软件PSIM简介

在从事开关电源相关产品开发的工程师或者正在学习开关电源的学习者&#xff0c;常常会用到各种仿真软件进行电路的仿真&#xff0c;不仅可以快速验证电路参数&#xff0c;还能清楚知道各器件的工作状态。 现在的电路仿真软件很多&#xff0c;例如matlab、Multisim、Simplis&…

文档大师:打造一站式 Word 报告解决方案1

前言 在政府、医院、银行、财务以及销售等领域&#xff0c;常常需要创建各种报告文件来展开工作汇报&#xff0c;譬如季度销售报告、年度总结报告、体检报告和保险合同等。在没有报表工具支持之前&#xff0c;这类报告主要通过 Word 制作&#xff0c;费时费力且难以维护&#…

电子电气架构 --- 安全相关内容汇总

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…

LeetCode--排序算法(堆排序、归并排序、快速排序)

排序算法 归并排序算法思路代码时间复杂度 堆排序什么是堆&#xff1f;如何维护堆&#xff1f;如何建堆&#xff1f;堆排序时间复杂度 快速排序算法思想代码时间复杂度 归并排序 算法思路 归并排序算法有两个基本的操作&#xff0c;一个是分&#xff0c;也就是把原数组划分成…

短视频矩阵系统搭建开发指导

在数字化营销的广阔天地中&#xff0c;抖音短视频已迅速崛起为一个拥有巨大影响力的社交媒体平台。随着其受众范围的日益扩大&#xff0c;采用有效的搜索引擎优化&#xff08;SEO&#xff09;策略以增强视频的曝光度和吸引流量变得至关重要。本文旨在阐述一种专为抖音短视频量身…

GitHub Fork 和 Clone 的深度指南:操作解析与 Pull Request 完整流程20241231

GitHub Fork 和 Clone 的深度指南&#xff1a;操作解析与 Pull Request 完整流程 快速导航 引言Fork 与 Clone 概念对比完整开发流程Pull Request 最佳实践常见问题与解决方案最佳实践建议实战案例 引言 在开发者的协作世界中&#xff0c;GitHub 就像一座桥梁&#xff0c;连…

典型常见的基于知识蒸馏的目标检测方法总结二

来源&#xff1a;https://github.com/LutingWang/awesome-knowledge-distillation-for-object-detection收录的方法 NeurIPS 2017&#xff1a;Learning Efficient Object Detection Models with Knowledge Distillation CVPR 2017&#xff1a;Mimicking Very Efficient Networ…

【分布式数据库与数据存储方案】详解

分布式数据库与数据存储方案 一、分布式数据库概述 &#xff08;一&#xff09;概念 分布式数据库是一种将数据分散存储在多个物理节点上的数据库系统&#xff0c;这些节点通过网络进行连接和通信&#xff0c;对外呈现出一个统一的逻辑数据库&#xff0c;用户或应用程序可以像…

【分布式文件存储系统Minio】2024.12保姆级教程

文章目录 1.介绍1.分布式文件系统2.基本概念 2.环境搭建1.访问网址2.账号密码都是minioadmin3.创建一个桶4.**Docker安装miniomc突破7天限制**1.拉取镜像2.运行容器3.进行配置1.格式2.具体配置 4.查看桶5.给桶开放权限 3.搭建minio模块1.创建一个oss模块1.在sun-common下创建2.…

产品经理2025年展望

产品经理作为连接技术、设计与市场需求的桥梁&#xff0c;在快速变化的商业环境中扮演着至关重要的角色。展望2025年&#xff0c;随着技术的不断进步和消费者需求的日益多样化&#xff0c;产品经理的工作将面临更多挑战与机遇。 一、人工智能与自动化深化应用&#xff1a; 到…

风力涡轮机缺陷检测数据集,91.4%准确识别率,18912张图片,支持yolo,PASICAL VOC XML,COCO JSON格式的标注

风力涡轮机缺陷检测数据集&#xff0c;91.4&#xff05;准确识别率&#xff0c;18912张图片&#xff0c;支持yolo&#xff0c;PASICAL VOC XML&#xff0c;COCO JSON格式的标注 数据集下载&#xff1a; &#xff59;&#xff4f;&#xff4c;&#xff4f; &#xff56;&#…

五、Vue 循环语句

文章目录 简介一、基础数组迭代二、对象属性迭代三、整数循环 简介 在 Vue.js 的世界里&#xff0c;当我们需要处理重复性的结构并依据数据动态渲染时&#xff0c;v-for 指令就成了不可或缺的工具&#xff0c;它赋予开发者简洁且强大的能力&#xff0c;轻松应对各种列表渲染场景…

用css实现瀑布流布局

上效果 知识理解 column-count: 4; column-gap: 15px;实现固定四行瀑布流布局 columns: 200px auto;column-gap: 15px;由浏览器根据容器的宽度自动调整&#xff0c;尽可能一行多个200px宽度的列数 <!DOCTYPE html> <html lang"en"><head><me…

275-增强型多功能数据采集卡PCIe-6251-EX

产品特点&#xff1a; 高速高精度数据采集&#xff0c;16bit10MSPS&#xff0c;32路单端/16路差分高速高精度任意波形发生&#xff0c;14bit165MHz&#xff0c;2路完全独立完全可编程的I/O端口&#xff0c;33个完全可编程的量程选择&#xff0c;0~5V/0~10V/5V/10VPCIe通信接口…