Java实战:Spring Boot项目中如何利用Redis实现用户IP接口限流

引言

在高并发的Web应用中,接口限流是一项至关重要的技术手段,它有助于保护系统资源,防止因瞬间流量高峰导致服务崩溃。本文将深入探讨如何在Spring Boot项目中借助Redis实现用户IP级别的接口限流策略,通过具体的代码示例,详细介绍其设计思路与实现过程。

一、限流策略与Redis选择

  1. 限流策略

    常见的限流算法有令牌桶(Token Bucket)、漏桶(Leaky Bucket)和滑动窗口(Sliding Window)。在用户IP级别限流中,我们可以选择基于Redis的键值存储特性,结合Lua脚本,实现滑动窗口算法的限流策略,兼顾灵活性和高性能。

  2. 为何选择Redis

    Redis作为一款高性能的内存型数据库,具备优秀的数据结构和原子操作能力,非常适合用于限流场景。其键过期机制可以轻松实现限流窗口期的设定,同时,通过Redis的lua脚本支持,可以原子化地进行读写操作,确保限流逻辑的准确性。

二、Spring Boot集成Redis

  1. 添加Redis依赖

    在Spring Boot项目中,通过引入spring-boot-starter-data-redis依赖,方便地集成Redis:

    <!-- Maven -->
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    
  2. 配置Redis连接

    application.propertiesapplication.yml中配置Redis连接信息:

    spring.redis.host=127.0.0.1
    spring.redis.port=6379
    

三、基于Redis实现用户IP限流

  1. 限流Key设计

    为每个用户IP设置唯一的限流Key,格式如下:

    rate_limit:ip:<用户IP>:<接口名>
    
  2. Lua脚本设计

    编写Lua脚本来实现滑动窗口限流逻辑,该脚本的主要功能是检查指定IP在最近N秒内对特定接口的访问次数,如果超过预设阈值,则拒绝请求。

    -- lua-script.lua
    local key = KEYS[1] -- 用户IP限流key
    local limit = tonumber(ARGV[1]) -- 访问次数阈值
    local window = tonumber(ARGV[2]) -- 时间窗口(单位:秒)local current_timestamp = redis.call('TIME')[1]
    local requests = redis.call('ZRANGEBYSCORE', key, current_timestamp - window, '+inf')if #requests >= limit thenreturn 0 -- 限流
    endredis.zadd(key, current_timestamp, current_timestamp)
    return 1 -- 允许请求
    
  3. Spring Boot限流服务实现

    创建一个限流服务,封装限流逻辑,并在AOP中实现拦截与限流判定:

    @Service
    public class RateLimiterService {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;public boolean isAllowed(String ip, String apiName, int limit, int windowSeconds) {DefaultRedisScript<Boolean> script = new DefaultRedisScript<>(new ClassPathResource("lua-script.lua"), Boolean.class);script.setNumKeys(1);List<String> keys = Collections.singletonList("rate_limit:ip:" + ip + ":" + apiName);List<Object> args = Arrays.asList(limit, windowSeconds);Boolean allowed = redisTemplate.execute(script, keys, args);return allowed != null && allowed;}
    }@Aspect
    @Component
    public class RateLimitAspect {@Autowiredprivate RateLimiterService rateLimiterService;@Around("@annotation(com.example.RateLimited)")public Object around(ProceedingJoinPoint pjp) throws Throwable {MethodSignature signature = (MethodSignature) pjp.getSignature();RateLimited rateLimited = signature.getMethod().getAnnotation(RateLimited.class);HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();String ip = request.getHeader("X-Real-IP");if (!rateLimiterService.isAllowed(ip, signature.getMethod().getName(), rateLimited.limit(), rateLimited.window())) {throw new ApiException(HttpStatus.TOO_MANY_REQUESTS, "请求过于频繁,请稍后再试!");}return pjp.proceed();}
    }
    

    注:RateLimited是一个自定义的注解,用于标记需要限流的接口方法。

四、优化与扩展

  1. 自定义注解与限流策略

    可以根据业务需求,创建不同的限流注解,并在注解中定义不同的限流策略,如全局限流、用户ID限流等。

  2. 降级策略

    当达到限流阈值时,除了拒绝请求外,还可以采取降级策略,如返回默认数据、进入等待队列、发送警告通知等。

  3. 分布式限流

    在分布式环境下,需要考虑分布式锁或Redlock机制,确保限流逻辑的一致性。

五、结论

通过本文,我们了解了如何在Spring Boot项目中利用Redis实现用户IP级别的接口限流,从限流策略的设计、Redis的集成、Lua脚本的编写到最终的AOP拦截,形成了一套完整的解决方案。在实际项目中,应根据具体需求灵活调整限流策略,并结合其他手段如熔断、降级等,构建健壮的高并发服务体系。

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

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

相关文章

大数据概述

学习大数据有什么用&#xff1f; 2010年&#xff1a;大数据技术体系开始在国内火热 2015年&#xff1a;国务院印发《促进大数据发展行动纲要》 2016年&#xff1a;发改委发布关于组织实施促进大数据发展重大工程的通知 2017年&#xff1a;工信部印发大数据产业规划(2016-20…

Linux运维_Bash脚本_构建安装Meson-1.0.1和Ninja-1.11.1

Linux运维_Bash脚本_构建安装Meson-1.0.1和Ninja-1.11.1 Bash (Bourne Again Shell) 是一个解释器&#xff0c;负责处理 Unix 系统命令行上的命令。它是由 Brian Fox 编写的免费软件&#xff0c;并于 1989 年发布的免费软件&#xff0c;作为 Sh (Bourne Shell) 的替代品。 您…

Nginx高级技巧:实现负载均衡和反向代理

文章目录 Nginx概述Nginx作用正向代理反向代理负载均衡动静分离 Nginx的安装 -->Docker3.1 安装Nginx3.2 Nginx的配置文件3.3 修改docker-compose文件 Nginx源码安装nginx常用命令nginx配置文件配置文件位置配置文件结构详情 Nginx的反向代理【重点】基于Nginx实现反向代理4…

C语言冒泡排序(高级版)

目录: 冒泡排序的原理 主函数 "冒泡排序函数" 比较函数 交换函数 最终输出 完整代码 冒泡排序的原理: 冒泡排序的原理是&#xff1a;从左到右&#xff0c;相邻元素进行比较。每次比较一轮&#xff0c;就会找到序列中最大的一个或最小的一个。这个数就会从序列的最右…

Windows上构建一个和Linux类似的Terminal

preview 目的是在Windows上构建一个和Linux类似的Terminal&#xff0c;让Windows炼丹和Linux一样舒适&#xff0c;同是让Terminal取代Xshell完成远程链接。 预览如下图 在Linux下我们使用zsh和oh-my-zsh结合&#xff0c;Windows下我们使用powershell7和oh-my-posh结合。 前提…

Vue 前端开发 v-for和v-if两个指令不能混合使用

原由&#xff1a; 在进行项目开发的时候因为在一个标签上同时使用了v-for和v-if两个指令导致的报错。 提示错误&#xff1a;The undefined variable inside v-for directive should be replaced with a computed property that returns filtered array instead. You should no…

nginx------------缓存功能 ip透传 负载均衡 (六)

一、http 协议反向代理 &#xff08;一&#xff09;反向代理示例:缓存功能 缓存功能可以加速访问&#xff0c;如果没有缓存关闭后端服务器后&#xff0c;图片将无法访问&#xff0c;缓存功能默认关闭&#xff0c;需要开启。 ​ proxy_cache zone_name | off; 默认off #指明调…

基于Springboot纯净水配送和商城系统设计与实现 开题报告参考

博主介绍&#xff1a;黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者&#xff0c;CSDN博客专家&#xff0c;在线教育专家&#xff0c;CSDN钻石讲师&#xff1b;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程&#xff…

2023 版王道单科书勘误汇总(3.30)

注:因2023版对题目编号做了优化“历年真题全部放最后、且按年份排序”&#xff0c;以方便大家根据需要保留某些年份的真题作为最后的模拟。所以造成了一些题目和解析的编号错误。 数据结构: P11 P20 P56 P278 P326 “2.”中第 3 行”题 5改成”9”&#xff0c;第6行”题 8”改成…

css3详解

一.什么是CSS3 CSS3是Cascading Style Sheets的第三个版本&#xff0c;是一种用于描述文档样式的语言&#xff08;CSS3是CSS&#xff08;层叠样式表&#xff09;技术的升级版本&#xff09;。它是前端开发中用于控制网页布局和样式的技术之一。CSS3引入了许多新的特性和功能&a…

Linux常用操作命令大全

Linux常用操作命令大全 Linux,作为一款开源的操作系统,深受全世界开发者和系统管理员的喜爱。在Linux环境下,用户通过命令行界面可以执行各种操作,从而实现对系统的全面控制。本文将详细介绍Linux中常用的操作命令,帮助读者更好地理解和运用这些命令。 一、文件操作命令…

hexo图片显示不出且图片路径错误/.com//

参考博客&#xff1a; hexo 图片显示问题及使用typora设置图片路径-CSDN博客 javascript - hexo 图片路径错误/.com// - SegmentFault 思否 先说如何让hexo图片成功地显示出来 Step1: 修改config设置 将 _config.yml 设置文件中的 post_asset_folder 修改为 true 这一步的作…

平衡二叉树,二叉树的路径,左叶子之和

第六章 二叉树part04 今日内容&#xff1a; 110.平衡二叉树 257. 二叉树的所有路径 404.左叶子之和 110.平衡二叉树 &#xff08;优先掌握递归&#xff09; 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&am…

【不可不知的考研复试秘籍 1】

----------------------------------------------------------------------------------------------------- 考研复试科研背景提升班 教你快速深入了解掌握考研复试面试中的常见问题以及注意事项&#xff0c;系统的教你如何在短期内快速提升自己的专业知识水平和编程以及英语…

windows下安装cnpm

cnpm是淘宝团队开发的一个针对中国用户的npm镜像源&#xff0c;它是npm的一个定制版本。由于国外的npm源在国内访问速度较慢&#xff0c;所以cnpm镜像源可以提供更快的下载速度。cnpm的使用方式与npm基本相同&#xff0c;只需将npm替换为cnpm即可。 要想使用cnpm等先安装node.…

反序列化逃逸 [安洵杯 2019]easy_serialize_php1

打开题目 题目源码&#xff1a; <?php$function $_GET[f];function filter($img){$filter_arr array(php,flag,php5,php4,fl1g);$filter /.implode(|,$filter_arr)./i;return preg_replace($filter,,$img); }if($_SESSION){unset($_SESSION); }$_SESSION["user&qu…

每日一题 KY148还是畅通工程

某省调查乡村交通状况&#xff0c;得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通&#xff08;但不一定有直接的公路相连&#xff0c;只要能间接通过公路可达即可&#xff09;&#xff0c;并要求铺设的公路总长度…

PostgreSQL对已有表增加自增序列

对已有表增加自增序列&#xff1a; 1、在PostgreSQL当中&#xff0c;我们要实现对已有表的ID字段自增。 首先需创建一个关联序列&#xff0c;以下sql语句是创建一个序列&#xff1a; CREATE SEQUENCE menu_id_seq START 6000001; 序列名称是menu_id_seq&#xff0c;起始…

sizeof 和 strlen的区别

sizeof sizeof是单目操作符,sizeof计算变量所栈内存空间大小,单位是字节,如果操作数是类型的话,会计算类型所占大小,sizeof指在乎占用内存空间大小不在乎内容是什么. int main() {int a 0;printf("%zd\n", sizeof(a));printf("%zd\n", sizeof a );printf…

巧【二叉搜索树的最近公共祖先】【二叉搜索树的性质】Leetcode 235. 二叉搜索树的最近公共祖先

【二叉搜索树的最近公共祖先】【二叉搜索树性质】Leetcode 235. 二叉搜索树的最近公共祖先 【巧】解法1 利用二叉搜索树有序的性质解法2 采用二叉树求最近公共祖先的方法——后序遍历 ---------------&#x1f388;&#x1f388;235. 二叉搜索树的最近公共祖先 题目链接&#x…