Spring Cloud Gateway:網關

簡介

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路由謂詞工廠採用兩個參數datetime1datetime2,它們是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 nameregexp(這是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具有兩個參數,標頭nameregexp(這是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.orgbeta.somehost.orgwww.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

 

如果請求方法是GETPOST,則此路由將匹配。

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.正則表達式匹配,則此路由將匹配,因此barbaz將匹配。

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接受兩個參數groupweight(一個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 結果

[Integer.MIN_VALUE,0]

(invalid, IllegalArgumentException during initialization)

1

0.0.0.3

2

0.0.0.2

3

0.0.0.1

[4, Integer.MAX_VALUE]

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 官方文檔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章