在上一篇文章Spring Cloud GateWay 路由轉發規則介紹中我們講解了SpringCloud Gateway
內部提供的斷言、謂語
,讓我們可以組合更精確的業務場景進行請求,既然SpringCloud GateWay
擔任了閘道器
的角色,在之前Zuul
可以通過服務名進行自動轉發,SpringCloud Gateway
是否可以實現自動轉發呢?
初始化Gateway服務
Spring Cloud Gateway
可以根據配置的斷言、謂語
進行滿足條件轉發,也可以自動同步服務註冊中心
的服務列表進行指定serviceId
字首進行轉發,這裡的serviceId
是業務服務的spring.application.name
配置引數。
SpringCloud 版本控制依賴
把SpringCloud
的版本依賴新增到pom.xml
內,如下所示:
//...
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<!--Spring Cloud 版本控制-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
//...
複製程式碼
我們本章使用Eureka
作為服務註冊中心來完成服務請求轉發講解,需要把Spring Cloud Gateway
閘道器專案作為一個Client
註冊到Eureka Server
,先來看下新增的依賴,pom.xml
如下所示:
//...
<dependencies>
<!--Spring Cloud 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>
</dependencies>
//....
複製程式碼
接下來我們需要開啟Gateway
服務註冊中心的發現配置,開啟後才能自動同步服務註冊中心的服務列表
,application.yml
配置檔案如下所示:
# 服務名稱
spring:
application:
name: spring-cloud-gateway
# 開啟 Gateway 服務註冊中心服務發現
cloud:
gateway:
discovery:
locator:
enabled: true
# Eureka Server 配置
eureka:
client:
service-url:
defaultZone: http://localhost:10000/eureka/
# 配置Gateway日誌等級,輸出轉發細節資訊
logging:
level:
org.springframework.cloud.gateway: debug
複製程式碼
配置引數解釋如下所示:
spring.application.name
:服務名spring.cloud.gateway.discovery.locator.enabled
:開啟SpringCloud Gateway
的註冊中心發現配置,開啟後可自動從服務註冊中心拉取服務列表,通過各個服務的spring.application.name
作為字首進行轉發,該配置預設為false
。eureka.client.service-url.defaultZone
:配置Eureka Server
預設的空間地址logging.level.org.springframework.cloud.gateway
:設定SpringCloud Gateway
日誌等級為debug
,用於輸出轉發的細節日誌,方便檢視細節流程。
註冊閘道器到Eureka
在入口類新增對應的註解,開啟服務自動註冊,如下所示:
@SpringBootApplication
@EnableDiscoveryClient
public class SpringCloudGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudGatewayApplication.class, args);
}
}
複製程式碼
服務註冊中心
對應上面閘道器
配置的Eureka Server
的地址,我們需要新增對應的配置,pom.xml
如下所示:
//...
<dependencies>
<!--Eureka Server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
//...
複製程式碼
新增依賴後對Eureka Server
進行配置,配置檔案application.yml
如下所示:
# 服務名
spring:
application:
name: sample-eureka-server
# 埠號
server:
port: 10000
# Eureka 配置資訊
eureka:
client:
service-url:
defaultZone: http://localhost:${server.port}/eureka/
fetch-registry: false
register-with-eureka: false
複製程式碼
這裡我們修改預設的埠號為10000
,為了匹配在閘道器專案
的配置資訊,至於fetch-registry
、register-with-eureka
可以去我之前的文章檢視,SpringCloud元件:將服務提供者註冊到Eureka叢集
開啟Eureka Server
我們通過@EnableEurekaServer
註解來開啟服務,如下所示:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
複製程式碼
閘道器
、服務註冊中心
我們都已經準備好了,下面我們可以編寫業務邏輯服務,來驗證SpringCloud Gateway
具體是否可以根據serviceId
進行轉發請求。
單服務
我們簡單編寫一個GET
請求地址,輸出字串資訊,pom.xml
新增依賴如下所示:
<dependencies>
<!--Web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Eureka Client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
複製程式碼
配置檔案application.yml
如下所示:
# 服務名
spring:
application:
name: user-service
# 註冊到Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:10000/eureka/
# 服務埠號
server:
port: 9090
複製程式碼
配置該服務的服務名稱為user-service
,這裡對應SpringCloud Gateway
的serviceId
。
註冊服務到Eureka
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class UserServiceApplication {
/**
* logger instance
*/
static Logger logger = LoggerFactory.getLogger(UserServiceApplication.class);
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
logger.info("「「「「「使用者服務啟動完成.」」」」」");
}
@GetMapping(value = "/index")
public String index() {
return "this is user index";
}
}
複製程式碼
user-service
提供了/index
的請求地址,當訪問時,會對應輸出this is user index
。
測試服務請求轉發
接下來我們進行驗證,測試順序如下所示:
第一步:啟動Eureka Server
第二步:啟動SpringCloud Gateway
啟動成功後控制檯會列印響應的註冊到Eureka
的日誌資訊,如下所示:
DiscoveryClient_SPRING-CLOUD-GATEWAY/192.168.1.56:spring-cloud-gateway: registering service...
Netty started on port(s): 8080
複製程式碼
SpringCloud Gateway
內部通過Netty
完成WebServer
的請求轉發。
第三步:啟動user-service服務
啟動成功後控制檯列印相應註冊日誌,如下所示:
DiscoveryClient_USER-SERVICE/192.168.1.56:user-service:9090: registering service...
Tomcat started on port(s): 9090 (http) with context path ''
複製程式碼
第四步:測試訪問
SpringCloud Gateway
會每間隔30秒
進行重新拉取服務列表後路由重定義操作,日誌資訊如下所示:
# Spring Cloud Gateway
RouteDefinition CompositeDiscoveryClient_SPRING-CLOUD-GATEWAY applying {pattern=/SPRING-CLOUD-GATEWAY/**} to Path
RouteDefinition CompositeDiscoveryClient_SPRING-CLOUD-GATEWAY applying filter {regexp=/SPRING-CLOUD-GATEWAY/(?<remaining>.*), replacement=/${remaining}} to RewritePath
RouteDefinition matched: CompositeDiscoveryClient_SPRING-CLOUD-GATEWAY
# User Service
RouteDefinition CompositeDiscoveryClient_USER-SERVICE applying {pattern=/USER-SERVICE/**} to Path
RouteDefinition CompositeDiscoveryClient_USER-SERVICE applying filter {regexp=/USER-SERVICE/(?<remaining>.*), replacement=/${remaining}} to RewritePath
RouteDefinition matched: CompositeDiscoveryClient_USER-SERVICE
複製程式碼
通過上面的日誌資訊我們已經可以推斷出SpringCloud Gateway
對映spring.application.name
的值作為服務路徑字首,不過是大寫的,預計我們可以通過http://localhost:8080/USER-SERVICE/index
訪問到對應的資訊。
訪問測試如下:
~ curl http://localhost:8080/USER-SERVICE/index
this is user index
複製程式碼
通過閘道器訪問具體服務的格式:http://閘道器IP:閘道器埠號/serviceId/**
多服務的負載均衡
如果Eureka Server
上有兩個相同serviceId
的服務時,SpringCloud Gateway
會自動完成負載均衡。
複製一個user-service
服務例項,修改服務埠號
,如下所示:
# 服務名稱
spring:
application:
name: user-service
# Eureka Server
eureka:
client:
service-url:
defaultZone: http://localhost:10000/eureka/
# 服務埠號
server:
port: 9091
複製程式碼
在複製的專案內使用相同的spring.application.name
保持serviceId
一致,只做埠號的修改,為了區分GateWay
完成了負載均衡,我們修改/index
請求的返回內容如下所示:
@GetMapping(value = "/index")
public String index() {
return "this is user lb index";
}
複製程式碼
訪問http://localhost:8080/USER-SERVICE/index
,輸出內容如下所示:
this is user lb index
this is user index
this is user lb index
this is user index
...
複製程式碼
總結
通過本章的講解,我們已經對SpringCloud Gateway
的轉發有一個簡單的理解,通過從服務註冊中心拉取服務列表後,自動根據serviceId
對映路徑字首,同名服務多例項時會自動實現負載均衡。
原始碼位置
Gitee
:gitee.com/hengboy/spr…