目錄
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] # 斷言,路徑相匹配的進行路由