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

Spring Boot 接口访问频率限制的实现详解

目录

  1. 概述
  2. 为什么需要接口访问频率限制
  3. 常见的实现方式
    • 基于过滤器的实现
    • 基于拦截器的实现
    • 基于第三方库Bucket4j的实现
  4. 实际代码示例
    • 基于过滤器实现Rate Limiting
    • 基于拦截器实现Rate Limiting
    • 使用Bucket4j实现Rate Limiting
  5. 最佳实践
    • 选择合适的限流算法
    • 优化性能
    • 记录日志和监控
  6. 总结

概述

接口访问频率限制是通过在一定时间内限制用户对接口的访问次数来实现的。常见的限流算法包括令牌桶算法(Token Bucket)、漏桶算法(Leaky Bucket)、固定窗口计数器(Fixed Window Counter)和滑动窗口计数器(Sliding Window Counter)等。在Spring Boot中,我们可以通过多种方式来实现接口的限流,如使用过滤器、拦截器或者借助第三方库。

为什么需要接口访问频率限制

  1. 防止恶意攻击:通过限制接口的访问频率,可以有效防止恶意用户或机器人频繁访问接口,导致系统资源耗尽。
  2. 提升系统稳定性:在高并发场景下,限流可以有效保护后端服务,避免因流量过大而导致系统崩溃。
  3. 提升用户体验:合理的限流可以保障所有用户都能获得较好的服务质量,避免个别用户过度使用资源。

常见的实现方式

基于过滤器的实现

过滤器是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

引言 在用户至上的时代&#xff0c;精准把握用户行为已成为产品优化的关键。本文将详细介绍 user-interaction-tracker 库&#xff0c;它提供了一种高效的解决方案&#xff0c;用于跟踪用户交互的持续时间&#xff0c;并提升项目埋点的效率。通过本文&#xff0c;你将了解到如…...

中文分词库 jieba 详细使用方法与案例演示

1 前言 jieba 是一个非常流行的中文分词库&#xff0c;具有高效、准确分词的效果。 它支持3种分词模式&#xff1a; 精确模式全模式搜索引擎模式 jieba0.42.1测试环境&#xff1a;python3.10.9 2 三种模式 2.1 精确模式 适应场景&#xff1a;文本分析。 功能&#xff1…...

EXO-helper解释

目录 helper解释 helper解释 在Python中,字符串 "\033[93m" 是一个ANSI转义序列,用于在支持ANSI转义码的终端或控制台中改变文本的颜色。具体来说,\033[93m 用于将文本颜色设置为亮黄色(或浅黄色,具体取决于终端的显示设置)。 这里的 \033 实际上是八进制的 …...

Qt开发网络嗅探器01

引言 随着互联网的快速发展和普及&#xff0c;人们对网络性能、安全和管理的需求日益增长。在复杂的网络环境中&#xff0c;了解和监控网络中的数据流量、安全事件和性能问题变得至关重要。为了满足这些需求&#xff0c;网络嗅探器作为一种重要的工具被 广泛应用。网络嗅探器是…...

mysql面试(三)

MVCC机制 MVCC&#xff08;Multi-Version Concurrency Control&#xff09; 即多版本并发控制&#xff0c;了解mvcc机制&#xff0c;需要了解如下这些概念 事务id 事务每次开启时&#xff0c;都会从数据库获得一个自增长的事务ID&#xff0c;可以从事务ID判断事务的执行先后…...

阿里云公共DNS免费版自9月30日开始限速 企业或商业场景需使用付费版

本周阿里云发布公告对公共 DNS 免费版使用政策进行调整&#xff0c;免费版将从 2024 年 9 月 30 日开始按照请求源 IP 进行并发数限制&#xff0c;单个 IP 的请求数超过 20QPS、UDP/TCP 流量超过 2000bps 将触发限速策略。 阿里云称免费版的并发数限制并非采用固定的阈值&…...

捷配生产笔记-一文搞懂阻焊层基本知识

什么是阻焊层&#xff1f; 阻焊层&#xff08;也称为阻焊剂&#xff09;是应用于PCB表面的一层薄薄的聚合物材料。其目的是保护铜电路&#xff0c;防止焊料在焊接过程中流入不需要焊接的区域。除焊盘外&#xff0c;整个电路板都涂有阻焊层。 阻焊层应用于 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> ①宽度&#xff08;长&#xff09; ②高度&#xff08;宽&a…...

【SpingCloud】客户端与服务端负载均衡机制,微服务负载均衡NacosLoadBalancer, 拓展:OSI七层网络模型

客户端与服务端负载均衡机制 可能有第一次听说集群和负载均衡&#xff0c;所以呢&#xff0c;我们先来做一个介绍&#xff0c;然后再聊服务端与客户端的负载均衡区别。 集群与负载均衡 负载均衡是基于集群的&#xff0c;如果没有集群&#xff0c;则没有负载均衡这一个说法。 …...

【Elasticsearch】Elasticsearch 中的节点角色

Elasticsearch 中的节点角色 1.主节点&#xff08;master&#xff09;1.1 专用候选主节点&#xff08;dedicated master-eligible node&#xff09;1.2 仅投票主节点&#xff08;voting-only master-eligible node&#xff09; 2.数据节点&#xff08;data&#xff09;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...

分表分库是一种数据库架构的优化策略,用于处理大规模数据和高并发请求,提高数据库的性能和可扩展性。

分表分库是一种数据库架构的优化策略&#xff0c;用于处理大规模数据和高并发请求&#xff0c;提高数据库的性能和可扩展性。以下是一些常见的分表分库技术方案&#xff1a; 1. **水平分表&#xff08;Horizontal Sharding&#xff09;**&#xff1a; - 将单表数据根据某个…...

【ffmpeg命令入门】获取音视频信息

文章目录 前言使用ffmpeg获取简单的音视频信息输入文件信息文件元数据视频流信息音频流信息 使用ffprobe获取更详细的音视频信息输入文件信息文件元数据视频流信息音频流信息 总结 前言 在处理多媒体文件时&#xff0c;了解文件的详细信息对于调试和优化处理过程至关重要。FFm…...

【IoTDB 线上小课 05】时序数据文件 TsFile 三问“解密”!

【IoTDB 视频小课】持续更新&#xff01;第五期来啦~ 关于 IoTDB&#xff0c;关于物联网&#xff0c;关于时序数据库&#xff0c;关于开源... 一个问题重点&#xff0c;3-5 分钟详细展开&#xff0c;为大家清晰解惑&#xff1a; IoTDB 的 TsFile 科普&#xff01; 了解了时序数…...

python-爬虫实例(4):获取b站的章若楠的视频

目录 前言 道路千万条&#xff0c;安全第一条 爬虫不谨慎&#xff0c;亲人两行泪 获取b站的章若楠的视频 一、话不多说&#xff0c;先上代码 二、爬虫四步走 1.UA伪装 2.获取url 3.发送请求 4.获取响应数据进行解析并保存 总结 前言 道路千万条&#xff0c;安全第一条 爬…...

C# yaml 配置文件的用法(一)

目录 一、简介 二、yaml 的符号 1.冒号 2.短横杆 3.文档分隔符 4.保留换行符 5.注释 6.锚点 7.NULL值 8.合并 一、简介 YAML&#xff08;YAML Aint Markup Language&#xff09;是一种数据序列化标准&#xff0c;广泛用于配置文件、数据交换和存储。YAML的设计目标是…...

人工智能与机器学习原理精解【4】

文章目录 马尔科夫过程论要点理论基础σ代数定义性质应用例子总结 马尔可夫过程概述一、马尔可夫过程的原理二、马尔可夫过程的算法过程三、具体例子 马尔可夫链的状态转移概率矩阵一、确定马尔可夫链的状态空间二、收集状态转移数据三、计算转移频率四、构建状态转移概率矩阵示…...

Go channel实现原理详解(源码解读)

文章目录 Go channel详解Channel 的发展Channel 的应用场景Channel 基本用法Channel 的实现原理chan 数据结构初始化sendrecvclose使用 Channel 容易犯的错误总结Go channel详解 Channel 是 Go 语言内建的 first-class 类型,也是 Go 语言与众不同的特性之一。Channel 让并发消…...

数据结构-C语言-排序(4)

代码位置&#xff1a; test-c-2024: 对C语言习题代码的练习 (gitee.com) 一、前言&#xff1a; 1.1-排序定义&#xff1a; 排序就是将一组杂乱无章的数据按照一定的规律&#xff08;升序或降序&#xff09;组织起来。(注&#xff1a;我们这里的排序采用的都为升序) 1.2-排…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

Ubuntu Cursor升级成v1.0

0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开&#xff0c;快捷键也不好用&#xff0c;当看到 Cursor 升级后&#xff0c;还是蛮高兴的 1. 下载 Cursor 下载地址&#xff1a;https://www.cursor.com/cn/downloads 点击下载 Linux (x64) &#xff0c;…...

解析“道作为序位生成器”的核心原理

解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制&#xff0c;重点解析"道作为序位生成器"的核心原理与实现框架&#xff1a; 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...

内窥镜检查中基于提示的息肉分割|文献速递-深度学习医疗AI最新文献

Title 题目 Prompt-based polyp segmentation during endoscopy 内窥镜检查中基于提示的息肉分割 01 文献速递介绍 以下是对这段英文内容的中文翻译&#xff1a; ### 胃肠道癌症的发病率呈上升趋势&#xff0c;且有年轻化倾向&#xff08;Bray等人&#xff0c;2018&#x…...

13.10 LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析

LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析 LanguageMentor 对话式训练系统架构与实现 关键词:多轮对话系统设计、场景化提示工程、情感识别优化、LangGraph 状态管理、Ollama 私有化部署 1. 对话训练系统技术架构 采用四层架构实现高扩展性的对话训练…...

C++11 constexpr和字面类型:从入门到精通

文章目录 引言一、constexpr的基本概念与使用1.1 constexpr的定义与作用1.2 constexpr变量1.3 constexpr函数1.4 constexpr在类构造函数中的应用1.5 constexpr的优势 二、字面类型的基本概念与使用2.1 字面类型的定义与作用2.2 字面类型的应用场景2.2.1 常量定义2.2.2 模板参数…...