Spring Cloud Gateway 网关的使用
在之前的学习中,所有的微服务接口都是对外开放的,这就意味着用户可以直接访问,为了保证对外服务的安全性,服务端实现的微服务接口都带有一定的权限校验机制,但是由于使用了微服务,就需要每一个服务都进行一个校验,当校验逻辑需要修改时,又得修改多个应用,增加了开发负担,一个解决方式就是引入 API 网关,类似整个微服务架构的门面,所有的外部客户端都需要经过它来进行调度和过滤,相当于前台,需要办理什么业务,经过前台的确认之后会引导用户去对应的服务台

作为网关,具有以下的几个核心功能:
- 权限控制:对用户进行权限校验,如果校验失败就进行拦截
- 动态路由:一切请求先经过网关,但网关不处理业务,而是根据某种规则,把请求发送到某个微服务
- 负载均衡:当路由的目标服务有多个时,进行负载均衡
- 限流:当请求流量过高时,按照网关中配置微服务能够接受的流量进行放行,避免服务压力过大
Gateway
1. Gateway 的使用
首先需要创建一个单独的 Gateway 的服务,除了引入 gateway 的依赖之外,还需要引入 nacos 和 loadbalancer 的依赖
<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>
</dependencies>
然后就需要对网关进行配置:
spring:application:name: gatewaycloud:nacos:discovery:server-addr: 127.0.0.1:8848gateway:routes: #网关路由配置- id: order-service #自定义路由规则iduri: lb://order-service/ #目标服务地址predicates: #路由条件(满足条件才会被通行)- Path=/order/**
来解释一下上面的配置:
由于需要用到 Nacos 的服务发现功能,所以要把 Nacos 的配置也添加上,之后就是网关的路由配置,自定义一个路由规则 id 作为唯一标识符,方便后续对该规则进行管理和引用,然后就是目标服务地址, lb 表示使用负载均衡器将请求转发到名为 order-service 的服务,并设置了路由条件,请求的路径必须以 /order/ 开头
配置好之后启动服务,此时就可以通过网关服务来获取资源了

关于多个服务和多个路由条件的配置:
routes: #网关路由配置- id: order-service #自定义路由规则iduri: lb://order-service/ #目标服务地址predicates: #路由条件(满足条件才会被通行)- Path=/order/**,/feign/**- id: product-serviceuri: lb://product-servicepredicates:- Path=/product/**
2. Route Predicate Factories
在上面的配置中,使用 predicates 来配置路由条件,其中写的规则只是字符串形式,这些字符串会被 Route Predicate Factory (路由断言工厂,也称为路由谓词工厂)读取并处理,转变为路由判断条件
https://docs.spring.io/spring-cloud-gateway/reference/spring-cloudgateway/request-predicates-factories.html

也就是这 12 种基本的实现:

来演示一下 After 的使用,如果不符合条件就会不能够访问
predicates: #路由条件(满足条件才会被通行)- Path=/order/**,/feign/**- After=2026-01-12T18:10:21.024727900+08:00[Asia/Shanghai]

3. Gateway Filter Factories
Predicate 是决定了请求由哪一个路由处理,Filter 过滤器是在请求处理前后做一些的逻辑的处理
Filter 又分为 Pre 和 Post 两种类型:
Pre 类型过滤器:路由处理之前执行,也就是请求转发给后端服务之前,例如对请求进行限流,添加额外的请求头信息等
Post 类型过滤器:请求执行完成后,将结果返回给客户端之前执行,例如修改响应体的主体内容,对响应路径进行重写等

Spring Cloud Gateway 中内置了很多的过滤器,用于拦截和处理 web 请求,根据作用范围可以分为 GatewayFilter (作用到单个路由或者一个分组的路由上),GlobalFilter(作用到所有的路由上)

来演示一下 AddRequestParameter 用法:

接下来再访问接口,即使 id 不传值也通过过滤器处理之后就被赋值了

除了 AddRequestParameter,观望中还提供了很多其它的过滤器
AddRequestHeader GatewayFilter Factory :: Spring Cloud Gateway

RequestRateLimiter 可以对通过网关的请求进行限流操作,采用的是令牌桶的算法
关于限流的算法有以下几种:
- 固定窗口:将时间划分为固定大小的窗口,每个窗口有一个计数器,用于记录在该窗口内允许通过的请求数量,每通过一个请求计数器就加一,当计数器达到设定的阈值就不允许请求通过,缺点也是非常明显,比如设定 10 分钟可以通过 10000 个请求,前 9 分钟都没有请求,最后 1 分钟处理 10000 个请求也符合要求,显然是不合理的
- 滑动窗口:同样将时间划分为多个小的时间窗口,但不是按固定的大窗口重置计数器,而是将窗口滑动,这也就解决了固定窗口出现的问题,不过需要记录多个小窗口的信息,性能开销比较大
- 漏桶算法:就像一个漏斗型的水桶,当请求到达时,会先进入漏桶,如果漏桶未满,则允许请求通过;如果漏桶已满,则拒绝请求,桶以恒定的速率出水,代表处理请求的速率,无论流入的速率如何,流出的速率始终保持一致,这也就导致了不能够处理突发的大流量
- 令牌桶算法:在漏桶的基础上,令牌桶中会以一定的速率生成令牌,当流量小的时候,桶中就会不断积累令牌,当遇到突发的大流量,就可以直接拿着这些令牌通过,剩余的就排队等待令牌的生成,排队等待这种处理方式,还可以结合其他策略,比如当排队队列过长时,为了避免资源过度占用,可能会对部分请求进行拒绝;或者根据业务的优先级,优先处理高优先级请求等。
再来看下一个过滤器:

Retry 就是根据当前返回的状态码来进行重试,可以设置状态码和重试次数
在上面的配置中都是使用 filter 进行配置的,如果使用 Default Filters 配置的话就是对全部路由生效

来使用 default-filters 配置一下 retry,然后把状态码设置为 502

之后就重新请求了 3 次

GlobalFilter 是全局过滤器,会应用到所有的路由请求上,全局过滤器通常用于实现安全性,性能监控和日志记录等相关的全局功能

关于负载均衡,在之前的使用中就已经用到了,也就是 GlobalFilter

下面看一下 Metrics 怎么使用,首先需要引入下面的依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
然后再开启 metrics 的配置

然后再添加一下配置,用来监控详细的信息,在 /actuator 下可以查到所有监控的链接和信息

过滤器的执行顺序:
当一个项目中,既有 GatewayFilter 又有 GlobalFilter 时,请求路由后,网关会把当前项目中的 GatewayFilter 和 GlobalFilter 合并到一个 过滤器链中,并进行排序,依次执行过滤器

每一个过滤器都必须指定一个 int 类型的 order 值,默认值为 0 ,来表示过滤器的优先级,order 值越小,优先级越高,执行顺序越靠前
Filter 通过实现 Order 接口或者添加@Order注解来指定 order 值,Spring Cloud Gateway 提供的 Filter 由 Spring 指定,用户也可以自定义 Filter,如果过滤器的 order 值一样,会按照 defaultFilter > GatewayFilter > GlobalFilter 的顺序执行
4. 自定义过滤器
4.1. 自定义 GlobalFilter
全局过滤器需要实现 GlobalFilter,Ordered 接口,然后重写 filter 和 getOrder 方法
@Slf4j
@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//Pre执行逻辑log.info("Pre Global Filter...");return chain.filter(exchange).then(Mono.fromRunnable(()->{//Post执行逻辑log.info("Post Global Filter...");}));}@Overridepublic int getOrder() {return Ordered.LOWEST_PRECEDENCE; //设置优先级}
}
关于 Mono 方法参数的说明:

之后再去发起请求,自定义的全局过滤器已经生效了

4.2. 自定义 GatewayFilter
如果需要自定义可配置的 GatewayFilter,就需要创建一个过滤器工厂,根据读取到的配置来构造对象
定义一个类用来存储从配置文件中读取到的配置信息
@Data
public class CustomConfig {private String name;
}
创建一个过滤器工厂 CustomGatewayFilterFactory 继承 AbstractGatewayFilterFactory 类,然后再实现 Ordered 接口,并添加过滤器的逻辑
@Slf4j
@Component
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomConfig> implements Ordered {public CustomGatewayFilterFactory() {super(CustomConfig.class);}@Overridepublic GatewayFilter apply(CustomConfig config) {return new GatewayFilter() {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//Pre类型log.info("Pre Filter,config{}",config);return chain.filter(exchange).then(Mono.fromRunnable(()->{log.info("Post Filter,config{}",config);}));}};}@Overridepublic int getOrder() {return Ordered.LOWEST_PRECEDENCE;}
}
配置文件中把自定义的过滤器名称添加上,然后还需要添加传入的参数,这里过滤器的名称取的是 CustomGatewayFilterFactory 除去 GatewayFilterFactory,按照规范自定义过滤器工厂需要以 GatewayFilterFactory 为后缀

之后再启动服务,自定义的 GatewayFilter 也生效了,并且在指定优先级相同的条件下,先执行 GatewayFilter 再执行 GlobalFilter

相关文章:
Spring Cloud Gateway 网关的使用
在之前的学习中,所有的微服务接口都是对外开放的,这就意味着用户可以直接访问,为了保证对外服务的安全性,服务端实现的微服务接口都带有一定的权限校验机制,但是由于使用了微服务,就需要每一个服务都进行一…...
超高速工业相机的应用
超高速工业相机一般安装在机器流水线上代替人眼来做测量和判断,通过数字图像摄取目标转换成图像信号,传送给专用的图像处理系统。图像处理系统对这些信号进行各种运算来抽取目标的特征,进而根据判别的结果来控制现场的设备动作。一般来说&…...
学习笔记--电磁兼容性EMC
一、基本概念 电磁兼容性(Electromagnetic Compatibility,EMC)是电子电气设备在特定电磁环境中正常工作的能力,同时不会对其他设备产生不可接受的电磁干扰。其核心目标是确保设备在共享的电磁环境中既能抵抗干扰,又能避…...
利用开源小智AI制作桌宠机器狗
本文主要介绍如何利用开源小智AI制作桌宠机器狗 1 源码下载 首先下载小智源码,下载地址, 下载源码后,使用vsCode打开,需要在vscode上安装esp-idf,安装方式请自己解决 2 源码修改 2.1添加机器狗控制代码 在目录main/iot/things下添加dog.cc文件,内容如下; #include…...
基于PSO-LSTM长短期记忆神经网络的多分类预测【MATLAB】
一、研究背景与意义 在时间序列分类、信号识别、故障诊断等领域,多分类预测任务对模型的时序特征捕捉能力提出了极高要求。传统LSTM网络虽能有效建模长程依赖关系,但其性能高度依赖超参数的选择,例如隐含层神经元数量、学习率、迭代次数等。…...
Qt中C++与QML交互从原理、方法与实践陷阱深度解析
在我们使用Qt开发中,现在以及普遍通过 C 与 QML 的交互,将 C 的强大功能与 QML 的界面设计优势相结合,既保证了应用程序的性能和稳定性,又能快速实现美观、易用的用户界面。接下来专门讲下C与QML交互原理、方法与实践中的一些陷阱…...
基于SpringBoot和Leaflet的邻省GDP可视化实战
目录 前言 一、技术实现路径 1、空间数据检索 2、数据展示检索流程 二、SpringBoot后台实现 1、模型层实现 2、控制层实现 三、WebGIS前端实现 1、控制面展示 2、成果展示 四、总结 前言 在数字化浪潮席卷全球的今天,数据已成为驱动社会经济发展、指导政策…...
esp工程报错:something went wrong when trying to build the project esp-idf 一种解决办法
最近上手了正点原子esp32s3板子,环境采用的是vscodeesp-idf插件。导入了正点原子的demo测试,每次都报这个错误无法建造。也不是网上说的ninja error,不是中文路径的问题。 在终端中查看,发现是缺少了git。(我这里没有…...
Grouped-Query Attention(GQA)详解: Pytorch实现
Grouped-Query Attention(GQA)详解 Grouped-Query Attention(GQA) 是 Multi-Query Attention(MQA) 的改进版,它通过在 多个查询头(Query Heads)之间共享 Key 和 Value&am…...
DeepSeek AI人工智能该如何学习?
人工智能(Artificial Intelligence, AI)是当今科技领域的热门话题,它涵盖了机器学习、深度学习、自然语言处理、计算机视觉等多个子领域。 作为中国科技发展的核心方向之一,AI在国家战略规划中占据了重要地位,特别是在…...
【数据库】【MySQL】索引
MySQL中索引的概念 索引(MySQL中也叫做"键(key)")是一种数据结构,用于存储引擎快速定找到记录。 简单来说,它类似于书籍的目录,通过索引可以快速找到对应的数据行,而无需…...
SprinBoot整合HTTP API:从零开始的实战指南
在现代 Web 开发中,HTTP API 是前后端交互的核心。Spring Boot 作为 Java 生态中备受欢迎的框架,提供了简洁而强大的方式来构建和整合 HTTP API。本文将带你从零开始,通过具体代码示例,展示如何在 Spring Boot 中整合 HTTP API,实现高效、稳定的前后端通信。 一、为什么选…...
可狱可囚的爬虫系列课程 13:Requests使用代理IP
一、什么是代理 IP 代理 IP(Proxy IP)是一个充当“中间人”的服务器IP地址,用于代替用户设备(如电脑、手机等)直接与目标网站或服务通信。用户通过代理IP访问互联网时,目标网站看到的是代理服务器的IP地址&…...
DBeaver下载安装及数据库连接(MySQL)
1. DBeaver下载 官网下载地址:Download | DBeaver Community 2. 安装 1. 双击下载的安装包,选择简体中文。 2. 点击下一步。 3. 点击我接受。 4. 如下勾选为所有用户安装,点击下一步。 5. 需重复做1~3 的步骤。 6. 选择组件,默认即可&…...
国产开源PDF解析工具MinerU
前言 PDF的数据解析是一件较困难的事情,几乎所有商家都把PDF转WORD功能做成付费产品。 PDF是基于PostScript子集渲染的,PostScript是一门图灵完备的语言。而WORD需要的渲染,本质上是PDF能力的子集。大模型领域,我们的目标文件格…...
消息中间件的开源实现
根据你的需求,以下是一些可以实现类似阿里巴巴 MetaQ 功能的消息中间件和相关项目,这些项目可以帮助你实现消息的动态配置和管理: 1. RocketMQ RocketMQ 是一个分布式消息中间件,支持高吞吐量、低延迟的消息传递,适合…...
AcWing 299 裁剪序列
这道题算是我做过所有的单调队列优化 d p dp dp 题目中最难想的一道题,所以写篇题解再捋捋思路。 暴力 首先很容易想到设 d p i dp_i dpi 表示将前 i i i 个数划分成若干序列,【每个序列的最大值之和】的最小值。 那么就会有: d p i …...
P2889 [USACO07NOV] Milking Time S
题目大意 有 N N N 个小时可以挤奶。其中有 m m m 个时间段可以给 Bessis 奶牛挤奶。第 i i i 个时间段为 s i s_i si ~ t i t_i ti,可以获得 E f f i Eff_i Effi 滴奶。每次挤完奶后,人都要休息 R R R 小时。最后问,一共能挤出…...
基于Spring Boot的健康医院门诊在线挂号系统设与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
PyTorch-基础(CUDA、Dataset、transforms、卷积神经网络、VGG16)
PyTorch-基础 环境准备 CUDA Toolkit安装(核显跳过此步骤) CUDA Toolkit是NVIDIA的开发工具,里面提供了各种工具、如编译器、调试器和库 首先通过NVIDIA控制面板查看本机显卡驱动对应的CUDA版本,如何去下载对应版本的Toolkit工…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
Unity UGUI Button事件流程
场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...
