1. 什么是網關?網關有什么用?
????????在微服務架構中,網關就是一個提供統一訪問地址的組件,它解決了內部微服務與外部的交互問題。網關主要負責流量的路由和轉發,將外部請求引到對應的微服務實例上。同時提供身份認證、授權、限流、監控以及日志記錄等功能。
????????從上圖就能看出網關的作用了,它就是充當客戶端與內部微服務之間的橋梁的。前端雖然可以發送ajax,但是它沒有健康檢測、沒有負載均衡,所以需要使用網關來充當一個統一的入口。當前端的請求來到了網關,網關再去分發,因為網關是用 Java 代碼來寫的,所以可以在網關這里引入Nacos進行健康檢測,引入LoadBalancer進行負載均衡。而且它還有超時重試等高級功能。
🍁網關的主要作用
- 提供統一的訪問入口點:網關作為唯一的網絡流量入口和出口,簡化了客戶端的訪問。
- 安全控制:網關能夠提供安全檢查,例如統一登錄和授權。
- 協議轉換:網關可以在不同網絡協議之間轉換數據,例如處理HTTPS和HTTP之間的轉換。
- 網絡地址的轉換:它允許局域網內的多個設備共享一個公共IP地址與外部網絡通信,這樣做可以提高安全性,節省IP地址,并使內部網絡結構對外部不可見。
- 數據的過濾和處理:網關可以對流經的數據進行過濾和必要的處理。
2. Spring Cloud Gateway 的基礎使用
2.1 Spring Cloud Gateway 的組成
- 路由:定義訪問的目標地址。
- 斷言:定義一組規則,讓匹配到當前路由的請求去調用某個目標。
- 過濾器:對請求進行特殊處理。
2.2 Spring Cloud Gateway 最基礎的使用
準備工作:
- 創建SpringBoot多模塊項目
- 創建三個模塊:網關、訂單、用戶
假設訂單、用戶模塊在內網中,不能直接訪問,需要通過網關路由到對應的服務上面。
準備相關模塊中的 controller:
@RestController
@RequestMapping("/order")
public class OrderController {@RequestMapping("/getcount")public int getCount() {return new Random().nextInt(1000);}
}
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate ServletWebServerApplicationContext context; // 獲取動態端口@RequestMapping("/getname")public String getName() {return context.getWebServer().getPort() +"--UserService:name=java-"+new Random().nextInt(100);}
}
以上兩個某塊只需要添加 Spring Web 依賴即可。
使用網關又分為兩步:
- 添加依賴
- 配置規則
1. 添加依賴
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
將其添加到網關模塊中,不能添加到父模塊中,因為 Spring Cloud Gateway 底層是響應式的 Reactor Web。(會沖突)
2. 配置路由規則
spring:cloud:gateway:routes:- id: userserviceuri: http://localhost:9090 # 路由predicates: # 斷言- Path=/user/** // 滿足斷言,就會去走對應的路由- id: orderserviceuri: http://localhost:9091predicates:- Path=/order/**server:port: 10086
在實際業務中,路由 uri 這里肯定不能直接寫死,但是此處主要演示最基礎的使用。
????????完成以上兩步之后,運行訂單服務、用戶服務,網關,使用10086端口去訪問兩個內網中的服務,都能訪問的到,這樣就實現了統一入口!
2.3 單服務中的多路徑配置
????????在上述示例中,每個服務只有一個controller,所以在配置網關路由規則的時候,直接寫就行了,假如說,單個服務中有多個controller呢?路由規則該如何去寫?
在user-service模塊中創建日志controller:
@RestController
@RequestMapping("/userlog")
public class UserLogController {@RequestMapping("/getlog")public String getLog() {return "UserLogService:log=java-"+new Random().nextInt(1000);}
}
多路徑配置:
spring:cloud:gateway:routes:- id: userserviceuri: http://localhost:9090 # 路由predicates: # 斷言- Path=/user/**,/userlog/getlog # 單服務多路徑配置- id: orderserviceuri: http://localhost:9091predicates:- Path=/order/**server:port: 10086
????????如果需要在單服務中完成多路徑配置,那么這個時候只需要在Path后面寫多個匹配規則,用英文的逗號隔開即可。不能在predicates下面在搞一個Path,因為同一個predicates下面不能出現相同類型的斷言。
2.4 更多的斷言類型
1.根據時間匹配 (3種類型)
- After:請求在指定時間之后才匹配。
- Before:請求在指定時間之前才匹配。
- Between:請求在指定時間中間才匹配。
2. Cookie:配置請求中的 Cookie 值。
3. Header:配置請求中的 Header?值。
4. Host:配置請求頭中的 Host 值。
5. Method:匹配請求頭中?Method 的值。
6. Path:匹配請求路徑。
7. Query:匹配請求參數。
8. RemoteAddr:匹配請求的?IP 地址,支持 IPV4 和 IPV6.
9. Weight:根據權重來分發請求,權重根據 group 來計算。
10. XForwardedRemoteAddr:根據 X-Forwarded-For 匹配。
參考官方文檔:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories
【示例】演示 Header
spring:cloud:gateway:routes:- id: userserviceuri: http://localhost:9090 # 路由predicates: # 斷言- Path=/user/**,/userlog/getlog # 單服務多路徑配置- Header=X-Header-Flag, \d+ server:port: 10086
使用 postman 構造 header:
① 正常訪問
② 異常訪問
?
???????上述例子中,”X-Header-Flag“ 表示 Header 中的 key,”\d+“ 是一個正則表達式,表示 key 的值,此處表示匹配 1 個或多個數字,才能訪問的到。
其他正則表達式:
- \w+:匹配一個或多個字母、數字、下劃線字符。
- \s+:匹配一個或多個空白字符(空格、制表符、換行符)。
- .*:匹配任意字符0次或多次。
- .+:匹配除了換行符之外的任意字符一次或多次。
- [abc]:匹配字符集中的任意一個字符,例如 [abc] 可以匹配 a、b、或 c。
- [^abc]:匹配除了字符集中的任意字符之外的任意字符。
- ^:匹配字符串的開始位置。
- &:匹配字符串的結束位置。
- |:用于匹配多個模式中的任意一個。
- ():用于分組,,可以將一組字符作為一個整體進行匹配。