Spring Cloud - 閘道器
簡介
在分散式環境中,服務需要彼此通訊。但是,這是服務間通訊。我們也有這樣的用例:域外的客戶端需要訪問我們的服務的 API。因此,我們可以公開所有微服務地址供客戶端呼叫,或者建立一個服務閘道器來將請求路由到各種微服務並響應客戶端。
在這裡,建立閘道器是一種更好的方法。它有兩個主要優點:
無需維護每個單獨服務的安全性。
並且,可以集中處理橫切關注點,例如新增元資訊。
Netflix Zuul 和 Spring Cloud Gateway 是兩種眾所周知的雲網關,用於處理此類情況。在本教程中,我們將使用 Spring Cloud Gateway。
Spring Cloud Gateway – 依賴設定
讓我們使用我們一直在使用的餐廳案例。讓我們在兩個服務(即餐廳服務和客戶服務)前面新增一個新服務(閘道器)。首先,讓我們使用以下依賴項更新服務的pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
然後,使用正確的註解,即 @EnableDiscoveryClient,註解我們的 Spring 應用程式類。
package com.tutorialspoint;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class RestaurantGatewayService{
public static void main(String[] args) {
SpringApplication.run(RestaurantGatewayService.class, args);
}
}
我們使用 @EnableDiscoveryClient 註解是因為我們想使用 Eureka 服務發現來獲取正在提供特定用例的主機列表。
使用閘道器進行動態路由
Spring Cloud Gateway 有三個重要的組成部分:
路由 - 這些是閘道器的構建塊,包含要將請求轉發到的 URL 以及應用於傳入請求的斷言和過濾器。
斷言 - 這些是一組標準,傳入請求必須匹配這些標準才能轉發到內部微服務。例如,路徑斷言只有在傳入 URL 包含該路徑時才會轉發請求。
過濾器 - 這些充當在將請求傳送到內部微服務之前或在響應客戶端之前修改傳入請求的地方。
讓我們為我們的餐廳和客戶服務編寫一個簡單的閘道器配置。
spring:
application:
name: restaurant-gateway-service
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: customers
uri: lb://customer-service
predicates:
- Path=/customer/**
- id: restaurants
uri: lb://restaurant-service
predicates:
- Path=/restaurant/**
server:
port: ${app_port}
eureka:
client:
serviceURL:
defaultZone: https://:8900/eureka
關於上述配置的幾點說明:
我們啟用了discovery.locator 以確保閘道器可以從 Eureka 伺服器讀取。
我們在這裡使用了 Path 斷言來路由請求。這意味著任何以 /customer 開頭的請求都將路由到客戶服務,對於 /restaurant,我們將該請求轉發到餐廳服務。
現在,讓我們在閘道器服務之前設定其他服務:
啟動 Eureka 伺服器
啟動客戶服務
啟動餐廳服務
現在,讓我們編譯並執行閘道器專案。我們將使用以下命令:
java -Dapp_port=8084 -jar .\target\spring-cloud-gateway-1.0.jar
完成後,我們的閘道器準備好在 8084 埠上進行測試。讓我們首先訪問 https://:8084/customer/1,我們會看到請求被正確路由到客戶服務,並且我們得到以下輸出:
{
"id": 1,
"name": "Jane",
"city": "DC"
}
現在,訪問我們的餐廳 API,即 https://:8084/restaurant/customer/1,我們得到以下輸出:
[
{
"id": 1,
"name": "Pandas",
"city": "DC"
},
{
"id": 3,
"name": "Little Italy",
"city": "DC"
}
]
這意味著兩個呼叫都已正確路由到各自的服務。
斷言和過濾器請求
我們在上面的示例中使用了 Path 斷言。以下是一些其他重要的斷言:
| 斷言 | 描述 |
|---|---|
| Cookie 斷言(輸入:名稱和正則表示式) | 將 Cookie 的“名稱”與“正則表示式”進行比較 |
| Header 斷言(輸入:名稱和正則表示式) | 將 Header 的“名稱”與“正則表示式”進行比較 |
| Host 斷言(輸入:名稱和正則表示式) | 將傳入的“名稱”與“正則表示式”進行比較 |
| 權重斷言(輸入:組名和權重) | 權重斷言(輸入:組名和權重) |
過濾器 用於在將資料傳送到下游服務之前或在將響應傳送回客戶端之前,向請求新增/刪除資料。
以下是一些用於新增元資料的重要的過濾器。
| 過濾器 | 描述 |
|---|---|
| 新增請求頭過濾器(輸入:頭和值) | 在下游轉發請求之前新增“頭”和“值”。 |
| 新增響應頭過濾器(輸入:頭和值) | 在上游(即客戶端)轉發請求之前新增“頭”和“值”。 |
| 重定向過濾器(輸入:狀態和 URL) | 在傳遞到下游主機之前,新增包含 URL 的重定向頭。 |
| ReWritePath(輸入:正則表示式和替換) | 負責透過將匹配的“正則表示式”字串替換為輸入替換來重寫路徑。 |
過濾器和斷言的詳盡列表位於 https://cloud.spring.io/spring-cloudgateway/reference/html/#the-rewritepath-gatewayfilter-factory
監控
為了監控閘道器或訪問各種路由、斷言等,我們可以在專案中啟用執行器。為此,讓我們首先更新 pom.xml 以包含執行器作為依賴項。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
為了監控,我們將使用一個單獨的應用程式屬性檔案,其中包含啟用執行器的標誌。因此,它看起來像這樣:
spring:
application:
name: restaurant-gateway-service
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: customers
uri: lb://customer-service
predicates:
- Path=/customer/**
- id: restaurants
uri: lb://restaurant-service
predicates:
- Path=/restaurant/**
server:
port: ${app_port}
eureka:
client:
serviceURL:
defaultZone: https://:8900/eureka
management:
endpoint:
gateway:
enabled: true
endpoints:
web:
exposure:
include: gateway
現在,要列出所有路由,我們可以訪問:https://:8084/actuator/gateway/routes
[
{
"predicate": "Paths: [/customer/**], match trailing slash: true",
"route_id": "customers",
"filters": [],
"uri": "lb://customer-service",
"order": 0
},
{
"predicate": "Paths: [/restaurant/**], match trailing slash: true",
"route_id": "restaurants",
"filters": [],
"uri": "lb://restaurant-service",
"order": 0
}
]
其他重要的監控 API:
| API | 描述 |
|---|---|
| GET /actuator/gateway/routes/{id} | 獲取有關特定路由的資訊 |
| POST /gateway/routes/{id_to_be assigned} | 向閘道器新增新路由 |
| DELETE /gateway/routes/{id} | 從閘道器中刪除路由 |
| POST /gateway/refresh | 刪除所有快取條目 |