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

springcloud gateway网关动态配置限流

上一篇记录了gateway网关的基础功能和配置,并且使用了默认的限流功能。

springcloud gateway网关-CSDN博客

这里简单记录一下gateway网关集成mybatisPlus实现动态限流。gateway网关默认的限流方式各项限流参数都是在配置文件中配置,不够灵活,虽然使用阿里的Sentinel组件可以实现从nacos注册中心、配置中心动态读取配置,但是还是有一定的局限性。

有些业务上需要限流功能可以在平台的页面上进行灵活配置,并且实时生效。

大致流程:数据库添加一个流控表,有需要限流的URL,最大限流限制数、时间范围等字段。通过页面维护这个表的数据。gateway中写一个全局过滤器中,收到请求后,用URL去数据库中查询、或者从缓存查询,得到需要限制的参数,再调用写好的限流方法实现限流。限流方法用Redis的Zset数据结构实现的滑动窗口算法,当然,也可以用其他的限流算法。

下面的配置是基于上一篇文章的代码来实现。

一、pom文件中添加依赖

mybatisPlus相关依赖

        <!-- 数据库驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version></dependency><!-- druid数据库连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.16</version></dependency><!-- mybatis-plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version></dependency><!-- druid数据库连接池 需要用到该依赖 ,否则启动报错--><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency>

二、配置文件

server:port: 8089spring:application:name: gatewaydatasource:url: jdbc:mysql://127.0.0.1:3306/test-db?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghaiusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourcedruid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)# 连接池的配置信息# 初始化大小,最小,最大initial-size: 5min-idle: 5maxActive: 20# 配置获取连接等待超时的时间maxWait: 60000# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒timeBetweenEvictionRunsMillis: 60000# 配置一个连接在池中最小生存的时间,单位是毫秒minEvictableIdleTimeMillis: 300000validationQuery: SELECT 1testWhileIdle: truetestOnBorrow: falsetestOnReturn: false# 打开PSCache,并且指定每个连接上PSCache的大小poolPreparedStatements: truemaxPoolPreparedStatementPerConnectionSize: 20# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙#filters: stat,wall,slf4j# 通过connectProperties属性来打开mergeSql功能;慢SQL记录connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000webStatFilter:enabled: true########## Redis ############redis:database: 0host: 127.0.0.1port: 6379password:########## gateway 相关配置 ############cloud:gateway:routes:- id: service-01uri: http://127.0.0.1:8080predicates:- Path=/svs1/**filters:- StripPrefix=1 # 去掉path前缀,1代表去掉第一个- name: RequestRateLimiterargs:redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充数redis-rate-limiter.burstCapacity: 1 #令牌容量key-resolver: "#{@apiKeyResolver}" # 限流策略,对应配置中的Bean- id: service-02uri: http://127.0.0.1:8080predicates:- Path=/svs2/**filters:- StripPrefix=1#mybatis plus 设置
mybatis-plus:mapper-locations: classpath:mapper/*.xmlglobal-config:# 关闭MP3.0自带的bannerbanner: falsedb-config:#主键类型  0:"数据库ID自增",1:"该类型为未设置主键类型", 2:"用户输入ID",3:"全局唯一ID (数字类型唯一ID)", 4:"全局唯一ID UUID",5:"字符串全局唯一ID (idWorker 的字符串表示)";id-type: AUTO# 默认数据库表下划线命名table-underline: trueconfiguration:# 这个配置会将执行的sql打印出来,在开发或测试的时候可以用log-impl: org.apache.ibatis.logging.stdout.StdOutImpl# 返回类型为Map,显示null对应的字段call-setters-on-nulls: true

三、相关代码

1)redis工具类

package com.zhh.gateway.common.util;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;import java.util.concurrent.TimeUnit;/*** @Description: Redis缓存* @Author: zhaoheng* @CreateTime: 2024-03-13  21:10*/
@Component
public class RedisCache {public static final String SYS_PREFIX = "gateway:";@Autowiredprivate RedisTemplate redisTemplate;public String getZSetKey(String key) {return SYS_PREFIX + "zset:" + key;}/*** zSet数据结构添加数据* @param key		唯一标识* @param value		值* @param score		分值,用于排序* @param expireTime	过期时间,单位:秒* @param <T>*/public <T> void zSetAdd(String key, T value, double score, long expireTime) {key = getZSetKey(key);ZSetOperations zSetOps = redisTemplate.opsForZSet();zSetOps.add(key, value, score);zSetOps.getOperations().expire(key, expireTime, TimeUnit.SECONDS);}/*** 删除指定范围内的数据* @param key		唯一标识* @param min		最小值* @param max		最大值* @return*/public Long zSetRemoveRangeByScore(String key, double min, double max) {return redisTemplate.opsForZSet().removeRangeByScore(getZSetKey(key),min,max);}/*** 统计数据总量* @param key		唯一标识* @return*/public Long zSetCountAll(String key) {return redisTemplate.opsForZSet().zCard(getZSetKey(key));}
}

2)限流过滤器实现

核心就是Redis实现的滑动窗口的限流算法

package com.zhh.gateway.filter;import com.zhh.gateway.common.util.RedisCache;
import com.zhh.gateway.pojo.ApiLimiterPO;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;/*** @Description: 全局过滤器 限流过滤器* @Author: zhaoheng* @CreateTime: 2024*/
@Slf4j
@Component
public class ApiLimiterFilter implements GlobalFilter, Ordered {@Autowiredprivate RedisCache redisCache;@SneakyThrows@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String url = exchange.getRequest().getPath().value();log.info("request url:{}", url);// TODO 从请求头或cookie中获取签名,解析得到用户唯一标识String userId = "zs";this.apiLimiterByUser(url, userId);return chain.filter(exchange);}/*** IApiLimiterService* 过滤器执行顺序,值越小越靠前** @return*/@Overridepublic int getOrder() {return 0;}/*** 根据用户唯一标识限流** @param reqUrl 请求* @param userId 用户唯一标识* @throws Exception*/public void apiLimiterByUser(String reqUrl, String userId) throws Exception {// TODO 根据URL从数据库中查询限流相关配置//ApiLimiterPO apiLimiterPO = iApiLimiterService.getByUrl(reqUrl);// 模拟从数据库中查询到的数据ApiLimiterPO apiLimiterPO = ApiLimiterPO.builder().apiUrl("/api/v1.0/user/query")// 限流:1秒钟最多2个请求.rangeTime(1).limitMax(2).build();// 没有查询到数据,说明该接口没有配置限流if (null == apiLimiterPO) {log.info("无需限流,url:{}", reqUrl);return;}log.info("apiLimiterPO:{}", apiLimiterPO.toString());// 根据用户id限流String key = "xl:" + userId;// 时间窗口大小 限流:【rangeTime】秒钟最多【limitMax】个请求int rangeTime = apiLimiterPO.getRangeTime();// 流量大小int limitMax = apiLimiterPO.getLimitMax();// 当前时间long now = System.currentTimeMillis();// Redis实现滑动窗口算法  删除【rangeTime】秒之前的数据redisCache.zSetRemoveRangeByScore(key, 0, now - (rangeTime * 1000));// 添加请求数据到Redis,设置过期时间redisCache.zSetAdd(key, now, now, 60 * 60);// 统计总数据量Long sum = redisCache.zSetCountAll(key);if (sum > limitMax) {// TODO 一般都是自定义异常,然后全局异常处理器再统一返回错误信息给调用端throw new Exception("请稍后再试!");}}
}

这就完事!

读取数据库相关的简单业务代码就不做过多展示了,具体细节也是根据业务而定,这里只记录一下实现思路和核心流控代码。

相关文章:

springcloud gateway网关动态配置限流

上一篇记录了gateway网关的基础功能和配置&#xff0c;并且使用了默认的限流功能。 springcloud gateway网关-CSDN博客 这里简单记录一下gateway网关集成mybatisPlus实现动态限流。gateway网关默认的限流方式各项限流参数都是在配置文件中配置&#xff0c;不够灵活&#xff0…...

在Linux/Ubuntu/Debian中使用windows应用程序/软件

Wine 是一个兼容层&#xff0c;允许你在类 Unix 操作系统&#xff08;包括 Ubuntu&#xff09;上运行 Windows 应用程序。 以下是在 Ubuntu 上安装和使用 Wine 的基本步骤&#xff1a; 在 Ubuntu 上安装 Wine&#xff1a; 更新软件包列表&#xff1a; 打开终端并运行以下命令以…...

idea Springboot 组卷管理系统LayUI框架开发mysql数据库web结构java编程计算机网页

一、源码特点 springboot 组卷管理系统是一套完善的完整信息系统&#xff0c;结合mvc框架和LayUI框架完成本系统springboot spring mybatis &#xff0c;对理解JSP java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整…...

wordpress主题批量修改历史文章标题,文章内容

&#xff1a;​wordpress模板&#xff0c;在我映像中还是比较受欢迎的&#xff0c;至少它该有的插件都是应有尽有&#xff0c;不像帝国cms虽然功能多&#xff0c;但是基本用不上&#xff0c;而且很多会出错。也不像织梦cms漏洞太多&#xff0c;搞的建站期间出现很多其他事情&am…...

Unity2019.2.x 导出apk 安装到安卓Android12+及以上的系统版本 安装出现-108 安装包似乎无效的解决办法

Unity2019.2.x 导出apk 安装到安卓Android12及以上的系统版本 安装出现-108 安装包似乎无效的解决办法 导出AndroidStudio工程后 需要设置 build.gradle文件 // GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAINbuildscript {repositor…...

创建SpringCloudGateWay

创建SpringCloudGateWay 本案例基于尚硅谷《谷粒商城》项目&#xff0c;视频27 创建测试API网关 1、创建module 2、引入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:x…...

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:StepperItem)

用作Stepper组件的页面子组件。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 支持单个子组件。 接口 StepperItem() 属性 参数名参数类型参数描述prevLabelstring设置左侧文本按钮内…...

游戏盾SDK是如何实现智能加速的?

游戏盾SDK是一款能够提供内含windows、安卓、IOS版本的SDK下载&#xff0c;通过接入SDK&#xff0c;由SDK接管所有的通信流量&#xff0c;进行调度和加密传输&#xff0c;满足抗D、防C、流量加密等业务需求&#xff0c;为用户提供优质的网络环境&#xff0c;游戏极速畅通无阻。…...

西井科技参与IATA全球货运大会 以AI绿动能引领智慧空港新未来

3月12日至14日&#xff0c;由国际航空运输协会IATA主办的全球货运大会&#xff08;World Cargo Symposium&#xff09;在中国香港成功举办&#xff0c;这是全球航空货运领域最大规模与影响力的年度盛会。作为大物流领域全球领先的“智能化与新能源化”综合解决方案提供商&#…...

RPC通信原理(二)

RPC序列化 任何一种序列化框架&#xff0c;核心思想就是设计一种序列化协议&#xff0c;将对象的类型、属性类型、属性值一一按照固定的格式写到二进制字节流中来完成序列化&#xff0c;再按照固定的格式把数据一一读取出来&#xff0c;通过这些数据信息创建出一个新的对象&…...

Redis 淘汰策略

Redis 是一个使用键值对存储数据的内存中数据结构存储系统&#xff0c;它支持多种类型的数据结构&#xff0c;如字符串&#xff08;strings&#xff09;&#xff0c;列表&#xff08;lists&#xff09;&#xff0c;集合&#xff08;sets&#xff09;&#xff0c;有序集合&#…...

游戏数据处理

游戏行业关键数据指标 ~ 总激活码发放量、总激活量、总登录账号数 激活率、激活登录率 激活率 激活量 / 安装量 激活率 激活量 / 激活码发放量 激活且登录率 激活且登录量 / 激活码激活量 激活且登录率应用场景 激活且登录率是非常常用的转化率指标之一&#xff0c;广泛…...

Qt+FFmpeg+opengl从零制作视频播放器-14.程序Ubuntu移植

首先查看的是Linux系统的版本,我使用的是Ubuntu20.04.6LTS版本。 去Qt官网下载Qt 的版本。 这里下载的是5.12.12版本,双击运行,然后安装好Qt。 回想一下,在之前的程序,我们都是在Windows上开发,仅仅使用Qt和ffmpeg,Qt前面的步骤运行完成就可以安装好了,所以在linux上…...

Go 语言中的 Cond 机制详解

概述 在并发编程中&#xff0c;条件同步是一个常见的需求。Go 语言提供了 sync.Cond 类型来满足这一需求。sync.Cond 基于互斥锁&#xff08;sync.Mutex&#xff09;提供了条件变量的同步机制&#xff0c;允许一组 goroutine 在满足某个条件时进行阻塞等待&#xff0c;或者在条…...

如何使用vue定义组件之——子组件调用父组件数据

1.定义父子模板template <div class"container"><my-father></my-father><my-father></my-father><my-father></my-father><!-- 此处无法调用子组件&#xff0c;子组件必须依赖于父组件进行展示 --><!-- <my-…...

如何使用ArcGIS Pro生成带计曲线等高线

等高线作为常见的地图要素经常会被使用到&#xff0c;一般情况下生成的等高线是不带计曲线的&#xff0c;在某些情况下我们需要带计曲线的等高线&#xff0c;这里为大家介绍一下ArcGIS Pro生成带计曲线等高线的方法&#xff0c;希望能对你有所帮助。 数据来源 教程所使用的数…...

蓝桥杯C++大学B组一个月冲刺记录2024/3/13

蓝桥杯C大学B组一个月冲刺记录2024/3/13 规则:每日三题 向日葵的花语是说不出的爱恋 不过今天有点水题了 1.有序分数 给定一个整数 N&#xff0c;请你求出所有分母小于或等于 N&#xff0c;大小在 [0,1] 范围内的最简分数&#xff0c;并按从小到大顺序依次输出。 这个题在被划…...

计算机网络——Internet结构和ISP

互联网结构&#xff1a;网络的网络 ISP&#xff1a;互联网服务提供商&#xff08;Internet Service Provider&#xff0c;ISP&#xff09;是指为用户提供互联网接入服务的组织或公司。ISP在互联网结构中扮演着关键的角色&#xff0c;它们通过建立网络基础设施和提供网络连接服…...

E.接龙数列【蓝桥杯】/动态规划

接龙数列 题目描述 对于一个长度为 K 的整数数列&#xff1a;A1, A2, . . . , AK&#xff0c;我们称之为接龙数列当且仅当 Ai 的首位数字恰好等于 Ai−1 的末位数字 (2 ≤ i ≤ K)。 例如 12, 23, 35, 56, 61, 11 是接龙数列&#xff1b;12, 23, 34, 56 不是接龙数列&#xf…...

cv2.cvtColor()将二维转化为彩色图像

我们如果要将一维的图像转化为三维的彩色图像 import cv2 img cv2.cvtColor(img.squeeze(0), cv2.COLOR_GRAY2BGR) 这里的img.squeeze为二维数据&#xff0c;img为三维数据&#xff0c;所以压缩掉一个维度 。这样就将图像转化为了三维彩色图像。 cv2.imshow(Image, img) c…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...