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;尤其是在蛇年这样充满变数和机遇的年份。外贸网站源码…

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从其财政预…

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

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

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

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

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

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

2.11寒假作业

web&#xff1a;[SWPUCTF 2022 新生赛]js_sign 打开环境是这样的&#xff0c;随便输入进行看看 提示错误&#xff0c;看源码其中的js代码 这个代码很容易理解&#xff0c;要让输入的内容等于对应的字符串&#xff0c;显然直接复制粘贴是错的 这串字符看起来像是base64加密&…

c# http

C#代码 客户端&#xff1a; NETCore提供了三种不同类型用于生产的REST API&#xff1a; HttpWebRequest;WebClient;HttpClient HttpWebRequest 这是.NET创建者最初开发用于使用HTTP请求的标准类。使用HttpWebRequest可以让开发者控制请求/响应流程的各个方面&#xff0c;如…

哈希表实现(C++实现)

目录 1.哈希概念 2.哈希冲突 3.哈希函数 4.哈希冲突解决 闭散列 —— 开放定址法 线性探测 二次探测 开散列 —— 链地址法&#xff08;拉链法、哈希桶&#xff09; 5.哈希表的闭散列实现 哈希表的结构 哈希表的大小和扩容 哈希表的插入 哈希表的查找 哈希表的删除…

开箱即用:一个易用的开源表单工具!

随着互联网的普及&#xff0c;表单应用场景越来越广泛&#xff0c;从网站注册、调查问卷到考试测评&#xff0c;无处不在。传统的表单制作方式需要一定的代码基础&#xff0c;对于不懂编程的小伙伴来说&#xff0c;无疑是一道门槛。 今天&#xff0c;给大家分享一款开源的表单…

牛客 BM1: 反转链表

目录 一、题目 二、C解题程序框架 1. 结构体定义 2. 类定义 3. 输入输出说明 三、链表指针 1. 链表指针的基本概念 2. 链表指针的常见操作 1. 遍历链表 2. 插入节点 3. 删除节点 3. 链表指针操作的注意事项 4. 总结 四、解题 方法一&#xff1a;迭代法 方法二&…

MIT开源7B推理模型Satori:用行动思维链进行强化学习,增强自回归搜索

自OpenAI的o1发布以来&#xff0c;研究社区为提升开源LLM的高级推理能力做出了诸多努力&#xff0c;包括使用强大的教师模型进行蒸馏、蒙特卡洛树搜索&#xff08;MCTS&#xff09;以及基于奖励模型的引导搜索等方法。 本研究旨在探索一个新的研究方向&#xff1a;使LLM具备自回…

Kubernetes控制平面组件:etcd(一)

云原生学习路线导航页&#xff08;持续更新中&#xff09; kubernetes学习系列快捷链接 Kubernetes架构原则和对象设计&#xff08;一&#xff09;Kubernetes架构原则和对象设计&#xff08;二&#xff09;Kubernetes架构原则和对象设计&#xff08;三&#xff09;kubectl 和 …

Django在终端创建项目(pycharm Windows)

1.选择目录 选择或新建一个文件夹&#xff0c;作为项目保存的地方 2.右键在终端打开 3.确定django-admin.exe安装位置 找到自己安装django时&#xff0c;django-admin.exe安装的位置&#xff0c;例如 4.运行命令 使用django-admin.exe的绝对路径&#xff0c;在刚才打开的终端…