重学SpringBoot3-集成Redis(七)之分布式限流

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》
期待您的点赞👍收藏⭐评论✍

重学SpringBoot3-集成Redis(七)之分布式限流

  • 1. 什么是分布式限流?
  • 2. 常见的限流算法
  • 3. Redis 分布式限流实现
    • 3.1. 添加依赖
    • 3.2. 配置 Redis 连接
    • 3.3. 编写限流逻辑
    • 3.4. 编写控制器测试限流
  • 4. 限流算法的改进
    • 4.1. 什么是滑动窗口限流?
    • 4.2. 使用 Redisson 实现滑动窗口限流
      • 4.2.1. 引入依赖
      • 4.2.2. 配置 Redisson
      • 4.2.3. 滑动窗口限流的实现
      • 4.2.4. 控制器测试限流
      • 4.2.5. 单用户限制
      • 4.2.6. 全部请求限制
    • 4.3. 优势
  • 5. 总结

在分布式系统中,流量控制是一项关键的任务,特别是当我们需要应对瞬时的大流量请求时。分布式限流是一种有效的方式,可以防止系统被突发的请求击垮。在这篇文章中,将介绍如何通过 RedisSpring Boot 3 实现分布式限流。

1. 什么是分布式限流?

限流的目的是控制一定时间窗口内的请求数量,确保系统稳定运行。分布式限流的核心在于它可以在多台服务器或多个节点上,对所有的请求进行全局控制。通过限流,我们可以:

  • 防止系统过载
  • 保护关键资源
  • 提高系统的稳定性和可用性

Redis 作为一个内存存储系统,具有高性能、分布式、可扩展的特点,非常适合用于实现分布式限流。

2. 常见的限流算法

在介绍具体实现之前,我们先了解一些常用的限流算法:

  1. 固定窗口算法:在一个固定的时间窗口内,限制请求次数。
  2. 滑动窗口算法:相比固定窗口算法,滑动窗口更平滑,可以在时间窗口内动态更新请求。
  3. 令牌桶算法:根据流量产生令牌,请求只能在获取到令牌后才可以通过。
  4. 漏桶算法:以固定速率处理请求,超出速率的请求被丢弃。

首先将以 固定窗口 为例,展示如何通过 Redis 实现限流。

3. Redis 分布式限流实现

3.1. 添加依赖

首先,确保项目中已经引入了 Redis 依赖,详细参考重学SpringBoot3-集成Redis(一)基本使用。在 pom.xml 文件中添加以下依赖:

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

3.2. 配置 Redis 连接

application.yml 中配置 Redis 的基本连接信息:

spring:data:redis:host: localhostport: 6379            # Redis 端口password:             # 如果有密码可以在这里配置lettuce:pool:max-active: 100    # 最大并发连接数max-idle: 50       # 最大空闲连接数min-idle: 10       # 最小空闲连接数

3.3. 编写限流逻辑

我们可以使用 Redis 的 INCR 命令结合 EXPIRE 来实现限流功能。每当有请求时,先检查当前时间窗口内的请求次数,如果超过限制则拒绝请求。

package com.coderjia.boot310redis.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;import java.time.Duration;/*** @author CoderJia* @create 2024/10/7 上午 11:14* @Description**/
@Component
public class RateLimiter {@Autowiredprivate StringRedisTemplate redisTemplate;// 限制 10 秒内最多允许 5 次请求,可放到配置文件中private static final int LIMIT = 5;private static final int TIME_WINDOW = 10; // 单位:秒public boolean isAllowed(String userId) {String key = "rate:limit:" + userId;Long currentCount = redisTemplate.opsForValue().increment(key);if (currentCount == 1) {// 设置 key 的过期时间为 10 秒redisTemplate.expire(key, Duration.ofSeconds(TIME_WINDOW));}// 超过限制return currentCount <= LIMIT;}
}

在这个类中:

  • 我们使用 INCR 命令来对某个键进行自增操作。
  • 当第一次自增时,我们使用 expire 设置键的过期时间,即时间窗口的长度(如 10 秒)。
  • 如果某个用户在这个时间窗口内的请求次数超过了限制值,则返回 false,表示请求被拒绝。

3.4. 编写控制器测试限流

为了测试限流功能,我们创建一个简单的控制器,当用户访问时,检查其是否被限流。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class RateLimitController {@Autowiredprivate RateLimiter rateLimiter;@GetMapping("/api/request")public String handleRequest(@RequestParam String userId) {boolean allowed = rateLimiter.isAllowed(userId);if (allowed) {return "Request allowed for user: " + userId;} else {return "Request limit exceeded for user: " + userId;}}
}

现在,当用户连续访问 http://localhost:8080/api/request?userId=1 时,系统会根据设定的规则,决定是否允许请求。如下图,连续5次请求之后,之后再请求将会被限制访问,直到10s之后,进入到下一个固定窗口,可以再访问5次,之后触发限流。

限流效果

4. 限流算法的改进

在实际场景中,我们可以根据业务需求选择不同的限流算法。例如:

  1. 滑动窗口限流:通过记录每个请求的时间戳来实现更精确的限流控制。
  2. 令牌桶限流:可以动态调整请求速率,允许一定程度的突发流量。

如果需要更多的定制化功能,可以借助 Redisson 等工具,它提供了开箱即用的分布式限流功能,能够更加优雅地处理复杂的限流场景。

Redisson 是基于 Redis 的 Java 客户端,它提供了多种高级功能,包括分布式锁、信号量、限流等。利用 Redisson 实现滑动窗口限流,我们可以避免直接通过 Redis 的 INCREXPIRE 命令来手动操作,而是使用其提供的高层 API 实现更加精确的流量控制。

4.1. 什么是滑动窗口限流?

滑动窗口限流是一种动态的限流策略,它将时间划分为多个小窗口,并在多个窗口中统计请求次数,从而实现平滑的流量控制。相比于固定窗口限流,滑动窗口限流不会因为时间窗口的边界问题导致突发流量通过,而是根据请求的时间动态调整。

4.2. 使用 Redisson 实现滑动窗口限流

4.2.1. 引入依赖

详细配置可参考重学SpringBoot3-集成Redis(四)之Redisson ,需要在 pom.xml 文件中引入 Redisson 的依赖:

        <dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.23.4</version></dependency>

4.2.2. 配置 Redisson

配置 Redisson 的基本信息,在 application.yml 文件中进行 Redis 的连接配置:

spring:redis:redisson:config: |singleServerConfig:address: redis://1.94.26.81:6379   # Redis 连接地址,前缀为 redis://password: redis123456              # 如果 Redis 需要密码认证,则填写密码timeout: 3000                      # 命令执行超时时间(毫秒)

4.2.3. 滑动窗口限流的实现

Redisson 提供了 RateLimiter(限流器)来控制请求频率。RateLimiter 支持滑动窗口限流算法,我们可以通过它来控制一定时间内的请求次数。

package com.coderjia.boot310redis.config;import jakarta.annotation.PostConstruct;
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;/*** @author CoderJia* @create 2024/10/7 下午 12:10* @Description**/
@Component
public class SlidingWindowRateLimiter {@Autowiredprivate RedissonClient redissonClient;private RRateLimiter rateLimiter;@PostConstructpublic void init() {// 创建一个滑动窗口限流器rateLimiter = redissonClient.getRateLimiter("rrateLimiter");// 每 1 秒最多允许 5 次请求boolean b = rateLimiter.trySetRate(RateType.OVERALL, 5, 1, RateIntervalUnit.SECONDS);// 查看是否设置成功if (b){System.out.println("限流器设置成功");}else {System.out.println("限流器设置失败");}}public boolean tryAcquire() {// 尝试获取一个令牌return rateLimiter.tryAcquire(1);}
}

在这个代码中:

  • rateLimiter.trySetRate() 设置限流规则,每人每 1 秒最多允许 5 次请求
  • RateType.PER_CLIENT 设置限制同一用户,如果限制全部用户请求,可改为 RateType.OVERALL
  • rateLimiter.tryAcquire(1) 尝试获取一个令牌,如果成功获取,则返回 true,表示请求通过;如果失败,则返回 false,表示请求被限流。

4.2.4. 控制器测试限流

我们可以通过一个简单的控制器来测试滑动窗口限流:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class RateLimitController {@Autowiredprivate SlidingWindowRateLimiter rateLimiter;@GetMapping("/api/request")public String handleRequest() {boolean allowed = rateLimiter.tryAcquire();if (allowed) {return "Request allowed";} else {return "Request limit exceeded";}}
}

当我们访问 http://localhost:8080/api/request 时,系统会检查是否符合限流条件,从而决定是否允许请求。

这里需要借助 apifox 进行压测:

模拟单用户并发请求

4.2.5. 单用户限制

首先是单用户限制每秒钟访问5次,单用户连续请求100次,报告显示12s时间成功请求了60次,达到了我们的效果。

单用户限制

4.2.6. 全部请求限制

下面模拟20用户连续请求1分钟,下面报告显示1分钟内,请求了996次,由于设置的1秒内运行请求5次,所有成功率60*5/996约等于30%,考虑接口耗时,和报告的失败率近似。

全部请求限制

4.3. 优势

  1. 高精度限流:滑动窗口可以更精确地统计请求数,相较于固定窗口限流,它可以避免窗口边界导致的瞬时突发请求超出限制的情况。
  2. 自动管理:Redisson 自带的 RateLimiter 限流器无需手动维护 Redis 键值过期时间,它会自动处理这些细节,大大简化了限流的实现。

5. 总结

通过 Redis 实现的分布式限流,具有实现简单、性能高、易于扩展的优势。它能够帮助我们应对瞬时的大流量请求,保护系统免于过载。同时,结合不同的限流算法,我们可以根据具体的业务需求,设计灵活、精准的限流策略。

如果你在项目中遇到类似的限流需求,Redis 是一个很好的选择。希望这篇文章能够帮助你了解如何使用 Spring Boot 3 和 Redis 实现分布式限流。如果你有任何疑问或建议,欢迎留言讨论!

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

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

相关文章

Qt-窗口对话框QMessageBox的使用(51)

目录 前言 描述 使用 自定义按钮 简单方式创建 前言 Qt 提供了多种可复⽤的对话框类型&#xff0c;即 Qt 标准对话框。Qt 标准对话框全部继承于 QDialog类。常⽤标准对话框如下&#xff1a; 描述 消息对话框 QMessageBox 消息对话框是应⽤程序中最常⽤的界⾯元素。消息…

微信点赞的测试用例,应该在哪些方面进行设计!

功能模块测试的测试用例设计方法包括&#xff1a; 等价类划分法&#xff1a;把所有可能的输入数据&#xff0c;即程序的输入域划分成若干部分&#xff0c;然后从每一个部分中选取少数具有代表性的数据作为测试用例。比如字符串长度检查,字符类型检查,标点符号检查,特殊字符检查…

活动预告丨第二十八期 “CCF 开源高校行”暨“木兰技术开放日”活动走进北京大学...

点击蓝字 关注我们 CCF Opensource Development Committee 开源高校行 北京大学站 在数字化转型的浪潮中&#xff0c;开源软件人才的培养是信息技术创新发展的重要根基&#xff0c;高校学子作为我国开源生态的源头活水备受重视。10月9日下午15:00-17:10 “CCF 开源高校行”暨“…

318页PPT5G智慧校园顶层设计方案

2019年&#xff0c;中共中央、国务院印发的《中国教育现代化2035》提出从构建更为完善信息化基础环境、配置学校数字教学资源、建立学校信息化系统运行维护长效机制、统筹建设一体化智能化教学和管理与服务平台等方面建设智能化校园。因此&#xff0c;未来随着信息通信技术的不…

Java项目实战II基于Java+Spring Boot+MySQL的中药实验管理系统(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 中药作为中…

龙迅LT8911EXB 高性价比方案MIPICSI/DSI转EDP 1.4 大批量出货产品

龙迅LT891EXB描述&#xff1a; Lontium LT8911EXB是MIPIDSI/CSI到eDP转换器&#xff0c;单端口MIPI接收器有1个时钟通道和4个数据通道&#xff0c;每个数据通道最大运行2.0Gbps&#xff0c;最大输入带宽为8.0Gbps。转换器解码输入MIPI RGB16/18/24/30/36bpp、YUV422 16/20/24b…

huohuo

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

C++网络编程之套接字基础

概述 在网络编程中&#xff0c;套接字&#xff08;Socket&#xff09;是一种用于进程间通信的接口。套接字是操作系统提供的一种抽象层&#xff0c;它允许不同计算机之间的进程通过网络进行通信。套接字实际上并不神秘&#xff0c;简单来说&#xff0c;套接字是连接网络中不同主…

网络安全 IP地址防泄漏指南

IP地址作为每个上网人的“门牌标识号”&#xff0c;如果产生泄露&#xff0c;可能会导致个人行踪曝光、数据被窃取甚至遭受网络攻击&#xff0c;要防止IP地址不被窃取&#xff0c;我们可以尝试以下方法&#xff1a; 利用专用网络加强隐私保护 通过加密在公共网络上创建一条安全…

利用LangSmith Chat数据集轻松微调模型

在这篇文章中&#xff0c;我们将探讨如何使用LangSmith Chat数据集来微调AI模型&#xff0c;并将其应用于LangChain应用中。这个过程简单易行&#xff0c;只需三个步骤&#xff1a;创建聊天数据集、加载示例并微调模型。 引言 随着对聊天AI需求的增加&#xff0c;能够通过特定…

怎样在不改变使用习惯的前提下,实现替代FTP的操作?

但国家信创要求出台后&#xff0c;“28N”行业领域已陆续实现信创国产化的替代&#xff0c;从操作系统到CPU、数据库等&#xff0c;下一步&#xff0c;可能就会落实到引用层面&#xff0c;这时候&#xff0c;作为文件传输关键载体的FTP就不得不考虑信创国产化替代的问题。 那么…

如何采集1688商品的多语言数据

访问1688官网的数据&#xff0c;是中文的商品数据&#xff0c;如果直接采集1688的中文商品数据&#xff0c;还需要自己翻译数据&#xff0c;翻译标题&#xff0c;描述&#xff0c;格式化数据等比较麻烦 教大家一种新的方式&#xff0c;1688在2023年底已经开通了跨境专供&#…

谷歌最近在其量子处理器中发现了一个“低噪声相变”现象

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

2024年第四届机器人、自动化和人工智能国际会议(RAAI 2024)即将召开!

学术会议查询-学术会议交流服务平台-爱科会易 (uconf.com)https://www.uconf.com/ 第四届机器人、自动化和人工智能国际会议&#xff08;RAAI 2024&#xff09;将于 2024 年 12 月 19-21 日在新加坡举行。会议旨在为研究人员、从业人员和行业专家提供一个平台&#xff0c;分享他…

鸿蒙--下拉刷新+上拉加载

概述 Refresh组件支持下拉刷新&#xff0c;包裹list组件&#xff0c;下拉事件中更新列表 这里我们需要提前了解一下 Builder装饰器 的基本用法 ArkUI提供了一种轻量的UI元素复用机制Builder&#xff0c;该自定义组件内部UI结构固定&#xff0c;仅与使用方进行数据传递&#…

如何在SU中添加建筑分层线?

建筑体块拉伸后&#xff0c;为增家一些表现效果&#xff0c;建筑分层线是有效的方法。但如果建筑是高层&#xff0c;一个个复制分层线很麻烦&#xff0c;这里就教会大家一个利用复制给建筑增加分层线的小技巧。 解决方案&#xff1a; 1、建筑分层线&#xff1a;导入建筑的线框…

DBO-BP回归预测 | MATLAB实现DBO-BP蜣螂优化算法优化神经网络多输入单输出回归预测

回归预测 | MATLAB实现DBO-BP蜣螂优化算法优化神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现DBO-BP蜣螂优化算法优化神经网络多输入单输出回归预测基本介绍程序设计参考资料基本介绍 MATLAB实现DBO-BP蜣螂优化算法优化神经网络多输入单输出回归预测。 蜣螂优化群优…

vue3--通用组件 popup 封装

在业务场景中,假设这里我们要实现点击 汉堡 后,会有一个自下而上的popup弹出层 因此这里我们需要先实现这样的一个公共的popup弹出层 那么我们这里的popup弹出层需要具备以下能力: 当popup展开时,内容视图应该不属于任何一个组件内部,而应该直接被插入到body下,这里需要…

网络资源模板--Android Studio 实现简易计算器App

目录 一、项目演示 二、项目测试环境 三、项目详情 四、完整的项目源码 一、项目演示 网络资源模板--基于Android studio 实现的简易计算器 二、项目测试环境 三、项目详情 动态绑定按钮&#xff1a; 使用循环遍历 buttons 数组&#xff0c;根据动态生成的按钮 ID (btn_0, …

Jenkins整合Docker实现CICD自动化部署(若依项目)

前期准备 提前准备好jenkins环境 并且jenkins能使用docker命令&#xff0c;并且已经配置好了jdk、node、maven环境&#xff0c;我之前写了安装jenkins的博客&#xff0c;里面讲得比较详细&#xff0c;推荐用我这种方式安装 docker安装jenkins&#xff0c;并配置jdk、node和m…