spring-cloud-gateway靜態路由
- 2020 年 4 月 4 日
- 筆記
為什麼引入 API 網關
使用 API 網關後的優點如下:
- 易於監控。可以在網關收集監控數據並將其推送到外部系統進行分析。
- 易於認證。可以在網關上進行認證,然後再將請求轉發到後端的微服務,而無須在每個微服務中進行認證。
- 減少了客戶端與各個微服務之間的交互次數。
基本環境見 spring-cloud-gateway 簡介, 項目中 provider1 的 maven 配置在此做下更正
pom.xml
<?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>spring-cloud-learning</artifactId> <groupId>cn.idea360</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>idc-provider1</artifactId> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> </dependencies> <build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> </plugin> </plugins> </build> </project>
靜態路由基本實現
靜態路由比較簡單,這裡做簡單實現。
更改路由模組 application.yml 配置,更改後的配置文件如下:
server: port: 2000 spring: application: name: idc-gateway redis: host: localhost port: 6379 timeout: 6000ms # 連接超時時長(毫秒) jedis: pool: max-active: 1000 # 連接池最大連接數(使用負值表示沒有限制) max-wait: -1ms # 連接池最大阻塞等待時間(使用負值表示沒有限制) max-idle: 10 # 連接池中的最大空閑連接 min-idle: 5 # 連接池中的最小空閑連接 cloud: consul: host: localhost port: 8500 gateway: discovery: locator: enabled: true # gateway可以通過開啟以下配置來打開根據服務的serviceId來匹配路由,默認是大寫 routes: - id: provider1 # 路由 ID,保持唯一 uri: lb://idc-provider1 # uri指目標服務地址,lb代表從註冊中心獲取服務 predicates: # 路由條件。Predicate 接受一個輸入參數,返回一個布爾值結果。該介面包含多種默認方法來將 Predicate 組合成其他複雜的邏輯(比如:與,或,非) - Path=/p/** filters: - StripPrefix=1 # 過濾器StripPrefix,作用是去掉請求路徑的最前面n個部分截取掉。StripPrefix=1就代表截取路徑的個數為1,比如前端過來請求/test/good/1/view,匹配成功後,路由到後端的請求路徑就會變成http://localhost:8888/good/1/view - id: provider2 # 路由 ID,保持唯一 uri: lb://idc-provider2 # uri指目標服務地址,lb代表從註冊中心獲取服務 predicates: # 路由條件。Predicate 接受一個輸入參數,返回一個布爾值結果。該介面包含多種默認方法來將 Predicate 組合成其他複雜的邏輯(比如:與,或,非) - Path=/p2/** filters: - StripPrefix=1 # 過濾器StripPrefix,作用是去掉請求路徑的最前面n個部分截取掉。StripPrefix=1就代表截取路徑的個數為1,比如前端過來請求/test/good/1/view,匹配成功後,路由到後端的請求路徑就會變成http://localhost:8888/good/1/view
測試
執行以下請求測試路由 1
curl http://localhost:2000/p/provider1/1
結果 返回 2001
。說明成功路由到了 provider1 服務。
執行以下請求測試路由 2
curl http://localhost:2000/p2/provider2
返回 {"port":"2002"}
。說明成功路由到了 provider2 服務。
Predicate 斷言條件
1 通過請求參數匹配
Query Route Predicate 支援傳入兩個參數,一個是屬性名一個為屬性值,屬性值可以是正則表達式。
... - id: provider1 uri: lb://idc-provider1 predicates: - Path=/p/** - Query=username filters: - StripPrefix=1
這樣配置,只要請求中包含 username 屬性的參數即可匹配路由。否則 404
測試
curl http://localhost:2000/p/provider1/1?username=admin
經過測試發現只要請求匯總帶有 username
參數即會匹配路由,不帶 username
參數則不會匹配。
還可以將 Query 的值以鍵值對的方式進行配置,這樣在請求過來時會對屬性值和正則進行匹配,匹配上才會走路由。
- id: provider1 uri: lb://idc-provider1 predicates: - Path=/p/** - Query=username, ad. filters: - StripPrefix=1
這樣只要當請求中包含 username
屬性並且參數值是以 admin 開頭的長度為三位的字元串才會進行匹配和路由。
測試
curl http://localhost:2000/p/provider1/1?username=adm
測試可以返回頁面程式碼,將 username
的屬性值改為 admin
再次訪問就會報 404
,證明路由需要匹配正則表達式才會進行路由。
2 通過 Header 屬性匹配
Header Route Predicate 和 Cookie Route Predicate 一樣,也是接收 2 個參數,一個 header 中屬性名稱和一個正則表達式,這個屬性值和正則表達式匹配則執行。
- id: provider1 uri: lb://idc-provider1 predicates: - Path=/p/** - Header=token, d+ filters: - StripPrefix=1
測試
curl http://localhost:2000/p/provider1/1 -H "token:11"
則返回頁面程式碼證明匹配成功。將參數-H "token:11"改為-H "token:spring"再次執行時返回 404 證明沒有匹配。
3 通過 Cookie 匹配
Cookie Route Predicate 可以接收兩個參數,一個是 Cookie name ,一個是正則表達式,路由規則會通過獲取對應的 Cookie name 值和正則表達式去匹配,如果匹配上就會執行路由,如果沒有匹配上則不執行。
- id: provider1 uri: lb://idc-provider1 predicates: - Path=/p/** - Cookie=sessionId, test filters: - StripPrefix=1
使用 curl 測試,命令行輸入:
curl http://localhost:2000/p/provider1/1 --cookie "sessionId=test"
則會返回頁面程式碼,如果去掉–cookie "sessionId=test",後台會報 404 錯誤。
4 通過 Host 匹配
Host Route Predicate 接收一組參數,一組匹配的域名列表,這個模板是一個 ant 分隔的模板,用.號作為分隔符。它通過參數中的主機地址作為匹配規則。
- id: provider1 uri: lb://idc-provider1 predicates: - Path=/p/** - Host=**.baidu.com filters: - StripPrefix=1
使用 curl 測試,命令行輸入:
curl http://localhost:2000/p/provider1/1 -H "Host: www.baidu.com" curl http://localhost:2000/p/provider1/1 -H "Host: md.baidu.com"
經測試以上兩種 host 均可匹配到 host_route 路由,去掉 host 參數則會報 404 錯誤。
5 通過請求方式匹配
可以通過是 POST、GET、PUT、DELETE 等不同的請求方式來進行路由。
- id: provider1 uri: lb://idc-provider1 predicates: - Path=/p/** - Method=GET filters: - StripPrefix=1
使用 curl 測試,命令行輸入:
curl http://localhost:2000/p/provider1/1
測試返回頁面程式碼,證明匹配到路由,我們再以 POST
的方式請求測試。
curl -X POST http://localhost:2000/p/provider1/1
返回 404 沒有找到,證明沒有匹配上路由
6 通過請求路徑匹配
Path Route Predicate 接收一個匹配路徑的參數來判斷是否走路由。
- id: provider1 uri: lb://idc-provider1 predicates: - Path=/p/{segment} - Method=POST filters: - StripPrefix=1
如果請求路徑符合要求,則此路由將匹配,例如:/foo/1 或者 /foo/bar。
7 通過請求 ip 地址進行匹配
Predicate 也支援通過設置某個 ip 區間號段的請求才會路由,RemoteAddr Route Predicate 接受 cidr 符號(IPv4 或 IPv6 )字元串的列表(最小大小為 1),例如 192.168.124.5/16 (其中 192.168.124.5 是 IP 地址,16 是子網掩碼)。
- id: provider1 uri: lb://idc-provider1 predicates: - Path=/p/** - RemoteAddr=192.168.124.5/16 filters: - StripPrefix=1
可以將此地址設置為本機的 ip 地址進行測試。
curl http://192.168.124.5:2000/p/provider1/1
如果請求的遠程地址是 192.168.124.5,則此路由將匹配。
8 組合使用
各種 Predicates 同時存在於同一個路由時,請求必須同時滿足所有的條件才被這個路由匹配。
一個請求滿足多個路由的斷言條件時,請求只會被首個成功匹配的路由轉發
結語
本篇到此結束,歡迎大家關注公眾號【當我遇上你】。