簡介
Spring Cloud Gateway 項目提供了一個基於Spring生態系統的API網關,其中包括:Spring 5,Spring Boot 2和項目Reactor。Spring Cloud Gateway的目的是提供一種簡單而有效的方法來路由到API,並向它們提供跨領域的關注。
工作原理
客戶端向Spring Cloud網關發出請求。如果網關處理程序映射確定請求與路由匹配,則將其發送到網關Web處理程序。該處理程序運行通過特定於請求的篩選器鏈發送請求。篩選器由虛線分隔的原因是,篩選器可以在發送代理請求之前或之後執行邏輯。執行所有“前置”過濾器邏輯,然後發出代理請求。發出代理請求後,將執行“後”過濾器邏輯。
配置路由謂詞工廠和網關過濾工廠
有兩種配置謂詞和過濾器的方法:快捷方式 和 完全擴展的參數。下面的大多數示例都使用快捷方式。
名稱和自變量名稱將在第一部分或每部分的兩個部分中以code
的形式列出。參數通常按快捷方式配置所需的順序列出。
1. 快捷方式配置
快捷方式配置由過濾器名稱識別,後跟等號(=),後跟由逗號分隔的參數值(,)。
application.yml
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- Cookie=mycookie,mycookievalue
先前的示例使用兩個參數定義了Cookie
Route Predicate Factory,即cookie名稱mycookie
和與mycookievalue
相匹配的值。
2. 路由謂詞工廠
Spring Cloud網關將路由匹配爲Spring WebFlux HandlerMapping
基礎結構的一部分。Spring Cloud網關包括許多內置的Route Predicate工廠。所有這些謂詞都與HTTP請求的不同屬性匹配。多個路由謂詞工廠可以合併,也可以通過邏輯and
合併。
3. 路由謂詞工廠之後
After
路由謂詞工廠採用一個參數,即datetime
(這是Java ZonedDateTime
)。該謂詞匹配在當前日期時間之後發生的請求。
application.yml。
spring: cloud: gateway: routes: - id: after_route uri: https://example.org predicates: - After=2017-01-20T17:42:47.789-07:00[America/Denver]
該路線與2017年1月20日17:42山區時間(丹佛)之後的所有請求匹配。
4. 路線謂詞工廠之前
Before
路由謂詞工廠採用一個參數datetime(它是Java ZonedDateTime
)。該謂詞匹配當前日期時間之前發生的請求。
application.yml。
spring: cloud: gateway: routes: - id: before_route uri: https://example.org predicates: - Before=2017-01-20T17:42:47.789-07:00[America/Denver]
該路線與2017年1月20日17:42山區時間(丹佛)之前的所有請求匹配。
5. 路由謂詞工廠之間
Between
路由謂詞工廠採用兩個參數datetime1
和datetime2
,它們是Java ZonedDateTime
對象。該謂詞匹配在datetime1之後和datetime2之前發生的請求。datetime2參數必須在datetime1之後。
application.yml。
spring: cloud: gateway: routes: - id: between_route uri: https://example.org predicates: - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
該路線與2017年1月20日山區時間(丹佛)之後和2017年1月21日17:42山區時間(丹佛)之後的所有請求匹配。這對於維護時段可能很有用。
6. Cookie路線謂詞工廠
Cookie
Route Predicate Factory採用兩個參數,即cookie name
和regexp
(這是Java正則表達式)。該謂詞匹配具有給定名稱的cookie,並且值匹配正則表達式。
application.yml。
spring: cloud: gateway: routes: - id: cookie_route uri: https://example.org predicates: - Cookie=chocolate, ch.p
此路由與請求匹配,具有一個名爲chocolate
的cookie,該cookie的值與ch.p
正則表達式匹配。
7. 標頭路由謂詞工廠
Header
Route Predicate Factory具有兩個參數,標頭name
和regexp
(這是Java正則表達式)。該謂詞與具有給定名稱的標頭匹配,並且值與正則表達式匹配。
application.yml。
spring: cloud: gateway: routes: - id: header_route uri: https://example.org predicates: - Header=X-Request-Id, \d+
如果請求具有名爲X-Request-Id
的標頭,且其值與\d+
正則表達式匹配(具有一個或多個數字的值),則此路由匹配。
8. 主機路由謂詞工廠
Host
Route Predicate Factory採用一個參數:主機名patterns
的列表。模式是Ant樣式的模式,以.
作爲分隔符。該謂詞與匹配模式的Host
頭匹配。
application.yml。
spring: cloud: gateway: routes: - id: host_route uri: https://example.org predicates: - Host=**.somehost.org,**.anotherhost.org
還支持URI模板變量,例如{sub}.myhost.org
。
如果請求的Host
標頭的值爲www.somehost.org
或beta.somehost.org
或www.anotherhost.org
,則此路由將匹配。
該謂詞提取URI模板變量(如上例中定義的sub
)作爲名稱和值的映射,並使用在ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE
中定義的鍵將其放置在ServerWebExchange.getAttributes()
中。這些值可供GatewayFilter工廠使用。
9. 方法路線謂詞工廠
Method
路由謂詞工廠採用一個methods
參數,該參數是一個或多個要匹配的HTTP方法。
application.yml。
spring: cloud: gateway: routes: - id: method_route uri: https://example.org predicates: - Method=GET,POST
如果請求方法是GET
或POST
,則此路由將匹配。
10. 路徑路線謂詞工廠
Path
路由謂詞工廠採用兩個參數:Spring PathMatcher
patterns
的列表和matchOptionalTrailingSeparator
的可選標誌。
application.yml。
spring: cloud: gateway: routes: - id: host_route uri: https://example.org predicates: - Path=/foo/{segment},/bar/{segment}
如果請求路徑爲例如/foo/1
或/foo/bar
或/bar/baz
,則此路由將匹配。
該謂詞提取URI模板變量(如以上示例中定義的segment
)作爲名稱和值的映射,並使用在ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE
中定義的鍵將其放置在ServerWebExchange.getAttributes()
中。這些值可供GatewayFilter工廠使用。
可以使用實用程序方法來簡化對這些變量的訪問。
Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange); String segment = uriVariables.get("segment");
11. 查詢路由謂詞工廠
Query
Route Predicate Factory採用兩個參數:必需的param
和可選的regexp
(這是Java正則表達式)。
application.yml。
spring: cloud: gateway: routes: - id: query_route uri: https://example.org predicates: - Query=baz
如果請求包含baz
查詢參數,則此路由將匹配。
application.yml。
spring: cloud: gateway: routes: - id: query_route uri: https://example.org predicates: - Query=foo, ba.
如果請求包含一個foo
查詢參數,其值與ba.
正則表達式匹配,則此路由將匹配,因此bar
和baz
將匹配。
12. RemoteAddr路由謂詞工廠
RemoteAddr
路由謂詞工廠採用sources
的列表(最小大小1),它是CIDR表示法(IPv4或IPv6)字符串,例如192.168.0.1/16
(其中192.168.0.1
是IP地址, 16
是子網掩碼)。
application.yml。
spring: cloud: gateway: routes: - id: remoteaddr_route uri: https://example.org predicates: - RemoteAddr=192.168.1.1/24
如果請求的遠程地址爲192.168.1.10
,則此路由將匹配。
13. 重量路線謂詞工廠
Weight
Route Predicate Factory接受兩個參數group
和weight
(一個int)。權重是按組計算的。
application.yml。
spring: cloud: gateway: routes: - id: weight_high uri: https://weighthigh.org predicates: - Weight=group1, 8 - id: weight_low uri: https://weightlow.org predicates: - Weight=group1, 2
此路由會將約80%的流量轉發到https://weighthigh.org,並將約20%的流量轉發到https://weighlow.org
14. 修改解析遠程地址的方式
默認情況下,RemoteAddr路由謂詞工廠使用傳入請求中的遠程地址。如果Spring Cloud網關位於代理層後面,則此地址可能與實際的客戶端IP地址不匹配。
您可以通過設置自定義RemoteAddressResolver
來自定義解析遠程地址的方式。Spring Cloud網關帶有一個基於X-Forwarded-For標頭 XForwardedRemoteAddressResolver
的非默認遠程地址解析器。
XForwardedRemoteAddressResolver
有兩個靜態構造方法,它們採用不同的安全性方法:
XForwardedRemoteAddressResolver::trustAll
返回一個RemoteAddressResolver
,該地址始終使用在X-Forwarded-For
標頭中找到的第一個IP地址。這種方法容易受到欺騙,因爲惡意客戶端可能會爲X-Forwarded-For
設置一個初始值,該初始值將被解析程序接受。
XForwardedRemoteAddressResolver::maxTrustedIndex
獲取一個索引,該索引與在Spring Cloud網關前面運行的受信任基礎結構的數量相關。例如,如果Spring Cloud網關只能通過HAProxy訪問,則應使用值1。如果在訪問Spring Cloud網關之前需要兩跳可信基礎結構,則應使用值2。
給定以下標頭值:
X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3
下面的maxTrustedIndex
值將產生以下遠程地址。
maxTrustedIndex |
結果 |
---|---|
[ |
(invalid, |
1 |
0.0.0.3 |
2 |
0.0.0.2 |
3 |
0.0.0.1 |
[4, |
0.0.0.1 |
使用Java配置:
GatewayConfig.java
RemoteAddressResolver resolver = XForwardedRemoteAddressResolver .maxTrustedIndex(1); ... .route("direct-route", r -> r.remoteAddr("10.1.1.1", "10.10.1.1/24") .uri("https://downstream1") .route("proxied-route", r -> r.remoteAddr(resolver, "10.10.1.1", "10.10.1.1/24") .uri("https://downstream2") )
參考文獻:Spring Cloud 官方文檔