目录
11.服务网关-Gateway新一代网关
一、Gateway概述
1、Gateway是什么
1.1 概述
2、 能干嘛
3、微服务架构中网关在哪里
4、为什么选择gateway?
4.1 SpringCloud Gateway具有如下特性
4.2 SpringCloud Gateway 与 Zuul的区别
5、Zuul1.x模型
6、gateway模型
二、Gateway的三大核心概念与工作流程
1、Route(路由)
2、Predicate(断言)
3、Filter(过滤)
4、总结
三、工作流程
四、入门配置
1、创建cloud-gateway-gateway-9527 模块
2、pom
3、yml
4、主启动类(网关不需要业务类)
5. Gateaway9527网关如何做路由映射呢?
6、测试
7、Gateway网关路由有两种配置方式
7.1 在yml中配置——之前的方式
7.2 代码中注入RouteLocator的Bean
7.3 测试
五、进阶
5.1 通过微服务名实现动态路由
5.1.1 目前面临的问题
5.1.2 修改9527实现动态路由
5.1.3 测试
六、Predicate 断言的使用
1、常用的Predicate 断言
1. After Route Predicate:
2.Before Route Predicate:
3.Between Route Predicate:
4.Cookie Route Predicate:
5.Header Route Predicate:
6.Host Route Predicate:
7.Method Route Predicate:
8.Path Route Predicate:
9.Query Route Predicate:
2、小总结
七、Filter的使用
1、Filter是什么
2、自定义全局过滤器(GlobalFilter)
12.服务配置-SpringCloud Config分布式配置中心
一、概述
1.1 分布式系统面临的---配置问题
1.2 Config是什么
1.3 怎么用
1.4 能干嘛
二、 Config服务端配置与测试
2.1 用你自己的账号在GitHub上新建一个名为springcloud-config的新Repository
2.2 由上一步获得刚新建的git地址
2.3 本地硬盘目录上新建git仓库并clone
2.4 新建Module模块 cloud-config-center-3344,它就是Cloud的配置中心模块 cloudConfig Center
2.5 pom
2.6 yml
2.7 主启动类
2.8 测试
2.8.1 Https
2.8.2 SSH
2.8.3 映射规则
2.9 配置的读取规则
2.9.1 /{label}/{application}-{profile}.yml
2.9.2 /{application}-{profile}.yml
2.9.3 /{application}/{profile}[/{label}]
2.10 总结
三、Config客户端配置与测试
3.1 新建cloud-config-client-3355
3.2 pom
3.3 bootstrap.yml
3.4 主启动类
3.5 业务类
3.6 测试
3.7 问题随之而来——分布式配置的动态刷新问题
四、Config客户端之动态刷新
4.1 pom引入actuator监控
4.2 修改yml,暴露监控端口
4.3 在业务类上加一个@RefreshScope注解
4.4 测试:3355还是没有动态刷新
4.5 需要运维人员发送Post请求刷新3355
4.6 多个微服务客户端,难道每个微服务都要手动刷新?
13.服务消息总线——SpringCloud Bus
1、概述
1.1 是什么
1.2 能干嘛
1.3 为什么被称为总线
2、RabbitMQ环境配置
3、SpringCloud Bus动态刷新全局广播
3.1 Bus动态刷新全局广播的设计思想和选型
3.2 添加一个新的cloud-config-client-3366
3.2.1 pom
3.2.2 yml
3.2.3 主启动
3.2.4 业务类controller
3.3 配置案例
3.3.1 给cloud-config-center-3344配置中心服务端添加消息总线支持
3.3.2 给cloud-config-client-3355客户端添加消息总线支持
3.3.3 给cloud-config-client-3366客户端添加消息总线支持
3.4 测试
4、SpringCloud Bus动态刷新定点通知
4.1 案例
5、流程总结
14.Stream消息驱动-# SpringCloud Stream消息驱动
一、Stream消息驱动概述
1.1 为什么引入cloud stream?解决的痛点是什么?
1. 市面上存在着多种消息中间件技术
2. 不同的系统中会用到不同的消息中间件,那么当需要系统进行整合时,或者系统进行切换时
3. 那么有没有一种新的技术,让我们不再关注具体的MQ的细节,我们只需要用一种适配绑定的方式,自动的给我们在各种MQ内切换。
4. 引出了SpringCloud Stream
1.2 概述
什么是SpringCloudStream?
官网
1.3 设计思想
1.3.1 传统的消息中间件的流程
1.3.2 为什么用Cloud Stream
1.3.3 stream是怎么统一底层差异的?
1.3.4 Binder
1.4 Spring Cloud Stream标准流程套路
1.5 编码API和常用注解
二、入门案例
2.1 案例说明
2.2 消息驱动之生产者8801
2.2.1 新建module
2.2.2 pom
2.2.3 application.yml
2.2.4 主启动类
2.2.5 业务类
2.2.6 测试
2.3 消息驱动之消费者8802
2.3.1 新建cloud-stream-rabbitmq-consumer8802
2.3.2 pom
2.3.3 application.yml
2.3.4 主启动类
2.3.5 业务类
2.3.6 测试
三、高级特性:分组消费与持久化
3.1 依照8802,clone出一份cloud-stream-rabbitmq-consumer8803
3.1.1 pom
3.1.2 application.yml
3.1.3 主启动类
3.1.4 业务类
3.2 启动测试
3.3 运行后的问题1:重复消费问题
3.3.1 为什么要解决重复消费问题
3.3.2 解决:消息分组
3.3.3 自定义分组
3.3.4 消费组
3.4 运行后的问题2:消息持久化问题
15.Sleuth分布式请求链路跟踪-SpringCloud Sleuth
一、概述
二、搭建链路监控步骤
2.1 zipkin
2.1.1 下载
2.1.2 运行jar&运行控制台
2.1.3 完整的调用链路
2.2 服务提供者cloud-provider-payment8001
2.2.1 pom
2.2.2 yml
2.2.3 业务类PaymentController
2.3 服务消费者cloud-consumer-order80
2.3.1 pom
2.3.2 yml
2.3.3 业务类OrderController
2.4 测试
11.服务网关-Gateway新一代网关
一、Gateway概述
官网:
上一代zuul 1.X https://github.com/Netflix/zuul/wiki
当前gateway : 最新版 ,2.2.1.RELEASE
1、Gateway是什么
Cloud全家桶中有个很重要的组件就是网关,在1.x版本中都是采用Zuul网关;
但在2.x版本中,zuul的升级就是一直跳票,SpringCloud最后自己研发了一个网关代替Zuul
那就是 SpringCloud Gateway ,gateway是zuul 1.x版本的替代。
Gateway是在Spring生态系统之上架构的API网关服务,基于Spring 5,Spring Boot2 和Project Reactor技术。
Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能,例如:熔断、限流、重试等。
1.1 概述
●SpringCloud Gateway 是 Spring Cloud 的一个全新项目,基于 Spring 5.0+Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。
●SpringCloud Gateway作为Spring cloud生态系统中的网关,目标是代替 Zuul,在SpringCloud2.0以上版本中,没有对新版本的Zuul 2.0以上实现最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty,【说穿了就是 SpringCloud Gateway是异步非阻塞式,响应式的框架】
●Spring Cloud Gateway的目标提供统一的路由方式且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。
一句话:SpringCloud Gateway 使用的Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架。
源码架构:
2、 能干嘛
反向代理、鉴权、流量控制、熔断、日志监控等
3、微服务架构中网关在哪里
4、为什么选择gateway?
一方面因为Zuul1.0已经进入了维护阶段,同时Zuul2.0疯狂跳票。而且Gateway是SpringCloud团队研发的,是亲儿子产品,值得信赖。
而且很多功能Zuul都没有用起来也非常的简单便捷。
Gateway是基于异步非阻塞模型上进行开发的,性能方面不需要担心。虽然Netflix早就发布了最新的 Zuul 2.x,
但 Spring Cloud 貌似没有整合计划。而且Netflix相关组件都宣布进入维护期;不知前景如何?
多方面综合考虑Gateway是很理想的网关选择。
4.1 SpringCloud Gateway具有如下特性
●基于Spring Frameword5 ,Project Reactor 和 SpringBoot 2.0进行构建;
●动态路由:能够匹配任何请求属性
●可以对路由指定Predicate(断言)和Filter(过滤器)
●集成Hystrix的断路器功能;
●集成Spring Cloud的服务发现功能
●易于编写的Predicate(断言)和Filter(过滤器)
●请求限流功能;
●支持路径重写
4.2 SpringCloud Gateway 与 Zuul的区别
在SpringCloud Finchley 正式版之前(现在H版),SpringCloud推荐的网关是Netflix提供的zuul。
1.Zuul1.x 是一个基于阻塞 I/O的API网关
2.Zuul1.x 基于Servlet2.5使用阻塞架构它不支持任何长连接 (如WebSocket)Zuul的设计模式和Nginx较像,每次I/O操作都是从工作线程中选择一个执行,请求线程被阻塞到工作线程完成,但是差别是Nginx用C++实现,Zuul用java实现,而JVM本身会有第一次加载较慢的情况,使得Zuul的性能相对较差。
3.Zuul 2.x理念更加先进,像基于Netty非阻塞和支持长连接,但SpringCloud目前还没有整合。Zuul2.x的性能较Zuul 1.x有较大的提升。在性能方面,根据官方提供的基准测试,Spring Cloud Gateway的RPS(每秒请求次数)是Zuul的1.6倍。
4.Spring Cloud Gateway建立在Spring Framework 5、project Reactor和Spring Boot2 之上,使用非阻塞API
5.Spring Cloud Gateway 还支持WebSocket,并且与Spring紧密集成拥有更好的开发体验。
5、Zuul1.x模型
Springcloud中所集成的Zuul版本,采用的是Tomcat容器,使用的是传统的Servlet IO处理模型。
Servlet的生命周期?servlet由servlet container进行生命周期管理。
container启动时构造servlet对象并调用servlet init()进行初始化;
container运行时接受请求,并为每个请求分配一个线程(一般从线程池中获取空闲线程)然后调用service()。
container关闭时调用servlet destory()销毁servlet;
上述模式的缺点:
servlet是一个简单的网络IO模型,当请求进入servlet container时,servlet container就会为其绑定一个线程,在并发不高的场景下这种模型是适用的。但是一旦高并发(比如抽风用jemeter压),线程数量就会上涨,而线程资源代价是昂贵的(上线文切换,内存消耗大)严重影响请求的处理时间。在一些简单业务场景下,不希望为每个request分配一个线程,只需要1个或几个线程就能应对极大并发的请求,这种业务场景下servlet模型没有优势
所以Zuul 1.X是基于servlet之上的一个阻塞式处理模型,即spring实现了处理所有request请求的一个servlet(DispatcherServlet)并由该servlet阻塞式处理处理。所以Springcloud Zuul无法摆脱servlet模型的弊端
6、gateway模型
Redirecting...
传统的Web框架,比如说:struts2,springmvc等都是基于Servlet API与Servlet容器基础之上运行的。
但是在Servlet3.1之后有了异步非阻塞的支持。而WebFlux是一个典型非阻塞异步的框架,它的核心是基于Reactor的相关API实现的。相对于传统的web框架来说,它可以运行在诸如Netty,Undertow及支持Servlet3.1的容器上。非阻塞式+函数式编程(Spring5必须让你使用java8)
Spring WebFlux 是 Spring 5.0 引入的新的响应式框架,区别于 Spring MVC,它不需要依赖Servlet API,它是完全异步非阻塞的,并且基于 Reactor 来实现响应式流规范。
二、Gateway的三大核心概念与工作流程
1、Route(路由)
路由是构建网关的基本模块,它由ID,目标URI(Uniform Resource Identifier,统一资源标识符),一系列的断言和过滤器组成,如果断言为true则匹配该路由。
2、Predicate(断言)
开发人员可以匹配Http请求中的所有内容(例如请求头或者请求参数),如果请求参数与断言相匹配则进行路由。
3、Filter(过滤)
指的是Spring框架中的GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
4、总结
●web 请求,通过一些匹配条件,定位到真正的服务节点,并在这个转发过程的前后,进行一些精细化控制
●predicate 就是我们的匹配条件
●filter:就可以理解为一个无所不能的拦截器,有了这两个元素,再加上目标的uri,就可以实现一个具体的路由了。
三、工作流程
●
●客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。
●Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。
●过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。
●Filter在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。
核心逻辑:路由转发+执行过滤器链
四、入门配置
1、创建cloud-gateway-gateway-9527 模块
2、pom
做网关不需要添加 web starter 否则会报错
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>springcloud2020</artifactId><groupId>org.xu.springcloud</groupId><version>1.0.0</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-gateway-gateway-9527</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--gateway--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--eureka-client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity --><dependency><groupId>org.xu.springcloud</groupId><artifactId>cloud-api-commons</artifactId><version>1.0.0</version></dependency><!--一般基础配置类--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies></project>
3、yml
server: port: 9527 #指定应用启动端口为 9527。 访问方式:http://localhost:9527。 spring: application: name: cloud-gateway #作用:定义服务在注册中心(如 Eureka)中的名称,其他服务可通过该名称调用此网关。 #eureka:
eureka: instance: hostname: cloud-gateway-service #作用:指定实例的主机名(可选),通常用于服务发现。 client: service-url: register-with-eureka: true #作用:指定是否将此服务注册到 Eureka 服务器。false 表示不注册。 fetch-registry: true #作用:指定是否从 Eureka 服务器获取注册信息。false 表示不获取。 defaultZone: http://localhost:7001/eureka #作用:指定 Eureka 服务器的地址。
4、主启动类(网关不需要业务类)
package com.java.springcloud; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 { public static void main(String[] args) { SpringApplication.run(GateWayMain9527.class,args); }
}
5. Gateaway9527网关如何做路由映射呢?
我们以前访问cloud-provider-payment8001中的controller方法,通过:
localhost:8001/payment/get/id 和 localhost:8001/payment/lb 就能访问到相应的方法。
现在我们不想暴露8001端口号,希望在8001外面套一层9527
yml新增网关配置
server: port: 9527 #指定应用启动端口为 9527。 访问方式:http://localhost:9527。 spring: application: name: cloud-gateway #作用:定义服务在注册中心(如 Eureka)中的名称,其他服务可通过该名称调用此网关。 cloud: gateway: routes: - id: payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名 uri: http://localhost:8001 #匹配后提供服务的路由地址 predicates: - Path=/payment/get/** #断言,路径相匹配的进行路由 ,合起来的路径就变成了 http://localhost:8001/payment/get/** 如果你的路径是符合这里的就会正常访问到 - id: payment_route2 #路由的ID,没有固定规则但要求唯一,建议配合服务名 uri: http://localhost:8001 #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** #断言,路径相匹配的进行路由 #eureka:
eureka: instance: hostname: cloud-gateway-service #作用:指定实例的主机名(可选),通常用于服务发现。 client: service-url: register-with-eureka: true #作用:指定是否将此服务注册到 Eureka 服务器。false 表示不注册。 fetch-registry: true #作用:指定是否从 Eureka 服务器获取注册信息。false 表示不获取。 defaultZone: http://localhost:7001/eureka #作用:指定 Eureka 服务器的地址。
●routes:可以为controller中所有的rest接口做路由
●uri + predicate拼接:http://localhost:8001/payment/get/** 就是具体的接口请求路径。其中uri是需要通过localhost:9527 映射的地址,即访问localhost:9527会转发到 localhost:8001
●predicate:断言http://localhost:8001下面有一个/payment/get/**这样的地址。如果找到了这个地址就返回true,可以用9527端口访问,进行端口的适配;找不到就返回false,不能用9527这个端口适配。慢慢的就不再暴露微服务本来的接口8001,转而使用统一网关9527。
/get/** 中**表示通配符,因为这里是一个不确定的参数:/get/{id}
这样就为这两个方法做了路由匹配
开始启动测试的时候发现idea启动eureka报错了
2025-06-20 22:24:03.739 ERROR 7172 --- [reka7002.com-14] c.n.e.cluster.ReplicationTaskProcessor : Network level connection to peer eureka7002.com; retrying after delaycom.sun.jersey.api.client.ClientHandlerException: java.net.UnknownHostException: eureka7002.com
因为我自己网络的问题,前天晚上我是把电脑进行过网络重置的,应该是跟这有关系。
果然是,之前在学习eurka的时候是配置过本机电脑host文件相关eurka设置的,打开host文件一看eurka相关设置被注释掉了。
6、测试
启动7001、7002、cloud-provider-payment8001、9527
踩坑提示:gateway不需要spring-boot-starter-web依赖,否在会报错;原因是gateway底层使用的是webflux会与web冲突。
eureka集群中注册了9527和payment8001
直接通过8001访问:成功
通过9527网关访问:成功
7、Gateway网关路由有两种配置方式
7.1 在yml中配置——之前的方式
7.2 代码中注入RouteLocator的Bean
官网案例:
业务需求: 通过9527网关访问到百度新闻的网址;http://news.baidu.com/guonei
在config包下创建一个配置类 路由规则是:我现在访问/guonei,将会转发到http://news.baidu.com/guonei
与之对应的yml:
一定要注意:不管是bean的方式还是配置文件的方式,Path路径的值是拼接在请求地址后面的
package com.java.springcloud.config; import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; @Configuration
public class GateWayConfig { @Bean public RouteLocator customRouteLocator2(RouteLocatorBuilder builder) { /* RouteLocatorBuilder.Builder 是 Spring Cloud Gateway 中用于构建路由定位器(RouteLocator)的构建器类。 它允许你定义一系列的路由规则,这些规则将请求路径映射到相应的目标 URI。通过使用 RouteLocatorBuilder.Builder, 你可以灵活地配置路由,从而实现请求转发、负载均衡等功能。 */ // 创建一个 RouteLocatorBuilder.Builder 对象 RouteLocatorBuilder.Builder routes = builder.routes(); // 创建一个名为 "payment_routh" 的路由(这个是随机起的但是要保证唯一名称),路径为 "/guonei",URI 为 "http://news.baidu.com" routes.route("payment_routh2", r -> r.path("/guonei").uri("http://news.baidu.com")).build(); // 返回构建的 RouteLocatorBuilder.Builder 对象 return routes.build(); } @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { /* RouteLocatorBuilder.Builder 是 Spring Cloud Gateway 中用于构建路由定位器(RouteLocator)的构建器类。 它允许你定义一系列的路由规则,这些规则将请求路径映射到相应的目标 URI。通过使用 RouteLocatorBuilder.Builder, 你可以灵活地配置路由,从而实现请求转发、负载均衡等功能。 */ // 创建一个 RouteLocatorBuilder.Builder 对象 RouteLocatorBuilder.Builder routes = builder.routes(); // 创建一个名为 "payment_routh" 的路由(这个是随机起的但是要保证唯一名称),路径为 "/guonei",URI 为 "http://news.baidu.com/guonei" routes.route("payment_routh", r -> r.path("/guonei12").uri("http://news.baidu.com")).build(); // 返回构建的 RouteLocatorBuilder.Builder 对象 return routes.build(); }
}
7.3 测试
访问localhost:9527/guonei
成功!
2025年百度地址https://news.baidu.com/guonei 是访问不到的,没有这种地址了。
五、进阶
5.1 通过微服务名实现动态路由
5.1.1 目前面临的问题
一个路由规则仅仅只对应一个接口方法,即我们将请求地址写死了。 试想一下:在分布式集群的情况下,会有多少个主机,多少个端口,多少个接口? 难道我们要为每一个接口都定义一个路由规则吗?
解决思路:我们前面用80调用8001和8002中的接口时,只认微服务名。访问接口时没有指定哪个端口。 那么我们在定义路由规则时也可以通过微服务名实现动态路由和负载均衡。
5.1.2 修改9527实现动态路由
默认情况下Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能。
pom:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>
yml:spring.cloud.gateway.discovery.locator.enabled:true;
在添加uri的时候,开始是lb://微服务名
server: port: 9527 #指定应用启动端口为 9527。 访问方式:http://localhost:9527。 spring: application: name: cloud-gateway #作用:定义服务在注册中心(如 Eureka)中的名称,其他服务可通过该名称调用此网关。 cloud: gateway: discovery: locator: enabled: true #作用:指定是否启用从注册中心(如 Eureka)中自动获取服务实例的功能。true 表示启用。 routes: - id: payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
# uri: http://localhost:8001 #匹配后提供服务的路由地址 uri: lb://cloud-payment-service #lb表示负载均衡,后面跟着的是注册中心的服务名 predicates: - Path=/payment/getPaymentById/** #断言,路径相匹配的进行路由 ,合起来的路径就变成了 http://localhost:8001/payment/get/** 如果你的路径是符合这里的就会正常访问到 - id: payment_route2 #路由的ID,没有固定规则但要求唯一,建议配合服务名
# uri: http://localhost:8001 #匹配后提供服务的路由地址 uri: lb://cloud-payment-service #lb表示负载均衡,后面跟着的是注册中心的服务名 predicates: - Path=/payment/lb/** #断言,路径相匹配的进行路由 #eureka:
eureka: instance: hostname: cloud-gateway-service #作用:指定实例的主机名(可选),通常用于服务发现。 client: service-url: register-with-eureka: true #作用:指定是否将此服务注册到 Eureka 服务器。false 表示不注册。 fetch-registry: true #作用:指定是否从 Eureka 服务器获取注册信息。false 表示不获取。 defaultZone: http://localhost:7001/eureka/,http://eureka7002.com:7002/eureka/ #作用:指定 Eureka 服务器的地址。
注意:
uri: lb://cloud-payment-service
lb://开头代表从注册中心中获取服务(Load Balancing),后面接的就是你需要转发到的服务名称,而且找到的服务实现负载均衡。 这里的lb不是代码路径中的lb,不要搞混了,我因为没有专心听讲,误以为这个lb是跟代码中的接口方法路径保持一致,后面验证了一下发现根本不是这么回事,所以专门百度了一下
]()
spring:cloud:gateway:httpclient:connect-timeout: 1000response-timeout: 5s
配置好后的路由规则:
发送localhost:9527/xx/xxx请求,会去找cloud-payment-service服务名中对应微服务实例。 再根据具体的路径,找的具体的方法接口,并且开启了负载均衡。
5.1.3 测试
http://localhost:9527/payment/lb
8001、8002交替,负载均衡的轮循算法
请求其他的方法也是没有问题的。
六、Predicate 断言的使用
我们注意:Predicates 这是一个复数,其实有多种Predicate。 我们这里用的Predicate的是[Path],它是路由规则的其中一个。作用是,如果cloud-payment-service 的微服务实例中有/payment/get**的接口,就会返回true,路由规则生效。
但实际上存在多种Predicate:
每一个断言Predicate都有它独特的规则,多个Predicate断言是一个与&组合。
●Spring Cloud Gateway 将路由匹配作为Spring WebFlux Handler Mapping基础架构的一部分。
●Spring Cloud Gateway 包括许多内置的Route Predicate 工厂,所有的这些Predicate都和Http请求的不同属性匹配,多个Route Predicate可以进行组合。
●Spring Cloud Gateway 创建route对象时,使用RoutePredicateFactory创建Predicate对象,Predicate对象可以赋值给Route,SpringCloud Gateway包含许多内置的Route Predicate Factories.
●所有的 这些谓词都匹配Http的请求的各种属性,多种谓词工厂可以组合,并通过逻辑and
官网对gateway的断言每个都写了栗子:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#the-after-route-predicate-factory
1、常用的Predicate 断言
1. After Route Predicate:
●匹配改断言时间之后的uri请求
●- After=2021-09-28T19:14:51.514+08:00[Asia/Shanghai]
如何获得上述格式的时间呢?
package com.atguigu.test;import java.time.ZoneId;
import java.time.ZonedDateTime;/*** @auther zzyy* @create 2019-12-02 17:37*/
public class ZonedDateTimeDemo
{public static void main(String[] args){ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区System.out.println(zbj);
// ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York")); // 用指定时区获取当前时间
// System.out.println(zny);}
}
配置yml
我自己实际代码配置
spring: application: name: cloud-gateway #作用:定义服务在注册中心(如 Eureka)中的名称,其他服务可通过该名称调用此网关。 cloud: gateway: discovery: locator: enabled: true #作用:指定是否启用从注册中心(如 Eureka)中自动获取服务实例的功能。true 表示启用。 routes: - id: payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
# uri: http://localhost:8001 #匹配后提供服务的路由地址 uri: lb://cloud-payment-service #lb表示负载均衡,后面跟着的是注册中心的服务名 predicates: - Path=/payment/getPaymentById/** #断言,路径相匹配的进行路由 ,合起来的路径就变成了 http://localhost:8001/payment/get/** 如果你的路径是符合这里的就会正常访问到 - id: payment_route2 #路由的ID,没有固定规则但要求唯一,建议配合服务名
# uri: http://localhost:8001 #匹配后提供服务的路由地址 uri: lb://cloud-payment-service #lb表示负载均衡,后面跟着的是注册中心的服务名 predicates: #这个是负数 - Path=/payment/lb1/** #断言,路径相匹配的进行路由 - After=2025-06-22T14:10:03.685+08:00[Asia/Shanghai] #断言,在指定时间之后进行路由
注意我上面配置的是http://localhost:9527/payment/lb1 接口地址的断言规则,而我下面竟然去访问另外一个接口地址了,这里千万要注意了,还是不够专注在学习的时候
测试:
成功
将时间修改到一小时后:报错 (不知道是我浏览器的问题还是idea有问题,修改时间以后重新访问竟然能正常访问,真是奇怪,这句话打脸是我自己代码的问题),当我说完以后我又去看了一下代码,发现是我配置的就不是这个接口地址的规则,而是访问http://localhost:9527/payment/lb1
的断言规则,所以一定要注意自己配置的是哪个接口地址的断言规则
时间配置正确以后可以正常访问
2.Before Route Predicate:
●匹配改断言时间之前的uri请求
这个断言规则跟上面的After规则不能一起使用,因为还有一个Between的路由断言规则,是用来表示时间范围的。使用的时候一定要注意了
spring: application: name: cloud-gateway #作用:定义服务在注册中心(如 Eureka)中的名称,其他服务可通过该名称调用此网关。 cloud: gateway: discovery: locator: enabled: true #作用:指定是否启用从注册中心(如 Eureka)中自动获取服务实例的功能。true 表示启用。 routes: - id: payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
# uri: http://localhost:8001 #匹配后提供服务的路由地址 uri: lb://cloud-payment-service #lb表示负载均衡,后面跟着的是注册中心的服务名 predicates: - Path=/payment/getPaymentById/** #断言,路径相匹配的进行路由 ,合起来的路径就变成了 http://localhost:8001/payment/get/** 如果你的路径是符合这里的就会正常访问到 - id: payment_route2 #路由的ID,没有固定规则但要求唯一,建议配合服务名
# uri: http://localhost:8001 #匹配后提供服务的路由地址 uri: lb://cloud-payment-service #lb表示负载均衡,后面跟着的是注册中心的服务名 predicates: #这个是负数 - Path=/payment/lb1/** #断言,路径相匹配的进行路由 #- After=2025-06-21T14:10:03.685+08:00[Asia/Shanghai] #断言,在指定时间之后进行路由 - Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai] # 断言,路径相匹配的进行路由