? ? Spring Cloud網關
Greenwich SR5
該項目提供了一個基于Spring生態系統的API網關,其中包括:Spring 5,Spring Boot 2和項目Reactor。Spring Cloud網關的目的是提供一種簡單而有效的方法來路由到API,并向它們提供跨領域的關注,例如:安全性,監視/度量和彈性。
? ? 如何包括Spring Cloud網關
要將Spring Cloud網關包含在項目中,請將該啟動器與組org.springframework.cloud
和工件ID?spring-cloud-starter-gateway
一起使用。有關?使用當前Spring Cloud版本Train設置構建系統的詳細信息,請參見Spring Cloud項目頁面。
如果包括啟動器,但由于某種原因,您不希望啟用網關,請設置spring.cloud.gateway.enabled=false
。
| 重要 |
---|---|
Spring Cloud網關基于Spring Boot 2.x,?Spring WebFlux和項目Reactor?構建。因此,使用Spring Cloud網關時,許多熟悉的同步庫(例如,Spring Data和Spring Security)和模式可能不適用。如果您不熟悉這些項目,建議您在使用Spring Cloud Gateway之前,先閱讀它們的文檔以熟悉一些新概念。 |
| 重要 |
---|---|
Spring Cloud網關需要Spring Boot和Spring Webflux提供的Netty運行時。它不能在傳統的Servlet容器中或作為WAR構建。 |
111.詞匯表
- 路由:路由網關的基本構建塊。它由ID,目標URI,謂詞集合和過濾器集合定義。如果聚合謂詞為true,則匹配路由。
- 謂詞:這是?Java 8 Function謂詞。輸入類型為?Spring Framework?ServerWebExchange。這使開發人員可以匹配HTTP請求中的任何內容,例如標頭或參數。
- 過濾器:這些是使用特定工廠構造的實例?Spring Framework?GatewayFilter。在此,可以在發送下游請求之前或之后修改請求和響應。
112.工作原理
客戶端向Spring Cloud網關發出請求。如果網關處理程序映射確定請求與路由匹配,則將其發送到網關Web處理程序。該處理程序運行通過特定于請求的篩選器鏈發送請求。篩選器由虛線分隔的原因是,篩選器可以在發送代理請求之前或之后執行邏輯。執行所有“前置”過濾器邏輯,然后發出代理請求。發出代理請求后,將執行“后”過濾器邏輯。
|
在沒有端口的路由中定義的URI將分別將HTTP和HTTPS URI的默認端口分別設置為80和443。 |
113.配置路由謂詞工廠和網關過濾工廠
有兩種配置謂詞和過濾器的方法:快捷方式和完全擴展的參數。下面的大多數示例都使用快捷方式。
名稱和自變量名稱將在第一部分或每部分的兩個部分中以code
的形式列出。參數通常按快捷方式配置所需的順序列出。
113.1快捷方式配置
快捷方式配置由過濾器名稱識別,后跟等號(=
),后跟由逗號分隔的參數值(,
)。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: after_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Cookie</span>=mycookie,mycookievalue</span></span></span>
先前的示例使用兩個參數定義了Cookie
?Route Predicate Factory,即cookie名稱mycookie
和與mycookievalue
相匹配的值。
113.2完全展開的參數
完全擴展的參數看起來更像帶有名稱/值對的標準Yaml配置。通常,將有一個name
鍵和一個args
鍵。args
鍵是用于配置謂詞或過濾器的鍵值對的映射。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: after_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - name</span>: Cookie
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> name</span>: mycookie
<span style="color:#7f007f"> regexp</span>: mycookievalue</span></span></span>
這是上面顯示的Cookie
謂詞的快捷方式配置的完整配置。
114.路由謂詞工廠
Spring Cloud網關將路由匹配為Spring WebFlux?HandlerMapping
基礎結構的一部分。Spring Cloud網關包括許多內置的Route Predicate工廠。所有這些謂詞都與HTTP請求的不同屬性匹配。多個路由謂詞工廠可以合并,也可以通過邏輯and
合并。
114.1路由謂詞工廠之后
After
路由謂詞工廠采用一個參數,即datetime
(這是Java?ZonedDateTime
)。該謂詞匹配在當前日期時間之后發生的請求。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: after_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - After</span>=2017-01-20T17:42:47.789-07:00[America/Denver<span style="color:#7f0055"><strong>]</strong></span></span></span></span>
該路線與2017年1月20日17:42山區時間(丹佛)之后的所有請求匹配。
114.2路線謂詞工廠之前
Before
路由謂詞工廠采用一個參數datetime(它是Java?ZonedDateTime
)。該謂詞匹配當前日期時間之前發生的請求。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: before_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Before</span>=2017-01-20T17:42:47.789-07:00[America/Denver<span style="color:#7f0055"><strong>]</strong></span></span></span></span>
該路線與2017年1月20日17:42山區時間(丹佛)之前的所有請求匹配。
114.3路由謂詞工廠之間
Between
路由謂詞工廠采用兩個參數datetime1
和datetime2
,它們是Java?ZonedDateTime
對象。該謂詞匹配在datetime1之后和datetime2之前發生的請求。datetime2參數必須在datetime1之后。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: between_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Between</span>=2017-01-20T17:42:47.789-07:00[America/Denver]<span style="color:#7f0055"><strong>,</strong></span> 2017-01-21T17:42:47.789-07:00[America/Denver<span style="color:#7f0055"><strong>]</strong></span></span></span></span>
該路線與2017年1月20日山區時間(丹佛)之后和2017年1月21日17:42山區時間(丹佛)之后的所有請求匹配。這對于維護時段可能很有用。
114.4 Cookie路線謂詞工廠
Cookie
?Route Predicate Factory采用兩個參數,即cookie?name
和regexp
(這是Java正則表達式)。該謂詞匹配具有給定名稱的cookie,并且值匹配正則表達式。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: cookie_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Cookie</span>=chocolate<span style="color:#7f0055"><strong>,</strong></span> ch.p</span></span></span>
此路由與請求匹配,具有一個名為chocolate
的cookie,該cookie的值與ch.p
正則表達式匹配。
114.5標頭路由謂詞工廠
Header
?Route Predicate Factory具有兩個參數,標頭name
和regexp
(這是Java正則表達式)。該謂詞與具有給定名稱的標頭匹配,并且值與正則表達式匹配。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: header_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Header</span>=X-Request-Id<span style="color:#7f0055"><strong>,</strong></span> \d+</span></span></span>
如果請求具有名為X-Request-Id
的標頭,且其值與\d+
正則表達式匹配(具有一個或多個數字的值),則此路由匹配。
114.6主機路由謂詞工廠
Host
?Route Predicate Factory采用一個參數:主機名patterns
的列表。模式是Ant樣式的模式,以.
作為分隔符。該謂詞與匹配模式的Host
頭匹配。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: host_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Host</span>=**.somehost.org,**.anotherhost.org</span></span></span>
還支持URI模板變量,例如{sub}.myhost.org
。
如果請求的Host
標頭的值為www.somehost.org
或beta.somehost.org
或www.anotherhost.org
,則此路由將匹配。
該謂詞提取URI模板變量(如上例中定義的sub
)作為名稱和值的映射,并使用在ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE
中定義的鍵將其放置在ServerWebExchange.getAttributes()
中。這些值可供GatewayFilter工廠使用。
114.7方法路線謂詞工廠
Method
路由謂詞工廠采用一個methods
參數,該參數是一個或多個要匹配的HTTP方法。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: method_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Method</span>=GET,POST</span></span></span>
如果請求方法是GET
或POST
,則此路由將匹配。
114.8路徑路線謂詞工廠
Path
路由謂詞工廠采用兩個參數:Spring?PathMatcher
?patterns
的列表和matchOptionalTrailingSeparator
的可選標志。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: host_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/foo/{segment},/bar/{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>
如果請求路徑為例如/foo/1
或/foo/bar
或/bar/baz
,則此路由將匹配。
該謂詞提取URI模板變量(如以上示例中定義的segment
)作為名稱和值的映射,并使用在ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE
中定義的鍵將其放置在ServerWebExchange.getAttributes()
中。這些值可供GatewayFilter工廠使用。
可以使用實用程序方法來簡化對這些變量的訪問。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);String segment = uriVariables.get(<span style="color:#2a00ff">"segment"</span>);</span></span></span>
114.9查詢路由謂詞工廠
Query
?Route Predicate Factory采用兩個參數:必需的param
和可選的regexp
(這是Java正則表達式)。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: query_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Query</span>=baz</span></span></span>
如果請求包含baz
查詢參數,則此路由將匹配。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: query_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Query</span>=foo<span style="color:#7f0055"><strong>,</strong></span> ba.</span></span></span>
如果請求包含一個foo
查詢參數,其值與ba.
正則表達式匹配,則此路由將匹配,因此bar
和baz
將匹配。
114.10 RemoteAddr路由謂詞工廠
RemoteAddr
路由謂詞工廠采用sources
的列表(最小大小1),它是CIDR表示法(IPv4或IPv6)字符串,例如192.168.0.1/16
(其中192.168.0.1
是IP地址,?16
是子網掩碼)。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: remoteaddr_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - RemoteAddr</span>=192.168.1.1/24</span></span></span>
如果請求的遠程地址為192.168.1.10
,則此路由將匹配。
114.11重量路線謂詞工廠
Weight
?Route Predicate Factory接受兩個參數group
和weight
(一個int)。權重是按組計算的。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: weight_high
<span style="color:#7f007f"> uri</span>: https://weighthigh.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Weight</span>=group1<span style="color:#7f0055"><strong>,</strong></span> 8
<span style="color:#7f007f"> - id</span>: weight_low
<span style="color:#7f007f"> uri</span>: https://weightlow.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Weight</span>=group1<span style="color:#7f0055"><strong>,</strong></span> 2</span></span></span>
此路由會將約80%的流量轉發到https://weighthigh.org,并將約20%的流量轉發到https://weighlow.org
114.11.1修改解析遠程地址的方式
默認情況下,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。
給定以下標頭值:
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3</span></span></span>
下面的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
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">RemoteAddressResolver resolver = XForwardedRemoteAddressResolver.maxTrustedIndex(1);....route(<span style="color:#2a00ff">"direct-route"</span>,r -> r.remoteAddr(<span style="color:#2a00ff">"10.1.1.1"</span>, <span style="color:#2a00ff">"10.10.1.1/24"</span>).uri(<span style="color:#2a00ff">"https://downstream1"</span>)
.route(<span style="color:#2a00ff">"proxied-route"</span>,r -> r.remoteAddr(resolver, <span style="color:#2a00ff">"10.10.1.1"</span>, <span style="color:#2a00ff">"10.10.1.1/24"</span>).uri(<span style="color:#2a00ff">"https://downstream2"</span>)
)</span></span></span>
115.網關過濾器工廠
路由過濾器允許以某種方式修改傳入的HTTP請求或傳出的HTTP響應。路由過濾器適用于特定路由。Spring Cloud網關包括許多內置的GatewayFilter工廠。
注意有關如何使用以下任何過濾器的更多詳細示例,請查看單元測試。
115.1 AddRequestHeader GatewayFilter工廠
AddRequestHeader
?GatewayFilter工廠采用name
和value
參數。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: add_request_header_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - AddRequestHeader</span>=X-Request-Foo<span style="color:#7f0055"><strong>,</strong></span> Bar</span></span></span>
這會將X-Request-Foo:Bar
標頭添加到所有匹配請求的下游請求標頭中。
AddRequestHeader知道用于匹配路徑或主機的URI變量。URI變量可用于該值,并將在運行時擴展。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: add_request_header_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/foo/{segment<span style="color:#7f0055"><strong>}</strong></span>
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - AddRequestHeader</span>=X-Request-Foo<span style="color:#7f0055"><strong>,</strong></span> Bar-{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>
115.2 AddRequestParameter GatewayFilter工廠
AddRequestParameter
?GatewayFilter工廠采用name
和value
參數。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: add_request_parameter_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - AddRequestParameter</span>=foo<span style="color:#7f0055"><strong>,</strong></span> bar</span></span></span>
這會將foo=bar
添加到所有匹配請求的下游請求的查詢字符串中。
AddRequestParameter知道用于匹配路徑或主機的URI變量。URI變量可用于該值,并將在運行時擴展。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: add_request_parameter_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Host</span>: {segment}.myhost.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - AddRequestParameter</span>=foo<span style="color:#7f0055"><strong>,</strong></span> bar-{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>
115.3 AddResponseHeader GatewayFilter工廠
AddResponseHeader
?GatewayFilter工廠采用name
和value
參數。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: add_response_header_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - AddResponseHeader</span>=X-Response-Foo<span style="color:#7f0055"><strong>,</strong></span> Bar</span></span></span>
這會將X-Response-Foo:Bar
標頭添加到所有匹配請求的下游響應的標頭中。
AddResponseHeader知道用于匹配路徑或主機的URI變量。URI變量可用于該值,并將在運行時擴展。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: add_response_header_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Host</span>: {segment}.myhost.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - AddResponseHeader</span>=foo<span style="color:#7f0055"><strong>,</strong></span> bar-{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>
115.4 DedupeResponseHeader GatewayFilter工廠
DedupeResponseHeader
?GatewayFilter工廠采用name
參數和可選的strategy
參數。name
可以包含標題名稱列表,以空格分隔。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: dedupe_response_header_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - DedupeResponseHeader</span>=Access-Control-Allow-Credentials Access-Control-Allow-Origin</span></span></span>
在網關CORS邏輯和下游邏輯都將它們添加的情況下,這將刪除Access-Control-Allow-Credentials
和Access-Control-Allow-Origin
響應頭的重復值。
DedupeResponseHeader過濾器還接受可選的strategy
參數。可接受的值為RETAIN_FIRST
(默認值),RETAIN_LAST
和RETAIN_UNIQUE
。
115.5 Hystrix GatewayFilter工廠
Hystrix是Netflix的一個庫,它實現了斷路器模式。Hystrix
?GatewayFilter允許您將斷路器引入網關路由,保護服務免受級聯故障的影響,并允許您在下游故障的情況下提供后備響應。
要在您的項目中啟用Hystrix
?GatewayFilters,請添加對Spring Cloud Netflix中的?spring-cloud-starter-netflix-hystrix
的依賴。
Hystrix
?GatewayFilter工廠需要一個name
參數,它是HystrixCommand
的名稱。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: hystrix_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - Hystrix</span>=myCommandName</span></span></span>
這會將其余過濾器包裝在命令名稱為myCommandName
的HystrixCommand
中。
Hystrix過濾器還可以接受可選的fallbackUri
參數。當前,僅支持forward:
計劃的URI。如果調用了后備,則請求將被轉發到與URI相匹配的控制器。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: hystrix_route
<span style="color:#7f007f"> uri</span>: lb://backing-service:8088
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/consumingserviceendpoint
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: Hystrix
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> name</span>: fallbackcmd
<span style="color:#7f007f"> fallbackUri</span>: forward:/incaseoffailureusethis
<span style="color:#7f007f"> - RewritePath</span>=/consumingserviceendpoint<span style="color:#7f0055"><strong>,</strong></span> /backingserviceendpoint</span></span></span>
調用Hystrix后備廣告時,它將轉發到/incaseoffailureusethis
?URI。請注意,此示例還通過目標URI上的lb
前綴演示了(可選)Spring Cloud Netflix Ribbon負載均衡。
主要方案是將fallbackUri
用于網關應用程序中的內部控制器或處理程序。但是,也可以將請求重新路由到外部應用程序中的控制器或處理程序,如下所示:
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: ingredients
<span style="color:#7f007f"> uri</span>: lb://ingredients
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=//ingredients/**
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: Hystrix
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> name</span>: fetchIngredients
<span style="color:#7f007f"> fallbackUri</span>: forward:/fallback
<span style="color:#7f007f"> - id</span>: ingredients-fallback
<span style="color:#7f007f"> uri</span>: http://localhost:9994
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/fallback</span></span></span>
在此示例中,網關應用程序中沒有fallback
端點或處理程序,但是,另一個應用程序中沒有fallback
端點或處理程序,已在http://localhost:9994
下注冊。
如果將請求轉發到后備,則Hystrix網關過濾器還會提供引起請求的Throwable
。它作為ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR
屬性添加到ServerWebExchange
中,可以在網關應用程序中處理后備時使用。
對于外部控制器/處理程序方案,可以添加帶有異常詳細信息的標頭。您可以在FallbackHeaders GatewayFilter Factory部分中找到有關它的更多信息。
Hystrix設置(例如超時)可以使用全局默認值進行配置,也可以使用Hystrix Wiki中所述的應用程序屬性在逐條路由的基礎上進行配置。
要為上述示例路由設置5秒超時,將使用以下配置:
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds</span>: 5000</span></span></span>
115.6 FallbackHeaders GatewayFilter工廠
FallbackHeaders
工廠允許您在轉發到外部應用程序中的fallbackUri
的請求的標頭中添加Hystrix執行異常詳細信息,例如以下情況:
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: ingredients
<span style="color:#7f007f"> uri</span>: lb://ingredients
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=//ingredients/**
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: Hystrix
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> name</span>: fetchIngredients
<span style="color:#7f007f"> fallbackUri</span>: forward:/fallback
<span style="color:#7f007f"> - id</span>: ingredients-fallback
<span style="color:#7f007f"> uri</span>: http://localhost:9994
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/fallback
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: FallbackHeaders
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> executionExceptionTypeHeaderName</span>: Test-Header</span></span></span>
在此示例中,在運行HystrixCommand
時發生執行異常之后,該請求將轉發到fallback
端點或運行在localhost:9994
上的應用程序中的處理程序。具有異常類型,消息和-if available-根本原因異常類型和消息的標頭將由FallbackHeaders
過濾器添加到該請求。
通過設置下面列出的參數的值及其默認值,可以在配置中覆蓋標頭的名稱:
executionExceptionTypeHeaderName
?("Execution-Exception-Type"
)executionExceptionMessageHeaderName
?("Execution-Exception-Message"
)rootCauseExceptionTypeHeaderName
?("Root-Cause-Exception-Type"
)rootCauseExceptionMessageHeaderName
?("Root-Cause-Exception-Message"
)
您可以在Hystrix GatewayFilter工廠部分中找到有關Hystrix與Gateway一起工作的更多信息。
115.7 MapRequestHeader GatewayFilter工廠
MapRequestHeader
?GatewayFilter要素采用'fromHeader'和'toHeader'參數。它創建一個新的命名標頭(toHeader),并從傳入的HTTP請求中從現有的命名標頭(fromHeader)中提取值。如果輸入標頭不存在,則過濾器不起作用。如果新的命名標頭已經存在,則將使用新值擴充其值。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: map_request_header_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - MapRequestHeader</span>=Bar<span style="color:#7f0055"><strong>,</strong></span> X-Request-Foo</span></span></span>
這會將X-Request-Foo:<values>
標頭添加到下游請求中,并帶有來自傳入的HTTP請求Bar
標頭的更新值。
115.8 PrefixPath GatewayFilter工廠
PrefixPath
?GatewayFilter工廠采用單個prefix
參數。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: prefixpath_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - PrefixPath</span>=/mypath</span></span></span>
這會將/mypath
作為所有匹配請求的路徑的前綴。因此,對/hello
的請求將被發送到/mypath/hello
。
115.9 PreserveHostHeader GatewayFilter工廠
PreserveHostHeader
?GatewayFilter工廠沒有參數。該過濾器設置請求屬性,路由過濾器將檢查該請求屬性以確定是否應發送原始主機頭,而不是由HTTP客戶端確定的主機頭。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: preserve_host_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:- PreserveHostHeader</span></span></span>
115.10 RequestRateLimiter GatewayFilter工廠
RequestRateLimiter
?GatewayFilter工廠使用RateLimiter
實現來確定是否允許繼續當前請求。如果不是,則返回狀態HTTP 429 - Too Many Requests
(默認)。
該過濾器采用一個可選的keyResolver
參數和特定于速率限制器的參數(請參見下文)。
keyResolver
是實現KeyResolver
接口的bean。在配置中,使用SpEL通過名稱引用bean。#{@myKeyResolver}
是引用名稱為myKeyResolver
的bean的SpEL表達式。
KeyResolver.java。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>interface</strong></span> KeyResolver {Mono<String> resolve(ServerWebExchange exchange);
}</span></span></span>
KeyResolver
接口允許可插拔策略派生用于限制請求的密鑰。在未來的里程碑中,將有一些KeyResolver
實現。
KeyResolver
的默認實現是PrincipalNameKeyResolver
,它從ServerWebExchange
檢索Principal
并調用Principal.getName()
。
默認情況下,如果KeyResolver
未找到密鑰,則請求將被拒絕。可以使用spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key
(對或錯)和spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code
屬性來調整此行為。
|
無法通過“快捷方式”符號配置RequestRateLimiter。以下示例無效 |
application.properties。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"># INVALID SHORTCUT CONFIGURATION
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}</span></span></span>
115.10.1 Redis RateLimiter
redis實現基于Stripe所做的工作。它需要使用spring-boot-starter-data-redis-reactive
?Spring Boot起動器。
使用的算法是令牌桶算法。
redis-rate-limiter.replenishRate
是您希望用戶每秒允許多少個請求,而沒有任何丟棄的請求。這是令牌桶被填充的速率。
redis-rate-limiter.burstCapacity
是允許用戶在一秒鐘內執行的最大請求數。這是令牌桶可以容納的令牌數。將此值設置為零將阻止所有請求。
通過在replenishRate
和burstCapacity
中設置相同的值可以達到穩定的速率。通過將burstCapacity
設置為高于replenishRate
,可以允許臨時突發。在這種情況下,速率限制器需要在突發之間間隔一段時間(根據replenishRate
),因為2個連續的突發將導致請求丟失(HTTP 429 - Too Many Requests
)。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: requestratelimiter_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: RequestRateLimiter
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> redis-rate-limiter.replenishRate</span>: 10
<span style="color:#7f007f"> redis-rate-limiter.burstCapacity</span>: 20</span></span></span>
Config.java。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@Bean</span></em>
KeyResolver userKeyResolver() {<span style="color:#7f0055"><strong>return</strong></span> exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst(<span style="color:#2a00ff">"user"</span>));
}</span></span></span>
這定義了每個用戶10的請求速率限制。允許20個突發,但是下一秒只有10個請求可用。KeyResolver
是一個簡單的參數,它獲取user
請求參數(注意:不建議在生產中使用)。
速率限制器也可以定義為實現RateLimiter
接口的bean。在配置中,使用SpEL通過名稱引用bean。#{@myRateLimiter}
是一個SpEL表達式,引用名稱為myRateLimiter
的bean。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: requestratelimiter_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: RequestRateLimiter
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> rate-limiter</span>: <span style="color:#2a00ff">"#{@myRateLimiter}"</span>
<span style="color:#7f007f"> key-resolver</span>: <span style="color:#2a00ff">"#{@userKeyResolver}"</span></span></span></span>
115.11重定向到GatewayFilter工廠
RedirectTo
?GatewayFilter工廠采用一個status
和一個url
參數。狀態應該是300系列重定向http代碼,例如301。URL應該是有效的URL。這將是Location
標頭的值。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: prefixpath_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - RedirectTo</span>=302<span style="color:#7f0055"><strong>,</strong></span> https://acme.org</span></span></span>
這將發送帶有Location:https://acme.org
標頭的狀態302以執行重定向。
115.12 RemoveRequestHeader GatewayFilter工廠
RemoveRequestHeader
?GatewayFilter工廠采用一個name
參數。它是要刪除的標題的名稱。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: removerequestheader_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - RemoveRequestHeader</span>=X-Request-Foo</span></span></span>
這將刪除X-Request-Foo
標頭,然后將其發送到下游。
115.13 RemoveResponseHeader GatewayFilter工廠
RemoveResponseHeader
?GatewayFilter工廠采用一個name
參數。它是要刪除的標題的名稱。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: removeresponseheader_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - RemoveResponseHeader</span>=X-Response-Foo</span></span></span>
這會將X-Response-Foo
標頭從響應中刪除,然后將其返回到網關客戶端。
要刪除任何類型的敏感標頭,應為可能需要的任何路由配置此過濾器。此外,您可以使用spring.cloud.gateway.default-filters
一次配置此過濾器,并將其應用于所有路由。
115.14 RewritePath GatewayFilter工廠
RewritePath
?GatewayFilter工廠采用路徑regexp
參數和replacement
參數。這使用Java正則表達式提供了一種靈活的方式來重寫請求路徑。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: rewritepath_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/foo/**
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - RewritePath</span>=/foo(?<segment>/?.*)<span style="color:#7f0055"><strong>,</strong></span> $\{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>
對于/foo/bar
的請求路徑,這將在發出下游請求之前將路徑設置為/bar
。請注意,由于YAML規范,$\
被$
所取代。
115.15 RewriteLocationResponseHeader GatewayFilter工廠
RewriteLocationResponseHeader
?GatewayFilter工廠通常會修改Location
響應標頭的值,以擺脫后端特定的詳細信息。它需要stripVersionMode
,locationHeaderName
,hostValue
和protocolsRegex
參數。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: rewritelocationresponseheader_route
<span style="color:#7f007f"> uri</span>: http://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - RewriteLocationResponseHeader</span>=AS_IN_REQUEST<span style="color:#7f0055"><strong>,</strong></span> Location<span style="color:#7f0055"><strong>,</strong></span> <span style="color:#7f0055"><strong>,</strong></span></span></span></span>
例如,對于請求POST?https://api.example.com/some/object/name
,Location
響應標頭值https://object-service.prod.example.net/v2/some/object/id
將被重寫為https://api.example.com/some/object/id
。
參數stripVersionMode
具有以下可能的值:NEVER_STRIP
,AS_IN_REQUEST
(默認),ALWAYS_STRIP
。
NEVER_STRIP
-即使原始請求路徑不包含版本,也不會剝離版本AS_IN_REQUEST
-僅當原始請求路徑不包含版本時,版本才會被剝離ALWAYS_STRIP
-即使原始請求路徑包含版本,也會剝離版本
參數hostValue
(如果提供)將用于替換響應Location
標頭中的host:port
部分。如果未提供,將使用Host
請求標頭的值。
參數protocolsRegex
必須是有效的正則表達式String
,協議名稱將與之匹配。如果不匹配,過濾器將不執行任何操作。默認值為http|https|ftp|ftps
。
115.16 RewriteResponseHeader GatewayFilter工廠
RewriteResponseHeader
?GatewayFilter工廠采用name
,regexp
和replacement
參數。它使用Java正則表達式以靈活的方式重寫響應標頭值。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: rewriteresponseheader_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - RewriteResponseHeader</span>=X-Response-Foo<span style="color:#7f0055"><strong>,</strong></span> <span style="color:#7f0055"><strong>,</strong></span> password=[^&]+<span style="color:#7f0055"><strong>,</strong></span> password=***</span></span></span>
對于標頭值為/42?user=ford&password=omg!what&flag=true
,在發出下游請求后它將被設置為/42?user=ford&password=***&flag=true
。由于YAML規范,請使用$\
來表示$
。
115.17 SaveSession GatewayFilter工廠
在向下游轉發呼叫之前,SaveSession GatewayFilter工廠強制執行WebSession::save
操作。這在將Spring Session之類的內容用于惰性數據存儲并且需要確保在進行轉接呼叫之前已保存會話狀態時特別有用。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: save_session
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/foo/**
<span style="color:#7f007f"> filters</span>:- SaveSession</span></span></span>
如果您將Spring Security與Spring Session?集成在一起,并且想要確保安全性詳細信息已轉發到遠程進程,則至關重要。
115.18 SecureHeaders GatewayFilter工廠
SecureHeaders
?GatewayFilter Factory根據此博客文章的建議向響應中添加了許多標頭。
添加了以下標頭(以及默認值):
X-Xss-Protection:1; mode=block
Strict-Transport-Security:max-age=631138519
X-Frame-Options:DENY
X-Content-Type-Options:nosniff
Referrer-Policy:no-referrer
Content-Security-Policy:default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'
X-Download-Options:noopen
X-Permitted-Cross-Domain-Policies:none
要更改默認值,請在spring.cloud.gateway.filter.secure-headers
名稱空間中設置適當的屬性:
Property進行更改:
xss-protection-header
strict-transport-security
frame-options
content-type-options
referrer-policy
content-security-policy
download-options
permitted-cross-domain-policies
要禁用默認值,請使用逗號分隔值設置屬性spring.cloud.gateway.filter.secure-headers.disable
。
|
需要使用小寫和安全標頭的全名。 |
可以使用以下值:
x-xss-protection
strict-transport-security
x-frame-options
x-content-type-options
referrer-policy
content-security-policy
x-download-options
x-permitted-cross-domain-policies
例:?spring.cloud.gateway.filter.secure-headers.disable=x-frame-options,strict-transport-security
115.19 SetPath GatewayFilter工廠
SetPath
?GatewayFilter工廠采用路徑template
參數。通過允許路徑的模板段,它提供了一種操作請求路徑的簡單方法。這將使用Spring Framework中的uri模板。允許多個匹配段。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: setpath_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/foo/{segment<span style="color:#7f0055"><strong>}</strong></span>
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - SetPath</span>=/{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>
對于/foo/bar
的請求路徑,這將在發出下游請求之前將路徑設置為/bar
。
115.20 SetRequestHeader GatewayFilter工廠
SetRequestHeader
?GatewayFilter工廠采用name
和value
參數。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: setrequestheader_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - SetRequestHeader</span>=X-Request-Foo<span style="color:#7f0055"><strong>,</strong></span> Bar</span></span></span>
該GatewayFilter用給定的名稱替換所有標頭,而不是添加。因此,如果下游服務器響應X-Request-Foo:1234
,則將其替換為X-Request-Foo:Bar
,下游服務將收到此信息。
SetRequestHeader知道用于匹配路徑或主機的URI變量。URI變量可用于該值,并將在運行時擴展。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: setrequestheader_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Host</span>: {segment}.myhost.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - SetRequestHeader</span>=foo<span style="color:#7f0055"><strong>,</strong></span> bar-{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>
115.21 SetResponseHeader GatewayFilter工廠
SetResponseHeader
?GatewayFilter工廠采用name
和value
參數。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: setresponseheader_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - SetResponseHeader</span>=X-Response-Foo<span style="color:#7f0055"><strong>,</strong></span> Bar</span></span></span>
該GatewayFilter用給定的名稱替換所有標頭,而不是添加。因此,如果下游服務器以X-Response-Foo:1234
響應,則將其替換為X-Response-Foo:Bar
,這是網關客戶端將收到的內容。
SetResponseHeader知道用于匹配路徑或主機的URI變量。URI變量可用于該值,并將在運行時擴展。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: setresponseheader_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Host</span>: {segment}.myhost.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - SetResponseHeader</span>=foo<span style="color:#7f0055"><strong>,</strong></span> bar-{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>
115.22 SetStatus GatewayFilter工廠
SetStatus
?GatewayFilter工廠采用單個status
參數。它必須是有效的Spring?HttpStatus
。它可以是整數值404
,也可以是枚舉NOT_FOUND
的字符串表示形式。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: setstatusstring_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - SetStatus</span>=BAD_REQUEST
<span style="color:#7f007f"> - id</span>: setstatusint_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - SetStatus</span>=401</span></span></span>
無論哪種情況,響應的HTTP狀態都將設置為401。
115.23 StripPrefix GatewayFilter工廠
StripPrefix GatewayFilter工廠采用一個參數parts
。parts
參數指示在向下游發送請求之前,要從請求中剝離的路徑中的零件數。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: nameRoot
<span style="color:#7f007f"> uri</span>: http://nameservice
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/name/**
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - StripPrefix</span>=2</span></span></span>
通過網關發送到/name/bar/foo
的請求時,對nameservice
的請求將類似于http://nameservice/foo
。
115.24重試GatewayFilter工廠
Retry
?GatewayFilter Factory支持以下參數集:
retries
:應嘗試重試的次數statuses
:應重試的HTTP狀態代碼,用org.springframework.http.HttpStatus
表示methods
:應重試的HTTP方法,使用org.springframework.http.HttpMethod
表示series
:要重試的一系列狀態代碼,使用org.springframework.http.HttpStatus.Series
表示exceptions
:應重試引發的異常列表backoff
:為重試配置了指數補償。重試在退避間隔firstBackoff * (factor ^ n)
之后執行,其中n
是迭代。如果配置了maxBackoff
,則應用的最大退避將被限制為maxBackoff
。如果basedOnPreviousValue
為true,將使用prevBackoff * factor
計算退避。
如果啟用了Retry
過濾器,則會配置以下默認值:
retries
-3次series
?— 5XX系列methods
?— GET方法exceptions
-IOException
和TimeoutException
backoff
-已禁用
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: retry_test
<span style="color:#7f007f"> uri</span>: http://localhost:8080/flakey
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Host</span>=*.retry.com
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: Retry
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> retries</span>: 3
<span style="color:#7f007f"> statuses</span>: BAD_GATEWAY
<span style="color:#7f007f"> methods</span>: GET,POST
<span style="color:#7f007f"> backoff</span>:
<span style="color:#7f007f"> firstBackoff</span>: 10ms
<span style="color:#7f007f"> maxBackoff</span>: 50ms
<span style="color:#7f007f"> factor</span>: 2
<span style="color:#7f007f"> basedOnPreviousValue</span>: <span style="color:#7f0055"><strong>false</strong></span></span></span></span>
|
當使用帶有 |
|
當將重試過濾器與任何具有主體的HTTP方法一起使用時,主體將被緩存,并且網關將受到內存的限制。正文被緩存在 |
115.25 RequestSize GatewayFilter工廠
當請求大小大于允許的限制時,RequestSize
?GatewayFilter工廠可以限制請求到達下游服務。過濾器采用maxSize
參數,該參數是請求的允許大小限制。maxSize is a `DataSize
類型,因此值可以定義為數字,后跟可選的DataUnit
后綴,例如'KB'或'MB'。字節的默認值為“ B”。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: request_size_route
<span style="color:#7f007f"> uri</span>: http://localhost:8080/upload
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/upload
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: RequestSize
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> maxSize</span>: 5000000</span></span></span>
當請求因大小而被拒絕時,RequestSize GatewayFilter Factory將響應狀態設置為413 Payload Too Large
,并帶有一個附加報頭errorMessage
。以下是此類errorMessage
的示例。
errorMessage
?:?Request size is larger than permissible limit. Request size is 6.0 MB where permissible limit is 5.0 MB
|
如果未在路由定義中作為過濾器參數提供,則默認請求大小將設置為5 MB。 |
115.26修改請求正文GatewayFilter工廠
該過濾器被認為是BETA,API將來可能會更改
ModifyRequestBody
過濾器可用于在網關向下游發送請求主體之前修改請求主體。
|
只能使用Java DSL配置此過濾器 |
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> RouteLocator routes(RouteLocatorBuilder builder) {<span style="color:#7f0055"><strong>return</strong></span> builder.routes().route(<span style="color:#2a00ff">"rewrite_request_obj"</span>, r -> r.host(<span style="color:#2a00ff">"*.rewriterequestobj.org"</span>).filters(f -> f.prefixPath(<span style="color:#2a00ff">"/httpbin"</span>).modifyRequestBody(String.<span style="color:#7f0055"><strong>class</strong></span>, Hello.<span style="color:#7f0055"><strong>class</strong></span>, MediaType.APPLICATION_JSON_VALUE,(exchange, s) -> <span style="color:#7f0055"><strong>return</strong></span> Mono.just(<span style="color:#7f0055"><strong>new</strong></span> Hello(s.toUpperCase())))).uri(uri)).build();
}<span style="color:#7f0055"><strong>static</strong></span> <span style="color:#7f0055"><strong>class</strong></span> Hello {String message;<span style="color:#7f0055"><strong>public</strong></span> Hello() { }<span style="color:#7f0055"><strong>public</strong></span> Hello(String message) {<span style="color:#7f0055"><strong>this</strong></span>.message = message;}<span style="color:#7f0055"><strong>public</strong></span> String getMessage() {<span style="color:#7f0055"><strong>return</strong></span> message;}<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>void</strong></span> setMessage(String message) {<span style="color:#7f0055"><strong>this</strong></span>.message = message;}
}</span></span></span>
115.27修改響應主體GatewayFilter工廠
該過濾器被認為是BETA,API將來可能會更改
ModifyResponseBody
過濾器可用于在將響應正文發送回客戶端之前對其進行修改。
|
只能使用Java DSL配置此過濾器 |
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> RouteLocator routes(RouteLocatorBuilder builder) {<span style="color:#7f0055"><strong>return</strong></span> builder.routes().route(<span style="color:#2a00ff">"rewrite_response_upper"</span>, r -> r.host(<span style="color:#2a00ff">"*.rewriteresponseupper.org"</span>).filters(f -> f.prefixPath(<span style="color:#2a00ff">"/httpbin"</span>).modifyResponseBody(String.<span style="color:#7f0055"><strong>class</strong></span>, String.<span style="color:#7f0055"><strong>class</strong></span>,(exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri).build();
}</span></span></span>
115.28默認過濾器
如果您要添加過濾器并將其應用于所有路由,則可以使用spring.cloud.gateway.default-filters
。該屬性采用過濾器列表
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> default-filters</span>:
<span style="color:#7f007f"> - AddResponseHeader</span>=X-Response-Default-Foo<span style="color:#7f0055"><strong>,</strong></span> Default-Bar
<span style="color:#7f007f"> - PrefixPath</span>=/httpbin</span></span></span>
116.全局過濾器
GlobalFilter
接口具有與GatewayFilter
相同的簽名。這些是特殊過濾器,有條件地應用于所有路由。(此接口和用法可能會在將來的里程碑中更改)。
116.1組合的全局過濾器和GatewayFilter排序
當有請求進入(并與路由匹配)時,過濾Web處理程序會將GlobalFilter
的所有實例和GatewayFilter
的所有特定于路由的實例添加到過濾器鏈中。該組合的過濾器鏈通過org.springframework.core.Ordered
接口排序,可以通過實現getOrder()
方法進行設置。
由于Spring Cloud網關區分執行過濾器邏輯的“前”階段和“后”階段(請參閱:工作原理),因此,具有最高優先級的過濾器將在“前”階段中處于第一個階段,在“階段”中處于最后一個階段。 “后期”階段。
ExampleConfiguration.java。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> GlobalFilter customFilter() {<span style="color:#7f0055"><strong>return</strong></span> <span style="color:#7f0055"><strong>new</strong></span> CustomGlobalFilter();
}<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> CustomGlobalFilter <span style="color:#7f0055"><strong>implements</strong></span> GlobalFilter, Ordered {<em><span style="color:gray">@Override</span></em><span style="color:#7f0055"><strong>public</strong></span> Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info(<span style="color:#2a00ff">"custom global filter"</span>);<span style="color:#7f0055"><strong>return</strong></span> chain.filter(exchange);}<em><span style="color:gray">@Override</span></em><span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>int</strong></span> getOrder() {<span style="color:#7f0055"><strong>return</strong></span> -1;}
}</span></span></span>
116.2轉發路由過濾器
ForwardRoutingFilter
在交換屬性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
中尋找URI。如果該網址具有forward
方案(即forward:///localendpoint
),它將使用Spring?DispatcherHandler
處理請求。請求URL的路徑部分將被轉發URL中的路徑覆蓋。未經修改的原始URL會附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR
屬性中的列表中。
116.3 LoadBalancerClient篩選器
LoadBalancerClientFilter
在交換屬性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
中尋找URI。如果該網址具有lb
方案(即lb://myservice
),它將使用Spring Cloud?LoadBalancerClient
將名稱(上例中為myservice
)解析為實際的主機和端口并替換相同屬性中的URI。未經修改的原始URL會附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR
屬性中的列表中。過濾器還將查看ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR
屬性,以查看其是否等于lb
,然后應用相同的規則。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: myRoute
<span style="color:#7f007f"> uri</span>: lb://service
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/service/**</span></span></span>
|
默認情況下,當在 |
|
從 |
|
|
116.4 ReactiveLoadBalancerClientFilter
ReactiveLoadBalancerClientFilter
在交換屬性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
中尋找URI。如果該網址具有lb
方案(即lb://myservice
),它將使用Spring Cloud?ReactorLoadBalancer
將名稱(上例中為myservice
)解析為實際的主機和端口并替換相同屬性中的URI。未經修改的原始URL會附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR
屬性中的列表中。過濾器還將查看ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR
屬性,以查看其是否等于lb
,然后應用相同的規則。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: myRoute
<span style="color:#7f007f"> uri</span>: lb://service
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/service/**</span></span></span>
|
默認情況下,當 |
|
從 |
116.5網絡路由過濾器
如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
交換屬性中的URL具有http
或https
方案,則將運行Netty路由篩選器。它使用Netty?HttpClient
發出下游代理請求。響應將放在ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR
交換屬性中,以供以后的過濾器使用。(有一個實驗性WebClientHttpRoutingFilter
,它執行相同的功能,但不需要凈值)
116.6 Netty寫響應過濾器
如果ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR
交換屬性中有凈值HttpClientResponse
,則NettyWriteResponseFilter
將運行。它在所有其他篩選器完成后運行,并將代理響應寫回到網關客戶端響應。(有一個實驗性WebClientWriteResponseFilter
,它執行相同的功能,但不需要凈值)
116.7 RouteToRequestUrl過濾器
如果ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR
交換屬性中存在Route
對象,則RouteToRequestUrlFilter
將運行。它基于請求URI創建一個新URI,但使用Route
對象的URI屬性進行了更新。新的URI放置在ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
交換屬性中。
如果URI具有方案前綴(例如lb:ws://serviceid
),則將從URI中剝離lb
方案,并將其放在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR
中,以供以后在過濾器鏈中使用。
116.8 Websocket路由過濾器
如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
交換屬性中的URL具有ws
或wss
方案,則Websocket路由篩選器將運行。它使用Spring Web套接字基礎結構向下游轉發Websocket請求。
通過在URI前面加上lb
,例如lb:ws://serviceid
,可以實現Websocket的負載均衡。
|
如果您將SockJS用作常規http的后??備,則應配置常規HTTP路由以及Websocket路由。 |
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:<span style="color:#3f5f5f"><em># SockJS route</em></span>
<span style="color:#7f007f"> - id</span>: websocket_sockjs_route
<span style="color:#7f007f"> uri</span>: http://localhost:3001
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/websocket/info/**<span style="color:#3f5f5f"><em># Normal Websocket route</em></span>
<span style="color:#7f007f"> - id</span>: websocket_route
<span style="color:#7f007f"> uri</span>: ws://localhost:3001
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/websocket/**</span></span></span>
116.9網關指標過濾器
要啟用網關度量標準,請添加spring-boot-starter-actuator作為項目依賴項。然后,默認情況下,只要屬性spring.cloud.gateway.metrics.enabled
未設置為false
,網關度量過濾器就會運行。該過濾器添加了一個帶有以下標記的名為“ gateway.requests”的計時器指標:
routeId
:路線IDrouteUri
:API將被路由到的URIoutcome
:根據HttpStatus.Series分類的結果status
:返回給客戶端的請求的Http狀態httpStatusCode
:返回給客戶端的請求的Http狀態httpMethod
:用于請求的Http方法
然后可以從/actuator/metrics/gateway.requests
?抓取?這些指標,并且可以輕松地將其與Prometheus集成以創建Grafana?儀表板。
|
要啟用Prometheus端點,請添加micrometer-registry-prometheus作為項目依賴項。 |
116.10將交換標記為已路由
網關路由ServerWebExchange
后,它將通過在交換屬性中添加gatewayAlreadyRouted
將該交換標記為“已路由”。將請求標記為已路由后,其他路由篩選器將不會再次路由請求,實質上會跳過該篩選器。您可以使用多種便捷方法將交換標記為已路由,或者檢查交換是否已路由。
ServerWebExchangeUtils.isAlreadyRouted
接受ServerWebExchange
對象,并檢查其是否已“路由”ServerWebExchangeUtils.setAlreadyRouted
接受ServerWebExchange
對象,并將其標記為“已路由”
117. HttpHeadersFilters
HttpHeadersFilters在向下游發送請求之前(例如,在NettyRoutingFilter
中)已應用于請求。
117.1轉發的標題過濾器
Forwarded
標頭過濾器創建一個Forwarded
標頭,以發送到下游服務。它將當前請求的Host
標頭,方案和端口添加到任何現有的Forwarded
標頭中。
117.2 RemoveHopByHop標頭過濾器
RemoveHopByHop
標頭過濾器從轉發的請求中刪除標頭。被刪除的頭的默認列表來自IETF。
默認刪除的標題為:
- 連接
- 活著
- 代理驗證
- 代理授權
- TE
- 預告片
- 傳輸編碼
- 升級
要更改此設置,請將spring.cloud.gateway.filter.remove-non-proxy-headers.headers
屬性設置為要刪除的標頭名稱列表。
117.3 XForwarded標頭過濾器
XForwarded
標頭過濾器創建各種X-Forwarded-*
標頭,以發送到下游服務。它使用Host
頭,當前請求的方案,端口和路徑來創建各種頭。
可以通過以下布爾屬性(默認為true)控制單個標題的創建:
spring.cloud.gateway.x-forwarded.for.enabled
spring.cloud.gateway.x-forwarded.host.enabled
spring.cloud.gateway.x-forwarded.port.enabled
spring.cloud.gateway.x-forwarded.proto.enabled
spring.cloud.gateway.x-forwarded.prefix.enabled
可以通過以下布爾屬性(默認為true)控制追加多個標頭:
spring.cloud.gateway.x-forwarded.for.append
spring.cloud.gateway.x-forwarded.host.append
spring.cloud.gateway.x-forwarded.port.append
spring.cloud.gateway.x-forwarded.proto.append
spring.cloud.gateway.x-forwarded.prefix.append
118. TLS / SSL
網關可以通過遵循常規的Spring服務器配置來偵聽https上的請求。例:
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">server</span>:
<span style="color:#7f007f"> ssl</span>:
<span style="color:#7f007f"> enabled</span>: <span style="color:#7f0055"><strong>true</strong></span>
<span style="color:#7f007f"> key-alias</span>: scg
<span style="color:#7f007f"> key-store-password</span>: scg1234
<span style="color:#7f007f"> key-store</span>: classpath:scg-keystore.p12
<span style="color:#7f007f"> key-store-type</span>: PKCS12</span></span></span>
網關路由可以同時路由到http和https后端。如果路由到https后端,則可以使用以下配置將網關配置為信任所有下游證書:
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> httpclient</span>:
<span style="color:#7f007f"> ssl</span>:
<span style="color:#7f007f"> useInsecureTrustManager</span>: <span style="color:#7f0055"><strong>true</strong></span></span></span></span>
使用不安全的信任管理器不適用于生產。對于生產部署,可以為網關配置一組可以通過以下配置信任的已知證書:
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> httpclient</span>:
<span style="color:#7f007f"> ssl</span>:
<span style="color:#7f007f"> trustedX509Certificates</span>:- cert1.pem- cert2.pem</span></span></span>
如果Spring Cloud網關未配置受信任的證書,則使用默認的信任存儲(可以使用系統屬性javax.net.ssl.trustStore覆蓋)。
118.1 TLS握手
網關維護一個客戶端池,該客戶端池用于路由到后端。通過https進行通信時,客戶端會啟動TLS握手。許多超時與此握手相關聯。可以配置以下超時(顯示默認值):
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> httpclient</span>:
<span style="color:#7f007f"> ssl</span>:
<span style="color:#7f007f"> handshake-timeout-millis</span>: 10000
<span style="color:#7f007f"> close-notify-flush-timeout-millis</span>: 3000
<span style="color:#7f007f"> close-notify-read-timeout-millis</span>: 0</span></span></span>
119.配置
Spring Cloud網關的配置由RouteDefinitionLocator
的集合驅動。
RouteDefinitionLocator.java。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>interface</strong></span> RouteDefinitionLocator {Flux<RouteDefinition> getRouteDefinitions();
}</span></span></span>
默認情況下,PropertiesRouteDefinitionLocator
使用Spring Boot的@ConfigurationProperties
機制加載屬性。
上面的所有配置示例都使用一種快捷方式符號,該快捷方式符號使用位置參數而不是命名參數。以下兩個示例是等效的:
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: setstatus_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: SetStatus
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> status</span>: 401
<span style="color:#7f007f"> - id</span>: setstatusshortcut_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - SetStatus</span>=401</span></span></span>
對于網關的某些用法,屬性將是足夠的,但某些生產用例將受益于從外部源(例如數據庫)加載配置。未來的里程碑版本將基于Spring Data Repositories實現RouteDefinitionLocator
實現,例如:Redis,MongoDB和Cassandra。
119.1 Fluent Java Routes API
為了在Java中進行簡單的配置,在RouteLocatorBuilder
?bean中定義了一個流暢的API。
GatewaySampleApplication.java。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#3f5f5f"><em>// static imports from GatewayFilters and RoutePredicates</em></span>
<em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> RouteLocator customRouteLocator(RouteLocatorBuilder builder, ThrottleGatewayFilterFactory throttle) {<span style="color:#7f0055"><strong>return</strong></span> builder.routes().route(r -> r.host(<span style="color:#2a00ff">"**.abc.org"</span>).and().path(<span style="color:#2a00ff">"/image/png"</span>).filters(f ->f.addResponseHeader(<span style="color:#2a00ff">"X-TestHeader"</span>, <span style="color:#2a00ff">"foobar"</span>)).uri(<span style="color:#2a00ff">"http://httpbin.org:80"</span>)).route(r -> r.path(<span style="color:#2a00ff">"/image/webp"</span>).filters(f ->f.addResponseHeader(<span style="color:#2a00ff">"X-AnotherHeader"</span>, <span style="color:#2a00ff">"baz"</span>)).uri(<span style="color:#2a00ff">"http://httpbin.org:80"</span>)).route(r -> r.order(-1).host(<span style="color:#2a00ff">"**.throttle.org"</span>).and().path(<span style="color:#2a00ff">"/get"</span>).filters(f -> f.filter(throttle.apply(1,1,10,TimeUnit.SECONDS))).uri(<span style="color:#2a00ff">"http://httpbin.org:80"</span>)).build();
}</span></span></span>
此樣式還允許更多自定義謂詞斷言。RouteDefinitionLocator
?beans定義的謂詞使用邏輯and
進行組合。通過使用流暢的Java API,您可以在Predicate
類上使用and()
,or()
和negate()
運算符。
119.2 DiscoveryClient路由定義定位器
可以將網關配置為基于在DiscoveryClient
兼容服務注冊表中注冊的服務來創建路由。
要啟用此功能,請設置spring.cloud.gateway.discovery.locator.enabled=true
并確保在類路徑上啟用了DiscoveryClient
實現(例如Netflix Eureka,Consul或Zookeeper)。
119.2.1為DiscoveryClient路由配置謂詞和過濾器
默認情況下,網關為通過DiscoveryClient
創建的路由定義單個謂詞和過濾器。
默認謂詞是使用模式/serviceId/**
定義的路徑謂詞,其中serviceId
是DiscoveryClient
中服務的ID。
缺省過濾器是帶有正則表達式/serviceId/(?<remaining>.*)
和替換文本/${remaining}
的重寫路徑過濾器。這只是在將請求發送到下游之前從路徑中剝離服務ID。
如果要自定義DiscoveryClient
路由使用的謂詞和/或過濾器,可以通過設置spring.cloud.gateway.discovery.locator.predicates[x]
和spring.cloud.gateway.discovery.locator.filters[y]
來實現。這樣做時,如果要保留該功能,則需要確保在上面包含默認謂詞和過濾器。以下是此示例的示例。
application.properties。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">spring.cloud.gateway.discovery.locator.predicates[0].name: Path
spring.cloud.gateway.discovery.locator.predicates[0].args[pattern]: "'/'+serviceId+'/**'"
spring.cloud.gateway.discovery.locator.predicates[1].name: Host
spring.cloud.gateway.discovery.locator.predicates[1].args[pattern]: "'**.foo.com'"
spring.cloud.gateway.discovery.locator.filters[0].name: Hystrix
spring.cloud.gateway.discovery.locator.filters[0].args[name]: serviceId
spring.cloud.gateway.discovery.locator.filters[1].name: RewritePath
spring.cloud.gateway.discovery.locator.filters[1].args[regexp]: "'/' + serviceId + '/(?<remaining>.*)'"
spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'"</span></span></span>
120. Reactor Netty訪問日志
要啟用Reactor Netty訪問日志,請設置-Dreactor.netty.http.server.accessLogEnabled=true
。(它必須是Java系統Property,而不是Spring Boot屬性)。
日志系統可以配置為具有單獨的訪問日志文件。以下是示例登錄配置:
logback.xml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"> <span style="color:#3f7f7f"><appender</span> <span style="color:#7f007f">name</span>=<span style="color:#2a00ff">"accessLog"</span> <span style="color:#7f007f">class</span>=<span style="color:#2a00ff">"ch.qos.logback.core.FileAppender"</span><span style="color:#3f7f7f">></span><span style="color:#3f7f7f"><file></span>access_log.log<span style="color:#3f7f7f"></file></span><span style="color:#3f7f7f"><encoder></span><span style="color:#3f7f7f"><pattern></span>%msg%n<span style="color:#3f7f7f"></pattern></span><span style="color:#3f7f7f"></encoder></span><span style="color:#3f7f7f"></appender></span><span style="color:#3f7f7f"><appender</span> <span style="color:#7f007f">name</span>=<span style="color:#2a00ff">"async"</span> <span style="color:#7f007f">class</span>=<span style="color:#2a00ff">"ch.qos.logback.classic.AsyncAppender"</span><span style="color:#3f7f7f">></span><span style="color:#3f7f7f"><appender-ref</span> <span style="color:#7f007f">ref</span>=<span style="color:#2a00ff">"accessLog"</span><span style="color:#3f7f7f"> /></span><span style="color:#3f7f7f"></appender></span><span style="color:#3f7f7f"><logger</span> <span style="color:#7f007f">name</span>=<span style="color:#2a00ff">"reactor.netty.http.server.AccessLog"</span> <span style="color:#7f007f">level</span>=<span style="color:#2a00ff">"INFO"</span> <span style="color:#7f007f">additivity</span>=<span style="color:#2a00ff">"false"</span><span style="color:#3f7f7f">></span><span style="color:#3f7f7f"><appender-ref</span> <span style="color:#7f007f">ref</span>=<span style="color:#2a00ff">"async"</span><span style="color:#3f7f7f">/></span><span style="color:#3f7f7f"></logger></span></span></span></span>
121. CORS配置
可以將網關配置為控制CORS行為。“全局” CORS配置是URL模式到Spring Framework?CorsConfiguration的映射。
application.yml。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> globalcors</span>:
<span style="color:#7f007f"> corsConfigurations</span>:
<span style="color:#7f007f"> '[/**]'</span>:
<span style="color:#7f007f"> allowedOrigins</span>: <span style="color:#2a00ff">"https://docs.spring.io"</span>
<span style="color:#7f007f"> allowedMethods</span>:- GET</span></span></span>
在上面的示例中,對于所有GET請求的路徑,來自docs.spring.io的請求都將允許CORS請求。
要為未被某些網關路由謂詞處理的請求提供相同的CORS配置,請將屬性spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping
設置為true。當嘗試支持CORS預檢請求并且您的路由謂詞未評估為true時,這很有用,因為http方法為options
。
122.執行器API
/gateway
執行器端點允許監視Spring Cloud Gateway應用程序并與之交互。為了可遠程訪問,必須在應用程序屬性中通過HTTP或JMX?啟用和公開端點。
application.properties。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">management.endpoint.gateway.enabled</span>=true <span style="color:#3f5f5f"><em># default value</em></span>
<span style="color:#7f007f">management.endpoints.web.exposure.include</span>=gateway</span></span></span>
122.1詳細執行器格式
一種新的,更詳細的格式已添加到網關。這為每個路由增加了更多細節,從而允許查看與每個路由關聯的謂詞和過濾器以及任何可用的配置。
/actuator/gateway/routes
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>[</strong></span><span style="color:#7f0055"><strong>{</strong></span><span style="color:#2a00ff">"predicate"</span>: <span style="color:#2a00ff">"(Hosts: [**.addrequestheader.org] && Paths: [/headers], match trailing slash: true)"</span><span style="color:#7f0055"><strong>,</strong></span><span style="color:#2a00ff">"route_id"</span>: <span style="color:#2a00ff">"add_request_header_test"</span><span style="color:#7f0055"><strong>,</strong></span><span style="color:#2a00ff">"filters"</span>: <span style="color:#7f0055"><strong>[</strong></span><span style="color:#2a00ff">"[[AddResponseHeader X-Response-Default-Foo = 'Default-Bar'], order = 1]"</span><span style="color:#7f0055"><strong>,</strong></span><span style="color:#2a00ff">"[[AddRequestHeader X-Request-Foo = 'Bar'], order = 1]"</span><span style="color:#7f0055"><strong>,</strong></span><span style="color:#2a00ff">"[[PrefixPath prefix = '/httpbin'], order = 2]"</span>]<span style="color:#7f0055"><strong>,</strong></span><span style="color:#2a00ff">"uri"</span>: <span style="color:#2a00ff">"lb://testservice"</span><span style="color:#7f0055"><strong>,</strong></span><span style="color:#2a00ff">"order"</span>: 0<span style="color:#7f0055"><strong>}</strong></span>
<span style="color:#7f0055"><strong>]</strong></span></span></span></span>
要啟用此功能,請設置以下屬性:
application.properties。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring.cloud.gateway.actuator.verbose.enabled</span>=true</span></span></span>
在將來的版本中,該默認值為true。
122.2檢索路由過濾器
122.2.1全局過濾器
要檢索應用于所有路由的全局過濾器,請向/actuator/gateway/globalfilters
發出GET
請求。產生的響應類似于以下內容:
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">{"org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@77856cc5": 10100,"org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@4f6fd101": 10000,"org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@32d22650": -1,"org.springframework.cloud.gateway.filter.ForwardRoutingFilter@106459d9": 2147483647,"org.springframework.cloud.gateway.filter.NettyRoutingFilter@1fbd5e0": 2147483647,"org.springframework.cloud.gateway.filter.ForwardPathFilter@33a71d23": 0,"org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@135064ea": 2147483637,"org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@23c05889": 2147483646
}</span></span></span>
該響應包含適當的全局過濾器的詳細信息。為每個全局過濾器提供過濾器對象的字符串表示形式(例如org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@77856cc5
)和過濾器鏈中的相應順序。
122.2.2路由過濾器
要檢索應用于路由的GatewayFilter工廠,請向/actuator/gateway/routefilters
發出GET
請求。產生的響應類似于以下內容:
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">{"[AddRequestHeaderGatewayFilterFactory@570ed9c configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,"[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]": null,"[SaveSessionGatewayFilterFactory@4449b273 configClass = Object]": null
}</span></span></span>
該響應包含應用于任何特定路由的GatewayFilter工廠的詳細信息。為每個工廠提供相應對象的字符串表示形式(例如[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]
)。請注意,null
值是由于端點控制器的實現不完整而導致的,因為它試圖設置對象在過濾器鏈中的順序,該順序不適用于GatewayFilter工廠對象。
122.3刷新路由緩存
要清除路由緩存,請向/actuator/gateway/refresh
發出POST
請求。該請求返回200,但沒有響應主體。
122.4檢索網關中定義的路由
要檢索網關中定義的路由,請向/actuator/gateway/routes
發出GET
請求。產生的響應類似于以下內容:
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">[{"route_id": "first_route","route_object": {"predicate": "org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/1736826640@1e9d7e7d","filters": ["OrderedGatewayFilter{delegate=org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory$$Lambda$436/674480275@6631ef72, order=0}"]},"order": 0
},
{"route_id": "second_route","route_object": {"predicate": "org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/1736826640@cd8d298","filters": []},"order": 0
}]</span></span></span>
該響應包含網關中定義的所有路由的詳細信息。下表描述了響應的每個元素(即路線)的結構。
路徑 | 類型 | 描述 |
---|---|---|
| String | The route id. |
| Object | The route predicate. |
| Array | The?GatewayFilter factories?applied to the route. |
| Number | The route order. |
122.5檢索有關特定路線的信息
要檢索有關一條路線的信息,請向/actuator/gateway/routes/{id}
發送一個GET
請求(例如/actuator/gateway/routes/first_route
)。產生的響應類似于以下內容:
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">{"id": "first_route","predicates": [{"name": "Path","args": {"_genkey_0":"/first"}}],"filters": [],"uri": "https://www.uri-destination.org","order": 0
}]</span></span></span>
下表描述了響應的結構。
路徑 | 類型 | 描述 |
---|---|---|
| String | The route id. |
| Array | The collection of route predicates. Each item defines the name and the arguments of a given predicate. |
| Array | The collection of filters applied to the route. |
| String | The destination URI of the route. |
| Number | The route order. |
122.6創建和刪除特定路線
要創建路由,請使用指定路由字段的JSON正文向/gateway/routes/{id_route_to_create}
發出POST
請求(請參見上一小節)。
要刪除路由,請向/gateway/routes/{id_route_to_delete}
發出DELETE
請求。
122.7概述:所有端點的列表
下表總結了Spring Cloud網關執行器端點。請注意,每個端點都有/actuator/gateway
作為基本路徑。
ID | HTTP方法 | 描述 |
---|---|---|
| GET | Displays the list of global filters applied to the routes. |
| GET | Displays the list of GatewayFilter factories applied to a particular route. |
| POST | Clears the routes cache. |
| GET | Displays the list of routes defined in the gateway. |
| GET | Displays information about a particular route. |
| POST | Add a new route to the gateway. |
| DELETE | Remove an existing route from the gateway. |
123.故障排除
123.1日志級別
以下是一些有用的記錄器,它們包含DEBUG
和TRACE
級別的有價值的故障排除信息。
org.springframework.cloud.gateway
org.springframework.http.server.reactive
org.springframework.web.reactive
org.springframework.boot.autoconfigure.web
reactor.netty
redisratelimiter
123.2竊聽
Reactor Netty?HttpClient
和HttpServer
可以啟用竊聽功能。與將reactor.netty
日志級別設置為DEBUG
或TRACE
結合使用時,將允許記錄信息,例如通過網絡發送和接收的標頭和正文。要啟用此功能,請分別為HttpServer
和HttpClient
設置spring.cloud.gateway.httpserver.wiretap=true
和/或spring.cloud.gateway.httpclient.wiretap=true
。
124.開發人員指南
這些是編寫網關的某些自定義組件的基本指南。
124.1編寫自定義路由謂詞工廠
為了編寫路由謂詞,您將需要實現RoutePredicateFactory
。您可以擴展名為AbstractRoutePredicateFactory
的抽象類。
MyRoutePredicateFactory.java。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> MyRoutePredicateFactory <span style="color:#7f0055"><strong>extends</strong></span> AbstractRoutePredicateFactory<HeaderRoutePredicateFactory.Config> {<span style="color:#7f0055"><strong>public</strong></span> MyRoutePredicateFactory() {<span style="color:#7f0055"><strong>super</strong></span>(Config.<span style="color:#7f0055"><strong>class</strong></span>);}<em><span style="color:gray">@Override</span></em><span style="color:#7f0055"><strong>public</strong></span> Predicate<ServerWebExchange> apply(Config config) {<span style="color:#3f5f5f"><em>// grab configuration from Config object</em></span><span style="color:#7f0055"><strong>return</strong></span> exchange -> {<span style="color:#3f5f5f"><em>//grab the request</em></span>ServerHttpRequest request = exchange.getRequest();<span style="color:#3f5f5f"><em>//take information from the request to see if it</em></span><span style="color:#3f5f5f"><em>//matches configuration.</em></span><span style="color:#7f0055"><strong>return</strong></span> matches(config, request);};}<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>static</strong></span> <span style="color:#7f0055"><strong>class</strong></span> Config {<span style="color:#3f5f5f"><em>//Put the configuration properties for your filter here</em></span>}}</span></span></span>
124.2編寫自定義GatewayFilter工廠
為了編寫GatewayFilter,您將需要實現GatewayFilterFactory
。您可以擴展名為AbstractGatewayFilterFactory
的抽象類。
PreGatewayFilterFactory.java。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> PreGatewayFilterFactory <span style="color:#7f0055"><strong>extends</strong></span> AbstractGatewayFilterFactory<PreGatewayFilterFactory.Config> {<span style="color:#7f0055"><strong>public</strong></span> PreGatewayFilterFactory() {<span style="color:#7f0055"><strong>super</strong></span>(Config.<span style="color:#7f0055"><strong>class</strong></span>);}<em><span style="color:gray">@Override</span></em><span style="color:#7f0055"><strong>public</strong></span> GatewayFilter apply(Config config) {<span style="color:#3f5f5f"><em>// grab configuration from Config object</em></span><span style="color:#7f0055"><strong>return</strong></span> (exchange, chain) -> {<span style="color:#3f5f5f"><em>//If you want to build a "pre" filter you need to manipulate the</em></span><span style="color:#3f5f5f"><em>//request before calling chain.filter</em></span>ServerHttpRequest.Builder builder = exchange.getRequest().mutate();<span style="color:#3f5f5f"><em>//use builder to manipulate the request</em></span><span style="color:#7f0055"><strong>return</strong></span> chain.filter(exchange.mutate().request(request).build());};}<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>static</strong></span> <span style="color:#7f0055"><strong>class</strong></span> Config {<span style="color:#3f5f5f"><em>//Put the configuration properties for your filter here</em></span>}}</span></span></span>
PostGatewayFilterFactory.java。?
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> PostGatewayFilterFactory <span style="color:#7f0055"><strong>extends</strong></span> AbstractGatewayFilterFactory<PostGatewayFilterFactory.Config> {<span style="color:#7f0055"><strong>public</strong></span> PostGatewayFilterFactory() {<span style="color:#7f0055"><strong>super</strong></span>(Config.<span style="color:#7f0055"><strong>class</strong></span>);}<em><span style="color:gray">@Override</span></em><span style="color:#7f0055"><strong>public</strong></span> GatewayFilter apply(Config config) {<span style="color:#3f5f5f"><em>// grab configuration from Config object</em></span><span style="color:#7f0055"><strong>return</strong></span> (exchange, chain) -> {<span style="color:#7f0055"><strong>return</strong></span> chain.filter(exchange).then(Mono.fromRunnable(() -> {ServerHttpResponse response = exchange.getResponse();<span style="color:#3f5f5f"><em>//Manipulate the response in some way</em></span>}));};}<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>static</strong></span> <span style="color:#7f0055"><strong>class</strong></span> Config {<span style="color:#3f5f5f"><em>//Put the configuration properties for your filter here</em></span>}}</span></span></span>
124.3編寫自定義全局過濾器
為了編寫自定義全局過濾器,您將需要實現GlobalFilter
接口。這會將過濾器應用于所有請求。
如何分別設置全局前置和后置過濾器的示例
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> GlobalFilter customGlobalFilter() {<span style="color:#7f0055"><strong>return</strong></span> (exchange, chain) -> exchange.getPrincipal().map(Principal::getName).defaultIfEmpty(<span style="color:#2a00ff">"Default User"</span>).map(userName -> {<span style="color:#3f5f5f"><em>//adds header to proxied request</em></span>exchange.getRequest().mutate().header(<span style="color:#2a00ff">"CUSTOM-REQUEST-HEADER"</span>, userName).build();<span style="color:#7f0055"><strong>return</strong></span> exchange;}).flatMap(chain::filter);
}<em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> GlobalFilter customGlobalPostFilter() {<span style="color:#7f0055"><strong>return</strong></span> (exchange, chain) -> chain.filter(exchange).then(Mono.just(exchange)).map(serverWebExchange -> {<span style="color:#3f5f5f"><em>//adds header to response</em></span>serverWebExchange.getResponse().getHeaders().set(<span style="color:#2a00ff">"CUSTOM-RESPONSE-HEADER"</span>,HttpStatus.OK.equals(serverWebExchange.getResponse().getStatusCode()) ? <span style="color:#2a00ff">"It worked"</span>: <span style="color:#2a00ff">"It did not work"</span>);<span style="color:#7f0055"><strong>return</strong></span> serverWebExchange;}).then();
}</span></span></span>
125.使用Spring MVC或Webflux構建一個簡單的網關
|
以下描述了替代樣式的網關。先前文檔的None適用于以下內容。 |
Spring Cloud Gateway提供了一個名為ProxyExchange
的實用程序對象,您可以在常規的Spring web處理程序中將其用作方法參數。它通過鏡像HTTP動詞的方法支持基本的下游HTTP交換。使用MVC,它還支持通過forward()
方法轉發到本地處理程序。要使用ProxyExchange
,只需在類路徑中包含正確的模塊(spring-cloud-gateway-mvc
或spring-cloud-gateway-webflux
)。
MVC示例(代理對遠程服務器下游“ /測試”的請求):
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@RestController</span></em>
<em><span style="color:gray">@SpringBootApplication</span></em>
<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> GatewaySampleApplication {<em><span style="color:gray">@Value("${remote.home}")</span></em><span style="color:#7f0055"><strong>private</strong></span> URI home;<em><span style="color:gray">@GetMapping("/test")</span></em><span style="color:#7f0055"><strong>public</strong></span> ResponseEntity<?> proxy(ProxyExchange<<span style="color:#7f0055"><strong>byte</strong></span>[]> proxy) <span style="color:#7f0055"><strong>throws</strong></span> Exception {<span style="color:#7f0055"><strong>return</strong></span> proxy.uri(home.toString() + <span style="color:#2a00ff">"/image/png"</span>).get();}}</span></span></span>
與Webflux相同:
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@RestController</span></em>
<em><span style="color:gray">@SpringBootApplication</span></em>
<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> GatewaySampleApplication {<em><span style="color:gray">@Value("${remote.home}")</span></em><span style="color:#7f0055"><strong>private</strong></span> URI home;<em><span style="color:gray">@GetMapping("/test")</span></em><span style="color:#7f0055"><strong>public</strong></span> Mono<ResponseEntity<?>> proxy(ProxyExchange<<span style="color:#7f0055"><strong>byte</strong></span>[]> proxy) <span style="color:#7f0055"><strong>throws</strong></span> Exception {<span style="color:#7f0055"><strong>return</strong></span> proxy.uri(home.toString() + <span style="color:#2a00ff">"/image/png"</span>).get();}}</span></span></span>
ProxyExchange
上有一些便利的方法可以使處理程序方法發現并增強傳入請求的URI路徑。例如,您可能希望提取路徑的尾隨元素以將它們傳遞到下游:
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@GetMapping("/proxy/path/**")</span></em>
<span style="color:#7f0055"><strong>public</strong></span> ResponseEntity<?> proxyPath(ProxyExchange<<span style="color:#7f0055"><strong>byte</strong></span>[]> proxy) <span style="color:#7f0055"><strong>throws</strong></span> Exception {String path = proxy.path(<span style="color:#2a00ff">"/proxy/path/"</span>);<span style="color:#7f0055"><strong>return</strong></span> proxy.uri(home.toString() + <span style="color:#2a00ff">"/foos/"</span> + path).get();
}</span></span></span>
網關處理程序方法可以使用Spring MVC或Webflux的所有功能。因此,例如,您可以注入請求標頭和查詢參數,并且可以使用映射批注中的聲明來約束傳入的請求。有關這些功能的更多詳細信息,請參見Spring MVC中的@RequestMapping
文檔。
可以使用ProxyExchange
上的header()
方法將標頭添加到下游響應中。
您還可以通過將映射器添加到get()
等方法來操縱響應頭(以及響應中您喜歡的任何其他內容)。映射器是Function
,它接收傳入的ResponseEntity
并將其轉換為傳出的ResponseEntity
。
為不傳遞到下游的“敏感”標頭(默認情況下為“ cookie”和“授權”)以及“代理”標頭(x-forwarded-*
)提供了一流的支持