Spring Boot 接口访问频率限制的实现详解
目录
- 概述
- 为什么需要接口访问频率限制
- 常见的实现方式
- 基于过滤器的实现
- 基于拦截器的实现
- 基于第三方库Bucket4j的实现
- 实际代码示例
- 基于过滤器实现Rate Limiting
- 基于拦截器实现Rate Limiting
- 使用Bucket4j实现Rate Limiting
- 最佳实践
- 选择合适的限流算法
- 优化性能
- 记录日志和监控
- 总结
概述
接口访问频率限制是通过在一定时间内限制用户对接口的访问次数来实现的。常见的限流算法包括令牌桶算法(Token Bucket)、漏桶算法(Leaky Bucket)、固定窗口计数器(Fixed Window Counter)和滑动窗口计数器(Sliding Window Counter)等。在Spring Boot中,我们可以通过多种方式来实现接口的限流,如使用过滤器、拦截器或者借助第三方库。
为什么需要接口访问频率限制
- 防止恶意攻击:通过限制接口的访问频率,可以有效防止恶意用户或机器人频繁访问接口,导致系统资源耗尽。
- 提升系统稳定性:在高并发场景下,限流可以有效保护后端服务,避免因流量过大而导致系统崩溃。
- 提升用户体验:合理的限流可以保障所有用户都能获得较好的服务质量,避免个别用户过度使用资源。
常见的实现方式
基于过滤器的实现
过滤器是Java Web应用中常用的一种组件,它可以在请求到达Servlet之前对请求进行预处理。通过在过滤器中实现限流逻辑,可以对所有的HTTP请求进行统一的限流控制。
基于拦截器的实现
拦截器是Spring框架提供的一种处理器,可以在请求处理之前和之后进行相关操作。相比于过滤器,拦截器可以更加细粒度地控制请求,适用于需要针对某些特定接口进行限流的场景。
基于第三方库Bucket4j的实现
Bucket4j是一个Java实现的高性能限流库,它支持多种限流算法,如令牌桶算法。通过使用Bucket4j,可以轻松地在Spring Boot应用中实现复杂的限流逻辑,并且它还提供了丰富的配置选项和统计功能。
实际代码示例
基于过滤器实现Rate Limiting
首先,我们需要创建一个自定义的过滤器类,并在其中实现限流逻辑。以下是一个示例代码:
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;public class RateLimitingFilter implements Filter {private final ConcurrentMap<String, Long> requestCounts = new ConcurrentHashMap<>();private static final long ALLOWED_REQUESTS_PER_MINUTE = 60;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化过滤器}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;HttpServletResponse httpResponse = (HttpServletResponse) response;String clientIp = httpRequest.getRemoteAddr();long currentTimeMillis = System.currentTimeMillis();requestCounts.putIfAbsent(clientIp, currentTimeMillis);long lastRequestTime = requestCounts.get(clientIp);if (TimeUnit.MILLISECONDS.toMinutes(currentTimeMillis - lastRequestTime) < 1) {long requestCount = requestCounts.values().stream().filter(time -> TimeUnit.MILLISECONDS.toMinutes(currentTimeMillis - time) < 1).count();if (requestCount > ALLOWED_REQUESTS_PER_MINUTE) {httpResponse.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);httpResponse.getWriter().write("Too many requests");return;}}requestCounts.put(clientIp, currentTimeMillis);chain.doFilter(request, response);}@Overridepublic void destroy() {// 销毁过滤器}
}
然后,在Spring Boot应用的配置类中注册这个过滤器:
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<RateLimitingFilter> loggingFilter(){FilterRegistrationBean<RateLimitingFilter> registrationBean = new FilterRegistrationBean<>();registrationBean.setFilter(new RateLimitingFilter());registrationBean.addUrlPatterns("/api/*");return registrationBean;}
}
基于拦截器实现Rate Limiting
首先,我们需要创建一个自定义的拦截器类,并在其中实现限流逻辑。以下是一个示例代码:
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;public class RateLimitingInterceptor implements HandlerInterceptor {private final ConcurrentMap<String, Long> requestCounts = new ConcurrentHashMap<>();private static final long ALLOWED_REQUESTS_PER_MINUTE = 60;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String clientIp = request.getRemoteAddr();long currentTimeMillis = System.currentTimeMillis();requestCounts.putIfAbsent(clientIp, currentTimeMillis);long lastRequestTime = requestCounts.get(clientIp);if (TimeUnit.MILLISECONDS.toMinutes(currentTimeMillis - lastRequestTime) < 1) {long requestCount = requestCounts.values().stream().filter(time -> TimeUnit.MILLISECONDS.toMinutes(currentTimeMillis - time) < 1).count();if (requestCount > ALLOWED_REQUESTS_PER_MINUTE) {response.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);response.getWriter().write("Too many requests");return false;}}requestCounts.put(clientIp, currentTimeMillis);return true;}
}
然后,在Spring Boot应用的配置类中注册这个拦截器:
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.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate RateLimitingInterceptor rateLimitingInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(rateLimitingInterceptor).addPathPatterns("/api/**");}
}
使用Bucket4j实现Rate Limiting
首先,在项目中引入Bucket4j依赖:
<dependency><groupId>com.github.vladimir-bukhtoyarov</groupId><artifactId>bucket4j-core</artifactId><version>7.0.0</version>
</dependency>
然后,创建一个自定义的过滤器类,并在其中实现限流逻辑:
import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Bucket;
import io.github.bucket4j.Bucket4j;
import io.github.bucket4j.Refill;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.Duration;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;public class Bucket4jRateLimitingFilter implements Filter {private final ConcurrentMap<String, Bucket> buckets = new ConcurrentHashMap<>();@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化过滤器}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;HttpServletResponse httpResponse = (HttpServletResponse) response;String clientIp = httpRequest.getRemoteAddr();Bucket bucket = buckets.computeIfAbsent(clientIp, this::newBucket);if (bucket.tryConsume(1)) {chain.doFilter(request, response);} else {httpResponse.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);httpResponse.getWriter().write("Too many requests");}}private Bucket newBucket(String clientIp) {return Bucket4j.builder().addLimit(Bandwidth.classic(60, Refill.greedy(60, Duration.ofMinutes(1)))).build();}@Overridepublic void destroy() {// 销毁过滤器}
}
然后,在Spring Boot应用的配置类中注册这个过滤器:
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<Bucket4jRateLimitingFilter> loggingFilter(){FilterRegistrationBean<Bucket4jRateLimitingFilter> registrationBean = new FilterRegistrationBean<>();registrationBean.setFilter(new Bucket4jRateLimitingFilter());registrationBean.addUrlPatterns("/api/*");return registrationBean;}
}
最佳实践
选择合适的限流算法
根据实际业务需求选择合适的限流算法,例如:
- 令牌桶算法:适用于需要平滑突发流量的场景。
- 漏桶算法:适用于需要严格控制流量的场景。
- 固定窗口计数器:适用于对简单限流要求的场景。
- 滑动窗口计数器:适用于需要精确控制限流的场景。
优化性能
- 减少锁竞争:在高并发环境下,尽量减少锁的使用,可以采用无锁数据结构或者线程安全的数据结构。
- 缓存结果:对于频繁访问的数据,可以考虑进行缓存,减少数据库查询的次数。
- 异步处理:对于耗时的操作,可以考虑采用异步处理,提高系统的响应速度。
记录日志和监控
- 记录访问日志:记录每次接口访问的详细信息,包括请求时间、IP地址、请求路径等。
- 监控限流情况:对限流情况进行监控,及时发现和处理异常流量。
- 报警机制:设置限流报警机制,当流量超过预设阈值时,及时报警。
总结
本文详细介绍了在Spring Boot中实现接口访问频率限制的几种方法,包括基于过滤器、拦截器和第三方库Bucket4j的实现。通过合理的限流策略,可以有效防止恶意攻击,提升系统的稳定性和用户体验。在实际应用中,选择合适的限流算法和实现方式,并结合业务需求进行优化,是确保系统高效运行的关键。
希望本文能够帮助你更好地理解和实现Spring Boot中的接口访问频率限制。如果你有任何问题或建议,欢迎在评论区留言讨论。
相关文章:
Spring Boot 接口访问频率限制的实现详解
目录 概述为什么需要接口访问频率限制常见的实现方式 基于过滤器的实现基于拦截器的实现基于第三方库Bucket4j的实现 实际代码示例 基于过滤器实现Rate Limiting基于拦截器实现Rate Limiting使用Bucket4j实现Rate Limiting 最佳实践 选择合适的限流算法优化性能记录日志和监控…...
前端页面:用户交互持续时间跟踪(duration)user-interaction-tracker
引言 在用户至上的时代,精准把握用户行为已成为产品优化的关键。本文将详细介绍 user-interaction-tracker 库,它提供了一种高效的解决方案,用于跟踪用户交互的持续时间,并提升项目埋点的效率。通过本文,你将了解到如…...
中文分词库 jieba 详细使用方法与案例演示
1 前言 jieba 是一个非常流行的中文分词库,具有高效、准确分词的效果。 它支持3种分词模式: 精确模式全模式搜索引擎模式 jieba0.42.1测试环境:python3.10.9 2 三种模式 2.1 精确模式 适应场景:文本分析。 功能࿱…...
EXO-helper解释
目录 helper解释 helper解释 在Python中,字符串 "\033[93m" 是一个ANSI转义序列,用于在支持ANSI转义码的终端或控制台中改变文本的颜色。具体来说,\033[93m 用于将文本颜色设置为亮黄色(或浅黄色,具体取决于终端的显示设置)。 这里的 \033 实际上是八进制的 …...
Qt开发网络嗅探器01
引言 随着互联网的快速发展和普及,人们对网络性能、安全和管理的需求日益增长。在复杂的网络环境中,了解和监控网络中的数据流量、安全事件和性能问题变得至关重要。为了满足这些需求,网络嗅探器作为一种重要的工具被 广泛应用。网络嗅探器是…...
mysql面试(三)
MVCC机制 MVCC(Multi-Version Concurrency Control) 即多版本并发控制,了解mvcc机制,需要了解如下这些概念 事务id 事务每次开启时,都会从数据库获得一个自增长的事务ID,可以从事务ID判断事务的执行先后…...
阿里云公共DNS免费版自9月30日开始限速 企业或商业场景需使用付费版
本周阿里云发布公告对公共 DNS 免费版使用政策进行调整,免费版将从 2024 年 9 月 30 日开始按照请求源 IP 进行并发数限制,单个 IP 的请求数超过 20QPS、UDP/TCP 流量超过 2000bps 将触发限速策略。 阿里云称免费版的并发数限制并非采用固定的阈值&…...
捷配生产笔记-一文搞懂阻焊层基本知识
什么是阻焊层? 阻焊层(也称为阻焊剂)是应用于PCB表面的一层薄薄的聚合物材料。其目的是保护铜电路,防止焊料在焊接过程中流入不需要焊接的区域。除焊盘外,整个电路板都涂有阻焊层。 阻焊层应用于 PCB 的顶部和底部。树…...
html 常用css样式及排布问题
1.常用样式 <style>.cy{width: 20%;height: 50px;font-size: 30px;border: #20c997 solid 3px;float: left;color: #00cc00;font-family: 黑体;font-weight: bold;padding: 10px;margin: 10px;}</style> ①宽度(长) ②高度(宽&a…...
【SpingCloud】客户端与服务端负载均衡机制,微服务负载均衡NacosLoadBalancer, 拓展:OSI七层网络模型
客户端与服务端负载均衡机制 可能有第一次听说集群和负载均衡,所以呢,我们先来做一个介绍,然后再聊服务端与客户端的负载均衡区别。 集群与负载均衡 负载均衡是基于集群的,如果没有集群,则没有负载均衡这一个说法。 …...
【Elasticsearch】Elasticsearch 中的节点角色
Elasticsearch 中的节点角色 1.主节点(master)1.1 专用候选主节点(dedicated master-eligible node)1.2 仅投票主节点(voting-only master-eligible node) 2.数据节点(data)2.1 内容…...
pip install与apt install区别
pipapt/apt-get安装源PyPI 的 python所有依赖的包软件、更新源、ubuntu的依赖包 1 查看pip install 安装的数据包 命令 pip list 2 查看安装包位置 pip show package_name参考 https://blog.csdn.net/nebula1008/article/details/120042766...
分表分库是一种数据库架构的优化策略,用于处理大规模数据和高并发请求,提高数据库的性能和可扩展性。
分表分库是一种数据库架构的优化策略,用于处理大规模数据和高并发请求,提高数据库的性能和可扩展性。以下是一些常见的分表分库技术方案: 1. **水平分表(Horizontal Sharding)**: - 将单表数据根据某个…...
【ffmpeg命令入门】获取音视频信息
文章目录 前言使用ffmpeg获取简单的音视频信息输入文件信息文件元数据视频流信息音频流信息 使用ffprobe获取更详细的音视频信息输入文件信息文件元数据视频流信息音频流信息 总结 前言 在处理多媒体文件时,了解文件的详细信息对于调试和优化处理过程至关重要。FFm…...
【IoTDB 线上小课 05】时序数据文件 TsFile 三问“解密”!
【IoTDB 视频小课】持续更新!第五期来啦~ 关于 IoTDB,关于物联网,关于时序数据库,关于开源... 一个问题重点,3-5 分钟详细展开,为大家清晰解惑: IoTDB 的 TsFile 科普! 了解了时序数…...
python-爬虫实例(4):获取b站的章若楠的视频
目录 前言 道路千万条,安全第一条 爬虫不谨慎,亲人两行泪 获取b站的章若楠的视频 一、话不多说,先上代码 二、爬虫四步走 1.UA伪装 2.获取url 3.发送请求 4.获取响应数据进行解析并保存 总结 前言 道路千万条,安全第一条 爬…...
C# yaml 配置文件的用法(一)
目录 一、简介 二、yaml 的符号 1.冒号 2.短横杆 3.文档分隔符 4.保留换行符 5.注释 6.锚点 7.NULL值 8.合并 一、简介 YAML(YAML Aint Markup Language)是一种数据序列化标准,广泛用于配置文件、数据交换和存储。YAML的设计目标是…...
人工智能与机器学习原理精解【4】
文章目录 马尔科夫过程论要点理论基础σ代数定义性质应用例子总结 马尔可夫过程概述一、马尔可夫过程的原理二、马尔可夫过程的算法过程三、具体例子 马尔可夫链的状态转移概率矩阵一、确定马尔可夫链的状态空间二、收集状态转移数据三、计算转移频率四、构建状态转移概率矩阵示…...
Go channel实现原理详解(源码解读)
文章目录 Go channel详解Channel 的发展Channel 的应用场景Channel 基本用法Channel 的实现原理chan 数据结构初始化sendrecvclose使用 Channel 容易犯的错误总结Go channel详解 Channel 是 Go 语言内建的 first-class 类型,也是 Go 语言与众不同的特性之一。Channel 让并发消…...
数据结构-C语言-排序(4)
代码位置: test-c-2024: 对C语言习题代码的练习 (gitee.com) 一、前言: 1.1-排序定义: 排序就是将一组杂乱无章的数据按照一定的规律(升序或降序)组织起来。(注:我们这里的排序采用的都为升序) 1.2-排…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释
以Module Federation 插件详为例,Webpack.config.js它可能的配置和含义如下: 前言 Module Federation 的Webpack.config.js核心配置包括: name filename(定义应用标识) remotes(引用远程模块࿰…...
数据库正常,但后端收不到数据原因及解决
从代码和日志来看,后端SQL查询确实返回了数据,但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离,并且ai辅助开发的时候,很容易出现前后端变量名不一致情况,还不报错,只是单…...
Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合
无论是python,或者java 的大型项目中,都会涉及到 自身平台微服务之间的相互调用,以及和第三发平台的 接口对接,那在python 中是怎么实现的呢? 在 Python Web 开发中,FastAPI 和 Django 是两个重要但定位不…...
