使用Redis和Nginx分别实现限制接口请求频率
前言
为啥需要限制接口请求频率?这个是因为防止接口一直被刷,比如发送手机验证码的接口,一直被刷的话,费钱费资源的,至少做点基本的防护工作。以下分别使用Redis和Nginx实现限制接口请求频率方案。
一、基于Redis实现接口限流
1.ZADD 命令
(1)用法:ZADD key score_1 value_1 score_2 value_2 ...
(2)作用:将一个或多个成员元素及其分数值加入到有序集当中。某个成员已经是有序集的成员,那么更新这个成员的分数值,并通过重新插入这个成员元素,来保证该成员在正确的位置上。分数值可以是整数值或双精度浮点数。
(3)返回值:被成功添加的新成员的数量,不包括那些被更新的、已经存在的成员。
(4)示例
redis > ZADD runoobkey 1 redis
(integer) 1
redis > ZADD runoobkey 2 mongodb
(integer) 1
redis > ZADD runoobkey 3 mysql
(integer) 1
redis > ZADD runoobkey 3 mysql
(integer) 0
redis > ZADD runoobkey 4 mysql
(integer) 0
redis > ZRANGE runoobkey 0 10 WITHSCORES1) "redis"
2) "1"
3) "mongodb"
4) "2"
5) "mysql"
6) "4"
2.ZREM 命令
(1)用法:ZREM key value_1 value_2 ...
(2)作用:移除有序集中的一个或多个成员,不存在的成员将被忽略。
(3)返回值:被成功添加的新成员的数量,不包括那些被更新的、已经存在的成员。
(4)示例
redis > ZRANGE runoobkey 0 10 WITHSCORES1) "redis"
2) "1"
3) "mongodb"
4) "2"
5) "mysql"
6) "4"redis > ZREM mongodb
(integer) 1redis > ZRANGE runoobkey 0 10 WITHSCORES
1) "redis"
2) "1"
3) "mysql"
4) "4"
3.ZCARD 命令
(1)用法:ZCARD key
(2)作用:获取有序集合中成员的数量。
(3)返回值:当key存在且是有序集类型时,返回有序集的基数。 当key不存在时,返回0 。
(4)示例
redis > ZADD myzset 1 "one"
(integer) 1
redis > ZADD myzset 2 "two"
(integer) 1
redis > ZCARD myzset
(integer) 2
4.ZREMRANGEBYSCORE 命令
(1)用法:ZREMRANGEBYSCORE key min max
(2)作用:移除有序集中,指定分数区间内的所有成员。
(3)返回值:被移除成员的数量。
(4)示例
redis > ZRANGE salary 0 -1 WITHSCORES
1) "tom"
2) "2000"
3) "peter"
4) "3500"
5) "jack"
6) "5000"redis > ZREMRANGEBYSCORE salary 1500 3500
(integer) 2redis> ZRANGE salary 0 -1 WITHSCORES
1) "jack"
2) "5000"
5.具体实现
(1)新建一个过滤器,如【/src/main/java/org/example/interceptor/RateLimiterInterceptor.java】
package org.example.interceptor;import cn.hutool.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;/*** 限流拦截器*/
@Component
public class RateLimiterInterceptor implements HandlerInterceptor {private static final String RATE_LIMITER_PREFIX = "Rate-Limiter:";private static final int LIMIT = 10; // 限流阈值private static final int TIME_WINDOW = 60; // 时间窗口,单位为秒@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {response.setCharacterEncoding("utf-8");response.setContentType("application/json");String key = RATE_LIMITER_PREFIX + request.getRequestURI() + ":" + request.getRemoteAddr(); // Rate-Limiter:/api/sendCode:127.0.0.1long currentTime = System.currentTimeMillis(); // 1703036748554long beforeTime = currentTime - TIME_WINDOW * 1000; // 1703036748554 - 60000 = 1703036688554// Long removeNum = stringRedisTemplate.opsForZSet().removeRangeByScore(K key, double min, double max); // 删除有序集合中分数在指定范围内的元素,返回删除元素的数量stringRedisTemplate.opsForZSet().removeRangeByScore(key, 0, beforeTime); // 删除有序集合中60秒之前存进去的所有数据,如:// Long memberNum = stringRedisTemplate.opsForZSet().size(K key); // 获取有序集合中元素的数量long count = stringRedisTemplate.opsForZSet().size(key); // 3if (count >= LIMIT) {HashMap<String, Object> responseObj = new HashMap<>();responseObj.put("code", HttpStatus.TOO_MANY_REQUESTS.value());responseObj.put("success", false);responseObj.put("msg", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());JSONObject json = new JSONObject(responseObj);response.getWriter().println(json);return false;} else {// Boolean addFlag = stringRedisTemplate.opsForZSet().add(K var1, V var2, double var3); // 向有序集合中添加一个或多个元素,并指定其分数stringRedisTemplate.opsForZSet().add(key, String.valueOf(currentTime), currentTime);// Boolean expireFlag = stringRedisTemplate.expire(K key, long timeout, TimeUnit unit); // 对指定key的数据设置过期时间stringRedisTemplate.expire(key, TIME_WINDOW, TimeUnit.SECONDS);return true;}}
}
(2)在SpringMVC配置类中注入此过滤器,如【/src/main/java/org/example/config/ResourceConfig.java】
package org.example.config;import org.example.interceptor.RateLimiterInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;@Configuration
public class ResourceConfig extends WebMvcConfigurationSupport {@Autowiredprivate RateLimiterInterceptor rateLimiterInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(rateLimiterInterceptor).addPathPatterns("/abcd/api/sendCode");}
}
6.运行效果
// ~
二、基于Nginx实现接口限流
1.在nginx.conf文件中新增限流配置
user nginx;
worker_processes 1;error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;events {worker_connections 1024;
}http {include /etc/nginx/mime.types;default_type application/octet-stream;log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';access_log /var/log/nginx/access.log main;sendfile on;#tcp_nopush on;keepalive_timeout 65;#gzip on;include /etc/nginx/conf.d/*.conf;# 负载均衡upstream springboot {server xxx.xxx.xxx.xxx:8080;}# limit_req_zone $binary_remote_addr zone=limit_zone:10m rate=10r/s; # 定义了一个名为limit_zone的限流区域,使用IP地址进行限流,该区域的大小为10MB,限流速率为10个请求每秒。limit_req_zone $binary_remote_addr zone=limit_zone:10m rate=10r/m; # 定义了一个名为limit_zone的限流区域,使用IP地址进行限流,该区域的大小为10MB,限流速率为10个请求每分钟。# 80端口的服务server { listen 80;server_name xxx.xxx.xxx.xxx;location / {alias html;index index.html index.htm;try_files $uri $uri/ /love/index.html;proxy_pass http://localhost;}location ^~ /love/ {root html/love;index index.html index.htm;proxy_pass http://localhost;}location ^~ /abcd/api/sendCode {# 在/xxx/api/sendCode接口的location中使用limit_req指令进行限流,限流区域为limit_zone,同时设置了一个瞬时突发流量为20个请求的阈值。# 这样,当同一个IP地址在一秒钟内发送超过10个请求到此接口时,Nginx会返回503错误码,表示请求被限流了。# limit_req zone=limit_zone burst=20;# 在/xxx/api/sendCode接口的location中使用limit_req指令进行限流,限流区域为limit_zone,同时设置了一个瞬时突发流量为5个请求的阈值。# 这样,当同一个IP地址在一秒钟内发送超过10个请求到此接口时,如果在一分钟内有超过10个请求,则允许其中的5个请求通过,nodelay表示不延迟响应,即立即返回503错误码。limit_req zone=limit_zone burst=5 nodelay;proxy_pass http://springboot;}}
}
2.运行效果
// ~
相关文章:
使用Redis和Nginx分别实现限制接口请求频率
前言 为啥需要限制接口请求频率?这个是因为防止接口一直被刷,比如发送手机验证码的接口,一直被刷的话,费钱费资源的,至少做点基本的防护工作。以下分别使用Redis和Nginx实现限制接口请求频率方案。 一、基于Redis实现…...
ansible模块 (7-13)
模块 7、hostname模块: 远程主机名管理模块 ansible 192.168.10.202 -m hostname -a nameliu 8、copy模块: 用于复制指定的主机文件到远程主机的模块 常用参数: dest: 指出要复制的文件在哪,必须使用绝对路径。如果源目标是…...
MySQL概括与SQL分类
文章目录 一、计算机语言二、SQL语言三、数据库系统四、MySQL简介 一、计算机语言 二、SQL语言 三、数据库系统 四、MySQL简介...
微信小程序:wx:for 获取view点击的元素currentTarget.dataset为空
遍历数组渲染一组view通过bindtap事件获取点击的元素 解决办法: 在遍历时,设置data-item即可。 示例: <view wx:for"{{types}}" data-item"{{item}}"wx:key"key" bindtap"syntheActiveItem"c…...
Word的兼容性问题很常见,禁用兼容模式虽步不是最有效的,但可以解决兼容性问题
当你在较新版本的Word应用程序中打开用较旧版本的Word创建的文档时,会出现兼容性问题。错误通常发生在文件名附近(兼容模式)。兼容性模式问题(暂时)禁用Word功能,从而限制使用较新版本Word的用户编辑文档。…...
环境搭建及源码运行_java环境搭建_idea版本下载及安装
1、介绍 Idea是一款被广泛使用的Java集成开发环境,它提供了丰富的功能和工具来帮助开发人员更高效地编写和调试代码。作为一款开源软件,Idea不仅提供了基本的代码编辑、自动完成和调试功能,还支持大量的插件和扩展,可为开发人员提…...
jvm相关命令操作
查看jvm使用情况 jmap -heap PID 查看线程使用情况 jstack pid 查看当前线程数 jstack 21294 |grep -E (#[0-9]) -o -c 查看系统线程数 top -H top -Hp pid #查看具体的进程中的线程信息 使用 jps 命令查看配置了JVM的服务 查看某个进程JVM的GC使用情况 jstat -gc 进程…...
芋道前端框架上线之后发现element-ui的icon图标全部乱码
前言 最近发现线上有人反映图标全部是乱码,登录上去看确实乱码,刷新就好最后一顿搜,发现是sass版本不兼容导致的图标乱码问题 解决办法 1.先把sass升级到1.39.0 2.来到vue.config.js文件配置代码-如果是芋道前端框架不用配置自带 css: {lo…...
每个伦敦金投资者都应该练习的日线图交易
在伦敦金市场中,每个投资者都应该试着去做日线图的交易。有的人一听到日线图马上摇头,原因是日线图的价格跨度大,导致止损距离也变大,这样对投资者来说无疑是增加了风险。如果资金量大的投资者还好说,可以降低仓位&…...
高通平台开发系列讲解(USB篇)adb应用adbd分析
沉淀、分享、成长,让自己和他人都能有所收获!😄 在apps_proc/system/core/adb/adb_main.cpp文件中main()函数会调用adb_main()函数,然后调用uab_init函数 在uab_init()函数中,会创建一个线程,在线程中会调用init_functionfs()函数,利用ep0控制节点,创建ep1、ep2输…...
【上海大学数字逻辑实验报告】七、中规模元件及综合设计
一、实验目的 掌握中规模时序元件的测试。学会在Quartus II上设计序列发生器。 二、实验原理 74LS161是四位可预置数二进制加计数器,采用16引脚双列直插式封装的中规模集成电路,其外形如下图所示: 其各引脚功能为: 异步复位输…...
JVM内存结构Java内存模型Java对象模型
导图: https://naotu.baidu.com/file/60a0bdcaca7c6b92fcc5f796fe6f6bc9 1.JVM内存结构&&Java内存模型&&Java对象模型 1.1.JVM内存结构 1.2.Java对象模型 Java对象模型表示的是这个对象本身的存储模型,JVM会给这个类创建一个instanceKlass保存在方…...
Istio 社区周报(第一期):2023.12.11 - 12.17
欢迎来到 Istio 社区周报 Istio 社区朋友们,你们好! 我很高兴呈现第一期 Istio 社区周报。作为 Istio 社区的一员,每周我将为您带来 Istio 的最新发展、有见地的社区讨论、专业提示和重要安全新闻内容。 祝你阅读愉快,并在下一期中…...
质量图导向法解包裹之---计算边缘可靠性
在这之前需要我们知道像素点的可靠性 % 这反映了相位变化的平滑程度。以下是一个可能的实现,它使用了二阶差分来计算可靠性: function rel calculateReliability(wrappedPhase)% 应用高斯滤波减少噪声filteredImg imgaussfilt(wrappedPhase, 2); % 2 …...
C# WPF上位机开发(进度条操作)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 软件上面如果一个操作比较缓慢,或者说需要很长的时间,那么这个时候最好添加一个进度条,提示一下当前任务的进展…...
vulnhub-Tre(cms渗透)
靶机和kali都使用net网络,方便探测主机获取ip1.靶机探测 使用fping扫描net网段 靶机ip:192.168.66.130 2.端口扫描 扫描发现该靶机三个端口,ssh,还有两个web,使用的中间件也是不一样的,一个是apache&…...
Re解析(正则表达式解析)
正则表达式基础 元字符 B站教学视频: 正则表达式元字符基本使用 量词 贪婪匹配和惰性匹配 惰性匹配如下两张图,而 .* 就表示贪婪匹配,即尽可能多的匹配到符合的字符串,如果使用贪婪匹配,那么结果就是图中的情况三 p…...
HTML输出特殊字符详细方法
以下是部分特殊字符代码表,它们的完整应用代码格式为:&#;用下面的四位数字替换,将得到对应的符号。(注意:应用这些代码,编辑器应该切换到HTML模式) ☏260f ☎260e ☺263a ☻263b ☼263c ☽…...
《漫画算法》笔记——计算两个大数的和
例题: 输入:“123”,“234” 输出:“357” 思路: 使用数组,分别计算每一位上的加和,注意记录进位信息。 然后,将数组恢复成字符串,输出。 值得注意的是,加和…...
Python3.13版本改进规划
大家好,最近faster-cpython 项目的文档介绍了关于 Python 3.13 的规划,以及在 3.13 版本中将要实现的一些优化和改进。faster-python 是 Python 的创始人 Guido van Rossum 和他的团队提出的计划 ,目标是在四年内将 CPython 的性能提升五倍。…...
AMFITRACK Gen3开发套件开箱测评:如何用电磁追踪技术搞定VR定位难题?
AMFITRACK Gen3开发套件深度评测:电磁追踪如何重塑VR定位体验 拆开AMFITRACK Gen3开发套件的包装箱时,那种精密仪器特有的金属质感立刻传递到指尖。作为第三代电磁运动跟踪系统的代表,这套设备正在挑战VR领域沿用多年的光学定位霸权。不同于需…...
[小红书AI自动化教程]凌晨2点我在睡觉,AI偷偷发了篇小红书爆款:醒来99+点赞,人类社媒苦役终结?
我把小红书交给 OpenClaw,它开始自己干活了 凌晨两点,我在睡觉,它却偷偷发了一篇爆款。 醒来点赞99,评论全是“姐妹求链接”。这不是科幻。去年我还为追热点熬夜秃头,如今一句“今天发什么”,AI 就能完成选…...
SleeperX:如何彻底解决MacBook电源管理的3个核心痛点
SleeperX:如何彻底解决MacBook电源管理的3个核心痛点 【免费下载链接】SleeperX MacBook prevent idle/lid sleep! Hackintosh sleep on low battery capacity. 项目地址: https://gitcode.com/gh_mirrors/sl/SleeperX 你是否经历过这些场景?正在…...
建立情感绑架链:让团队恐惧失去你——软件测试从业者的职场影响力解析
测试工程师的隐形权力困境 在软件研发体系中,测试工程师常陷入价值被低估的困境。当迭代压力激增时,测试周期首当其冲被压缩;当线上出现故障时,测试环节却成为追责焦点。这种结构性矛盾催生出一种特殊的职场生存策略——通过构建…...
SAM3问题解决:分割不准?试试调整检测阈值和提示词
SAM3问题解决:分割不准?试试调整检测阈值和提示词 1. 问题现象与原因分析 1.1 常见分割问题表现 在使用SAM3进行图像分割时,用户可能会遇到以下几种典型问题: 过度分割:一个物体被分割成多个不连续的部分欠分割&am…...
ChatGPT归档数据恢复机制深度解析:原理与实战指南
ChatGPT归档数据恢复机制深度解析:原理与实战指南 在AI应用开发中,数据管理是一个绕不开的话题。随着项目迭代和用户量增长,对话记录、训练数据、配置信息等会迅速累积。为了平衡存储成本与数据可用性,归档(Archive&a…...
从Python调包侠到量化研究员:我的3年转型踩坑实录与学习路线图
从Python调包侠到量化研究员:我的3年转型踩坑实录与学习路线图 三年前,我还是一名只会用Python调包的数据工程师,每天的工作就是清洗数据、跑模型、生成报表。直到某次聚会上,一位在私募基金做量化的朋友随口提了句"我们组去…...
AI科学发现新范式!NSR综述知识图谱应用全解(非常详细),从入门到精通,收藏这一篇就够了!
在生物、化学、材料等数据密集型科学领域,海量实验数据与文献知识不断积累,但这些知识往往分散在不同数据库与研究论文中,难以被系统整合与有效利用。科学知识图谱(Scientific Knowledge Graphs, SciKGs)通过结构化方式…...
Oracle Product Hub Portal Cloud(简称 OPH Cloud)是 Oracle 提供的基于云的主数据管理(MDM)解决方案
Oracle Product Hub Portal Cloud(简称 OPH Cloud)是 Oracle 提供的基于云的主数据管理(MDM)解决方案,专为统一、治理和分发产品主数据而设计。它是 Oracle Cloud Enterprise Resource Planning (ERP)、Supply Chain M…...
MedGemma-X性能优化:基于CUDA的医疗影像加速处理
MedGemma-X性能优化:基于CUDA的医疗影像加速处理 1. 当医生等结果的时间,能不能再短一点? 上周陪家人做肺部CT复查,从扫描结束到拿到报告,中间隔了近40分钟。放射科医生说,现在AI辅助系统已经能帮着初筛&…...
