SpringCloud - Gateway 网关

前言

该博客为Sentinel学习笔记,主要目的是为了帮助后期快速复习使用
学习视频:7小快速通关SpringCloud
辅助文档:SpringCloud快速通关
源码地址:cloud-demo

一、简介

官网:https://spring.io/projects/spring-cloud-gateway

Spring Cloud Gateway 是基于 Spring 生态系统(包括 Spring 6、Spring Boot 3 和 Project Reactor)构建的 API 网关。它旨在为 API 提供简单而有效的路由,并处理诸如安全性、监控/指标和弹性等跨领域关注点。
在这里插入图片描述

1.1 主要特性

  • 构建于 Spring Framework 和 Spring Boot 之上: 利用 Spring 强大的生态系统,确保与其他 Spring 项目的无缝集成。
  • 灵活的路由匹配: 能够基于任何请求属性(如路径、主机、方法等)定义路由规则。
  • 丰富的谓词和过滤器: 为每个路由提供特定的谓词和过滤器,方便实现复杂的路由逻辑和请求/响应的修改。
  • 断路器集成: 与 Hystrix 等断路器库集成,增强系统的弹性和容错能力。
  • 服务发现集成: 与 Spring Cloud DiscoveryClient 集成,实现动态路由和负载均衡。
  • 请求速率限制: 提供请求速率限制功能,保护后端服务免受流量突增的影响。
  • 路径重写: 支持对请求路径进行重写,满足不同的路由需求。

1.2 主要功能

在这里插入图片描述

1.3 版本选择

Spring Cloud Gateway 的两个版本主要区别在于它们的编程模型和适用场景:

  • Reactive Server(响应式版本)
    • 基于 WebFlux 框架,使用响应式编程模型。
    • 支持完全非阻塞的 I/O 操作,可以提高吞吐量和降低延迟。
    • 适用于构建高性能、高并发的微服务架构。
    • 与现代的响应式编程库(如 Reactor)兼容。
  • Server MVC(传统阻塞式版本)
    • 基于 Spring MVC 框架,使用传统的同步阻塞 I/O 模型。
    • 更适合与现有的 Spring MVC 应用程序集成。
    • 可能在高并发场景下的性能不如响应式版本。

推荐使用响应式Gateway
在这里插入图片描述

二、快速入门

2.1 需求

  1. 客户端发送 /api/order/** 转到 service-order
  2. 客户端发送 /api/product/** 转到 service-product
  3. 以上转发有负载均衡效果
    在这里插入图片描述

2.2 创建模块

创建gateway模块,引入 spring-cloud-starter-gatewayspring-cloud-starter-alibaba-nacos-discoveryspring-cloud-starter-loadbalancer

 <!-- gateway网关 --><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><!--loadbalancer负载均衡--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>

添加主程序GatewayMainApplication

@SpringBootApplication
public class GatewayMainApplication {public static void main(String[] args) {SpringApplication.run(GatewayMainApplication.class, args);}
}

添加配置文件application.yml

# 服务端口
server:port: 80spring:application:name: gateway # 服务名称cloud:nacos:server-addr: 127.0.0.1:8848 # nacos地址(默认)

这里可以启动微服务gatewayservice-orderservice-product,确保在Nacos控制台可以看到
在这里插入图片描述

2.3 改造微服务

创建 application-route.yml,为 service-orderservice-prduct 添加 /api基础路径

spring:cloud:gateway:routes:- id: order-routeuri: lb://service-order  # lb(LoadBalance)代表负载均衡predicates: # 路径断言规则- Path=/api/order/** # 路径匹配- id: product-routeuri: lb://service-productpredicates:- Path=/api/product/**

并且需要在application.yml中启用 application-route.yml才能生效

spring:profiles:include: route # 启用route

2.4 测试

在浏览器中输入http://localhost/api/order/readDb,通过网关访问 service-order微服务的接口
在这里插入图片描述

2.5 基础原理

  1. 请求处理
    • 用户请求首先到达 Gateway
  2. 路由规则(Route)
    • 网关根据预定义的路由规则(Route)来决定请求的转发路径。
    • 每个路由规则包含三个主要部分:
      • Predicate 断言:用于匹配请求的条件,如路径、头信息、查询参数等。
      • URI 目的地:匹配请求后,请求将被转发到的目标地址。
      • Filter 过滤器:在请求转发前后执行的一系列过滤器链,用于修改请求/响应、进行认证等。
  3. 过滤器链(Filter Chain)
    • 请求在转发到目的地之前,会先经过一系列过滤器(Filter)的处理。
    • 过滤器可以执行各种任务,如日志记录、请求修改、认证授权等。
    • 过滤器按照定义的顺序执行,形成一个过滤器链。
  4. 转发请求
    • 经过过滤器链处理后,请求被转发到最终的目的地(服务提供者)。
  5. 响应处理
    • 目的地处理完请求后,将响应返回给网关。
    • 响应同样会经过过滤器链的处理,然后返回给用户。

在这里插入图片描述

三、Predicate - 断言

3.1 断言写法

3.1.1 短写法

快捷方式配置由过滤器名称识别,后跟等号 (=),后跟用逗号 () 分隔的参数值。

# 断言短写法
spring:cloud:gateway:routes:- id: order-routeuri: lb://service-order  # lb(LoadBalance)代表负载均衡predicates: # 路径断言规则- Path=/api/order/** # 路径匹配

3.1.2 全写法

完全展开的参数看起来更像是带有名称/值对的标准 yaml 配置。通常,将有一个 name 键和一个 args 键。args 键是用于配置谓词或筛选条件的键值对的映射。

# 断言全写法
spring:cloud:gateway:routes:- id: order-routeuri: lb://service-order  # lb(LoadBalance)代表负载均衡predicates:- name: Path # 路径断言args: # 参数pattern: /api/order/**  # 匹配路径matchTrailingSlash: true # 匹配尾部斜杠

3.2 断言工厂

在这里插入图片描述
在这里插入图片描述

3.3 自定义断言工厂

创建XxxRoutePredicateFactory继承AbstractRoutePredicateFactory

/*** Vip断言工厂*/
@Component
public class VipRoutePredicateFactory extends AbstractRoutePredicateFactory<VipRoutePredicateFactory.Config> {public VipRoutePredicateFactory() {super(Config.class);}// 配置参数的顺序,为短写法准备@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList("param", "value");}// 断言逻辑@Overridepublic Predicate<ServerWebExchange> apply(Config config) {return new GatewayPredicate() {@Overridepublic boolean test(ServerWebExchange serverWebExchange) {// localhost/search?q=haha&user=jyhString first = serverWebExchange.getRequest().getQueryParams().getFirst(config.param);return StringUtils.hasText(first) && first.equals(config.value);}};}/*** 可以配置的参数*/@Validatedpublic static class Config {@NotEmptyprivate String param;@NotEmptyprivate String value;public @NotEmpty String getParam() {return param;}public void setParam(@NotEmpty String param) {this.param = param;}public @NotEmpty String getValue() {return value;}public void setValue(@NotEmpty String value) {this.value = value;}}
}

编写配置文件

spring:cloud:gateway:routes:- id: bing-routeuri: https://cn.bing.com/ # 跳转地址predicates:- name: Path # 路径断言args:patterns: /search- name: Query # 查询参数断言args:param: q #  参数名regexp: haha  # 正则表达式
#            - Vip=user,jyh- name: Vip # 自定义Vip断言args:param: uservalue: jyh

四、Filter - 过滤器

在这里插入图片描述
在这里插入图片描述

4.1 路由重写 - RewritePath

在这里插入图片描述

spring:cloud:gateway:routes:- id: order-routeuri: lb://service-order  # lb(LoadBalance)代表负载均衡predicates:- name: Path # 路径断言args: # 参数pattern: /api/order/**  # 匹配路径matchTrailingSlash: true # 匹配尾部斜杠filters:- RewritePath=/api/order/?(?<segment>.*), /$\{segment} # 重写路径

RewritePath=/api/order/?(?<segment>.*), /$\{segment}这个规则的意思是:
如果请求路径以 /api/order/ 开头,且后面有任意内容(如 /api/order/123),则会将路径重写为 /123 ,即删除 /api/order/ 部分,只保留后面的内容。

4.2 添加响应请求头 - AddResponseHeader

spring:cloud:gateway:routes:- id: order-routeuri: lb://service-order  # lb(LoadBalance)代表负载均衡predicates:- name: Path # 路径断言args: # 参数pattern: /api/order/**  # 匹配路径matchTrailingSlash: true # 匹配尾部斜杠filters:- AddResponseHeader=X-Response-Abc, 123 # 添加响应请求头

在这里插入图片描述

4.3 默认filter - Default Filters

所有路由规则都生效默认filter里面配置的规则

spring:cloud:gateway:routes:- id: order-routeuri: lb://service-order  # lb(LoadBalance)代表负载均衡predicates:- name: Path # 路径断言args: # 参数pattern: /api/order/**  # 匹配路径matchTrailingSlash: true # 匹配尾部斜杠filters:- RewritePath=/api/order/?(?<segment>.*), /$\{segment} # 重写路径- id: product-routeuri: lb://service-productpredicates:- Path=/api/product/**filters:- RewritePath=/api/product/?(?<segment>.*), /$\{segment} # 重写路径default-filters: # 默认过滤器- AddResponseHeader=X-Response-Abc, 123 # 添加响应头

4.4 全局filter - Global Filters

/*** 全局过滤器 - 耗时统计* @author jiangyiheng*/
@Slf4j
@Component
public class RtGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String uri = exchange.getRequest().getURI().toString();long start = System.currentTimeMillis();log.info("请求开始【{}】开始时间:{}", uri, start);// ======================以上是前置逻辑======================Mono<Void> filter = chain.filter(exchange).doFinally((result)->{// ======================以下是后置逻辑======================long end = System.currentTimeMillis();log.info("请求结束【{}】结束时间:{} ,耗时:{}ms", uri, end, end - start);}); // 放行return filter;}// 优先级@Overridepublic int getOrder() {return 0;}
}

在这里插入图片描述

4.5 自定义过滤器

创建一个XxxGatewayFilterFactory类继承AbstractNameValueGatewayFilterFactory工厂

/*** 自定义过滤器-令牌网关过滤器*/
@Component
public class OneTokenGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {@Overridepublic GatewayFilter apply(NameValueConfig config) {return new GatewayFilter() {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 每次响应前,添加一个一次性令牌,支持 uuid,jwt等各种格式return chain.filter(exchange).then(Mono.fromRunnable(()->{ServerHttpResponse response = exchange.getResponse();String value = config.getValue();if ("uuid".equalsIgnoreCase(value)) {value = UUID.randomUUID().toString();}if ("jwt".equalsIgnoreCase(value)) {value = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";}response.getHeaders().add(config.getName(), value);}));}};}
}

在这里插入图片描述

五、CORS - 跨域处理

5.1 全局跨域

spring:cloud:gateway:globalcors:cors-configurations:'[/**]':allowed-origin-patterns: '*' # 允许所有跨域allowed-methods: '*' # 允许所有请求方式allowed-headers: '*' # 允许所有头

5.2 局部跨域

spring:cloud:gateway:routes:- id: cors_routeuri: https://example.orgpredicates:- Path=/service/**metadata:cors:allowedOrigins: '*'allowedMethods:- GET- POSTallowedHeaders: '*'maxAge: 30

面试题:微服务之间的调用经过网关吗?
在这里插入图片描述
微服务之间的调用一般不会经过网关。网关主要用于处理外部请求,负责路由、认证、限流等功能。而微服务之间的通信通常通过服务发现负载均衡直接进行,不需要经过网关。然而,在某些特殊情况下,如果需要统一管理或控制,微服务之间的调用也可能通过网关。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

律所录音证据归集工具:基于PyQt6与多线程的自动化音频管理解决方案

在律所日常工作中&#xff0c;音频证据的整理与归集是一个高频且复杂的任务。面对大量的案件录音文件&#xff0c;如何实现快速且准确的分类与存档&#xff0c;成为了律所提高效率、降低出错率的关键。本文将通过技术角度解析一款名为律所录音证据归集工具的项目&#xff0c;详…

外贸网站源码 助力企业抢占蛇年市场先机!

在竞争激烈的外贸市场中&#xff0c;蛇年无疑是企业寻求突破与增长的关键一年。外贸网站源码为企业提供了快速搭建专业外贸网站的解决方案&#xff0c;助力企业在新的一年抢占市场先机。 快速上线 时间就是商机&#xff0c;尤其是在蛇年这样充满变数和机遇的年份。外贸网站源码…

什么是 Elasticsearch?

Elasticsearch 是一个非常强大的开源搜索和分析引擎&#xff0c;广泛应用于各种需要全文搜索、结构化搜索、聚合分析以及复杂数据分析的场景。下面我们就一起来揭开 Elasticsearch 的神秘面纱吧&#xff01; 什么是 Elasticsearch&#xff1f; Elasticsearch 是由 Elastic 公…

PyCharm结合DeepSeek-R1

PyCharm结合DeepSeek-R1&#xff0c;打造专属 AI 编程助手 在程序员的日常工作中&#xff0c;提高编程效率、快速解决代码问题是重中之重。今天给大家分享一个强强联合的组合 ——PyCharm 插件 Continue 与 DeepSeek-R1&#xff0c;它们能帮你打造出强大的个人 AI 编程助手。 …

DeepSeek-Coder系列模型:智能编程助手的未来

文章目录 一、模型架构与核心功能1. 模型架构2. 核心功能 二、多语言支持与代码生成1. Python代码生成2. Java代码生成3. C代码生成4. JavaScript代码生成 三、仓库级代码理解1. 代码结构分析2. 上下文理解 四、FIM填充技术1. 函数自动填充2. 代码补全 五、应用场景1. 代码补全…

Spring Boot从入门到精通:核心知识点+实战指南

目录 一、Spring Boot 是什么&#xff1f;为什么它如此流行&#xff1f; 二、快速创建你的第一个Spring Boot应用 2.1 使用Spring Initializr生成项目 2.2 核心代码示例 三、深度解析Spring Boot核心机制 3.1 自动配置原理揭秘 3.2 自定义Starter实战 四、生产环境必备…

bash shell笔记——循环结构

0 引言 本文主要介绍linux bash shell循环结构的基本使用 1 测试环境 查看系统版本&#xff1a; uname -a : Ubuntu 18.04 查看bash版本&#xff1a; bash -version : GNU bash, version 4.4.20(1)-release 创建.sh文件&#xff1a; vim 00test.sh 修改00test.sh权限&…

C/C++算法竞赛学习书籍

文章目录 C Primer Plus&#xff1a;中文版&#xff08;第六版&#xff09;C Primer 中文版&#xff08;第 5 版&#xff09;算法竞赛进阶指南 (李煜东)挑战程序设计竞赛 (秋叶拓哉 岩田阳一 北川宜稔)算法竞赛入门经典&#xff08;第2版&#xff09; (刘汝佳)啊哈算法 (啊哈磊…

Word成功接入DeepSeek详细步骤

原理 原理是利用Word的VBA宏&#xff0c;写代码接入API。无需下载额外插件。 步骤一、注册硅基流动 硅基流动统一登录 注册这个是为了有一个api调用的api_key&#xff0c;有一些免费的额度可以使用。大概就是这个公司提供token&#xff0c;我们使用这个公司的模型调用deepsee…

vue-点击生成动态值,动态渲染回显输入框

1.前言 动态点击生成数值&#xff0c;回显输入框&#xff0c;并绑定。 2.实现 <template><div style"display:flex;align-items: center;flex-direction:row"><a-input:key"inputKey"v-model"uploadData[peo.field]"placehold…

Python 识别图片和扫描PDF中的文字

目录 工具与设置 Python 识别图片中的文字 Python 识别图片中的文字及其坐标位置 Python 识别扫描PDF中的文字 注意事项 在处理扫描的PDF和图片时&#xff0c;文字信息往往无法直接编辑、搜索或复制&#xff0c;这给信息提取和分析带来了诸多不便。手动录入信息不仅耗时费…

利用邮件合并将Excel的信息转为Word(单个测试用例转Word)

利用邮件合并将Excel的信息转为Word 效果一览效果前效果后 场景及问题解决方案 一、准备工作准备Excel数据源准备Word模板 二、邮件合并操作步骤连接Excel数据源插入合并域预览并生成合并文档 效果一览 效果前 效果后 场景及问题 在执行项目时的验收阶段&#xff0c;对于测试…

进阶版MATLAB 3D柱状图

%% 1. 数据准备 % 假设数据是一个任意形式的矩阵 % 例如&#xff1a;5行 x 7列的矩阵 data [3 5 2 6 8 4 7;7 2 6 9 3 5 8;4 8 3 7 2 6 9;6 1 5 8 4 7 2;9 4 7 3 6 2 5];% 定义行和列的标签&#xff08;可选&#xff09; rowLabels {Row1, Row2, Row3, Row4, Row5}; % 行标签…

【JVM详解三】垃圾回收机制

一、对象是否存活 强引用&#xff1a;Object obj new Object(); 只要强引用还在&#xff0c;垃圾收集器永远不会回收掉被引用的对象。在不用对象的时将引用赋值为 null&#xff0c;能够帮助垃圾回收器回收对象。比如 ArrayList 的 clear() 方法实现。软引用&#xff08;SoftRe…

【免费】2007-2020年各省医疗卫生支出数据

2007-2020年各省医疗卫生支出数据 1、时间&#xff1a;2007-2020年 2、来源&#xff1a;国家统计局、统计年鉴 3、指标&#xff1a;行政区划代码、地区名称、年份、医疗卫生支出 4、范围&#xff1a;31省 5、指标说明&#xff1a;地方财政医疗卫生支出是指地方ZF从其财政预…

第9章 城市基础设施更新工程 9.3 管网改造施工

9.3 管网改造施工 9.3.1 管网改造施工内容 1.城市管道内部检测技术 管道破坏的后果及严重程度需要通过现场检测、根据破坏范围、管道材料、现场实际情况综合判断。电视监测cctv:管道水位较低状态下的监测&#xff0c;管内水位不宜大于管道直径的20%。直径50-2000mm管道的监测…

【深度学习入门实战】基于Keras的手写数字识别实战(附完整可视化分析)

​ 本人主页:机器学习司猫白 ok,话不多说,我们进入正题吧 项目概述 本案例使用经典的MNIST手写数字数据集,通过Keras构建全连接神经网络,实现0-9数字的分类识别。文章将包含: 关键概念图解完整实现代码训练过程可视化模型效果深度分析环境准备 import numpy as np impo…

利用子问题思路解决二叉树相关Oj题

目录 检查两棵树是否相同&#xff1a;题目链接 判断另⼀棵树的子树是否存在&#xff1a;题目链接 翻转二叉树&#xff1a;题目链接 判断⼀棵二叉树是否是平衡二叉树&#xff1a;题目链接 判断对称二叉树&#xff1a;题目链接 二叉树的层序遍历 二叉树的分层遍历&#xff1a;题目…

腾讯云大数据套件TBDS与阿里云大数据能力产品对比

前言 博主在接触大数据方向研究的时候是在2016年,那时候正是大数据概念非常火热的一个时间段,最著名的Google的3篇论文。Google FS、MapReduce、BigTable,奠定了大数据框架产品的基础。Google文件系统,计算框架和存储框架。往后所有的大数据产品和过程域无一不是在三个模块…

前端如何判断浏览器 AdBlock/AdBlock Plus(最新版)广告屏蔽插件已开启拦截

2个月前AdBlock/AdBlock Plus疑似升级了一次 因为自己主要负责面对海外的用户项目&#xff0c;发现以前的检测AdBlock/AdBlock Plus开启状态方法已失效了&#xff0c;于是专门研究了一下。并尝试了很多方法。 已失效的老方法 // 定义一个检测 AdBlock 的函数 function chec…