Spring Cloud之Gateway(二):閘道器過濾器
版本:2.0.2.RELEASE
連結:http://spring.io/projects/spring-cloud-gateway#overview
本章主要目錄如下:
Spring Cloud Gateway閘道器過濾器工廠是什麼?
本章主要內容如下:
Spring Cloud Gateway閘道器過濾器工廠是什麼?
路由過濾器允許以某種方式修改傳入的 HTTP 請求或輸出的 HTTP 響應。路由過濾器作用於特定路由。Spring Cloud Gateway 包含許多內建的 GatewayFilter 工廠。
注意:有關如何使用下面的任何過濾器的更詳細的示例,請看單元測試。
-
AddRequestHeader 閘道器過濾器工廠
新增請求頭閘道器過濾器工廠可以在請求頭中新增一對鍵值對引數。
application.yml
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: http://example.org
filters:
- AddRequestHeader=X-Request-Foo, Bar
這將為所有匹配請求的下游請求頭部新增 X-Request-Foo:Bar。
-
AddRequestParameter 閘道器過濾器工廠
新增請求引數閘道器過濾器工廠可以在請求中新增一對請求引數的鍵值對。
application.yml
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: http://example.org
filters:
- AddRequestParameter=foo, bar
這會將 foo=bar 新增到所有匹配請求的下游請求的查詢字串中。
-
AddResponseHeader 閘道器過濾器工廠
新增響應頭閘道器過濾器工廠可以在響應頭中新增鍵值對。
application.yml
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: http://example.org
filters:
- AddResponseHeader=X-Response-Foo, Bar
這會將 X-Response-Foo:Bar 新增到所有匹配請求的下游響應頭部中。
-
Hystrix 閘道器過濾器工廠
Hystrix 是 Netflix 的一個庫,它實現了斷路器模式。Hystrix 閘道器過濾器允許您將斷路器引入到閘道器路由,保護您的服務免受級聯故障的影響,並允許您在下游故障時提供回退響應。
要在專案中啟用Hystrix 閘道器過濾器,請從Spring Cloud Netflix中新增spring-cloud-starter-netflix-hystrix依賴項。
Hystrix 閘道器過濾器需要一個名稱引數,該引數是HystrixCommand 的名稱。
application.yml
spring:
cloud:
gateway:
routes:
- id: hystrix_route
uri: http://example.org
filters:
- Hystrix=myCommandName
這將使用命令名稱 myCommandName 將剩餘的過濾器包裝在 HystrixCommand 中。
Hystrix過濾器還可以接受可選的fallbackUri引數。 目前,僅支援forward:schemed URIs。如果呼叫了回退,請求將被轉發到與 URI 匹配的控制器。
application.yml
spring:
cloud:
gateway:
routes:
- id: hystrix_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingserviceendpoint
filters:
- name: Hystrix
args:
name: fallbackcmd
fallbackUri: forward:/incaseoffailureusethis
- RewritePath=/consumingserviceendpoint, /backingserviceendpoint
當呼叫 Hystrix 回退時,將轉發到/incaseoffailureusethis URI。請注意, 此示例還通過目標 URI 上的 lb 字首演示(可選)Spring Cloud Netflix Ribbon 負載均衡。
Hystrix 設定(例如超時)可以使用全域性預設值配置,也可以使用應用程式屬性逐個路徑配置,如 Hystrix wiki 中所述。
要為上面的示例路由設定 5 秒超時,將使用以下配置:
application.yml
hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000
-
PrefixPath 閘道器過濾器工廠
PrefixPath 閘道器過濾器工廠使用的是一個簡單的 prefix 引數。
application.yml
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: http://example.org
filters:
- PrefixPath=/mypath
這將使/mypath 為所有匹配請求的路徑字首。所以,向/hello 請求將被髮送到/mypath/hello。
-
PreserveHostHeader 閘道器過濾器工廠
此閘道器過濾器工廠沒有引數。此過濾器設定路由過濾器將檢查的請求屬性,以確定是否應傳送原始主機頭,而不是 http 客戶端確定的主機頭。
application.yml
spring:
cloud:
gateway:
routes:
- id: preserve_host_route
uri: http://example.org
filters:
- PreserveHostHeader
-
RequestRateLimiter 閘道器過濾器工廠
RequestRateLimiter 閘道器過濾器工廠使用 RateLimiter 實現來確定是否允許當前請求繼續。如果不是,則返回 HTTP 429 - Too Many Requests(預設情況下)的狀態。
此過濾器採用可選的 keyResolver 引數和特定於速率限制器的引數(參見下文)。
keyResolver 是一個實現 KeyResolver 介面的 bean。在配置中,使用 SpEL 按名稱引用bean。#{@myKeyResolver}是一個引用名為myKeyResolver的bean的SpEL表示式。
KeyResolver.java
public interface KeyResolver {
Mono<String> resolve(ServerWebExchange exchange);
}
KeyResolver 介面允許可插拔策略派生用於限制請求的金鑰。在未來的里程碑中,將會有一些 KeyResolver 實現。
KeyResolver 的預設實現是 PrincipalNameKeyResolver,它從 ServerWebExchange 檢索 Principal 並呼叫 Principal.getName()。
注意:RequestRateLimiter 不能通過“shortcut”表示法進行配置。以下示例無效。
application.properties.
# INVALID SHORTCUT CONFIGURATION
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}
-Redis 請求速率限制器
redis 實現基於 Stripe 完成的工作。它需要使用 spring-boot-starter-data-redis-reactive起步依賴。
使用的演算法是令牌桶演算法。
redis-rate-limiter.replenishRate:是您希望允許使用者每秒執行多少請求,而不會丟棄任何請求。這是令牌桶填充的速率。
redis-rate-limiter.burstCapacity:是使用者在一秒鐘內允許執行的最大請求數。這是令牌桶可以容納的令牌數。將此值設定為零將阻止所有請求。
通過在 replenishRate 和 burstCapacity 中設定相同的值來實現穩定的速率。通過將burstCapacity 設定為高於 replenishRate,可以允許臨時突發。在這種情況下,需要在這段突發時間之間允許速率限制器(根據 replenishRate),因為 2 個連續的突發將導致請求被丟棄(HTTP 429 - Too Many Requests)。
application.yml.
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: http://example.org
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
Config.java.
@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}
這定義了每個使用者的請求率限制是 10。允許突發 20,但下一秒只有 10 個請求可用。KeyResolver 是一個簡單的實現,它獲取使用者請求引數(注意:這不建議用於生產)。速率限制器也可以定義為實現 RateLimiter 介面的 bean。在配置中,使用 SpEL 按名稱引用 bean。#{@myRateLimiter}是一個引用名為 myRateLimiter 的 bean 的 SpEL 表示式。
application.yml.
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: http://example.org
filters:
- name: RequestRateLimiter
args:
rate-limiter: "#{@myRateLimiter}"
key-resolver: "#{@userKeyResolver}"
-
RedirectTo 閘道器過濾器工廠
重定向過濾器工廠接受一個狀態和一個 url 引數。該狀態是一個 300 系列重定向 http程式碼,如 301。url 應該是有效的 url。這將是 Location 頭部的值。
application.yml.
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: http://example.org
filters:
- RedirectTo=302, http://acme.org
將使用 Location:http://acme.org 標頭髮送狀態 302 以執行重定向。
-
RemoveNonProxyHeaders 閘道器過濾器工廠
刪除非代理頭閘道器過濾器工廠從轉發的請求中刪除請求頭。被刪除的請求頭的預設列表來自 IETF。
預設刪除的請求頭是:
Connection
Keep-Alive
Proxy-Authenticate
Proxy-Authorization
TE
Trailer
Transfer-Encoding
Upgrade
要更改此設定,請將 spring.cloud.gateway.filter.remove-non-proxy-headers.headers屬性設定為要刪除的標頭名稱列表。
-
RemoveRequestHeader 閘道器過濾器工廠
刪除請求頭閘道器過濾器工廠需要一個名稱的引數,這個名稱引數是需要刪除的請求頭名。
application.yml.
spring:
cloud:
gateway:
routes:
- id: removerequestheader_route
uri: http://example.org
filters:
- RemoveRequestHeader=X-Request-Foo
這將在向下遊傳送之前刪除 X-Request-Foo 請求頭。
-
RemoveResponseHeader 閘道器過濾器工廠
刪除響應頭閘道器過濾器工廠需要一個名稱的引數,這個名稱引數是需要刪除的響應頭名。
application.yml.
spring:
cloud:
gateway:
routes:
- id: removeresponseheader_route
uri: http://example.org
filters:
- RemoveResponseHeader=X-Response-Foo
將在返回到閘道器客戶端之前從響應中刪除 X-Response-Foo 頭。
-
RewritePath 閘道器過濾器工廠
RewritePath 閘道器過濾器工廠採用路徑正則表示式引數和一個替換引數。使用 Java 正
則表示式靈活地重寫請求路徑。
application.yml.
spring:
cloud:
gateway:
routes:
- id: rewritepath_route
uri: http://example.org
predicates:
- Path=/foo/**
filters:
- RewritePath=/foo/(?<segment>.*), /$\{segment}
對於/foo/bar 的請求路徑,將在生成下游請求之前設定路徑為/bar。注意,由於 YAML 規範,”$\” 被 “$” 替換。
-
SaveSession 閘道器過濾器工廠
SaveSession 閘道器過濾器工廠在轉發下游呼叫之前強制執行 WebSession::save 操作。當使用諸如 Spring Session 之類的帶有 lazy 資料儲存的東西時,這是特別有用的,並且需要在進行轉發呼叫之前確保會話狀態已被儲存。
application.yml.
spring:
cloud:
gateway:
routes:
- id: save_session
uri: http://example.org
predicates:
- Path=/foo/**
filters:
- SaveSession
如果您正在將 Spring Security 和 Spring Session 整合,並且希望確保安全細節已經轉發到遠端程序,那麼這是至關重要的。
-
SecureHeaders 閘道器過濾器工廠
安全頭閘道器過濾器工廠在此部落格文章(https://blog.appcanary.com/2017/http-security-headers.html)的推薦中為響應添加了許多標題。
添加了以下標頭(預設值):
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 名稱空間中設定相應的屬性:
要更改的屬性:
xss-protection-header
strict-transport-security
frame-options
content-type-options
referrer-policy
content-security-policy
download-options
permitted-cross-domain-policies
-
SetPath 閘道器過濾器工廠
設定路徑閘道器過濾器工廠採用路徑模板引數。它提供了一種通過允許路徑的模板段來操作請求路徑的簡單方法。這使用了來自 Spring 框架的 URI 模板。允許多個匹配段。
application.yml.
spring:
cloud:
gateway:
routes:
- id: setpath_route
uri: http://example.org
predicates:
- Path=/foo/{segment}
filters:
- SetPath=/{segment}
對於/foo/bar 的請求路徑,這將在進行下游請求之前將路徑設定為/bar。
-
SetResponseHeader 閘道器過濾器工廠
設定響應頭閘道器過濾器工廠需要引數名和引數的值的鍵值對引數。
application.yml.
spring:
cloud:
gateway:
routes:
- id: setresponseheader_route
uri: http://example.org
filters:
- SetResponseHeader=X-Response-Foo, Bar
這個閘道器過濾器將給定的名稱對應響應頭的值替換掉原來請求響應頭的值,注意不是新增而是替換。 因此,如果下游伺服器用 X-Response-Foo:1234 響應,則將被X-Response-Foo:Bar 替代,閘道器客戶端將收到的響應頭為 X-Response-Foo:Bar 而不是X-Response-Foo:1234。
-
SetStatus 閘道器過濾器工廠
設定請求響應狀態閘道器過濾器工廠需要一個 status 引數。該引數值必須是一個有效的Spring HttpStatus。該值可以是整型 404 或者是表示列舉型別 NOT_FOUND 的字串。
application.yml
spring:
cloud:
gateway:
routes:
- id: setstatusstring_route
uri: http://example.org
filters:
- SetStatus=BAD_REQUEST
- id: setstatusint_route
uri: http://example.org
filters:
- SetStatus=401
在這兩種情況下,響應的 HTTP 狀態將設定為 401。
-
StripPrefix 閘道器過濾器工廠
剝離字首閘道器過濾器工廠需要一個 parts 引數。parts 引數表明在將請求傳送到下游之前從請求中剝離的路徑中的元素數量。
application.yml.
spring:
cloud:
gateway:
routes:
- id: nameRoot
uri: http://nameservice
predicates:
- Path=/name/**
filters:
- StripPrefix=2
當通過閘道器向/name/bar/foo 發出請求時,對nameservice 的請求將類似於http://nameservice/foo
-
Retry 閘道器過濾器工廠
重試閘道器過濾器工廠需要 retries, statuses, methods 和 series 作為引數。
retries:將會嘗試的重試次數
statuses:將會重試的 HTTP 狀態程式碼,用org.springframework.http.HttpStatus
表示。
methods:將會重試的 HTTP 方法,使用 org.springframework.http.HttpMethod
表示。
series:要重試的一系列狀態程式碼,用 org.springframework.http.HttpStatus.Series
表示。
application.yml.
spring:
cloud:
gateway:
routes:
- id: retry_test
uri: http://localhost:8080/flakey
predicates:
- Host=*.retry.com
filters:
- name: Retry
args:
retries: 3
statuses: BAD_GATEWAY
注意:當使用帶有forward:字首URL 的重試過濾器時,應仔細編寫目標端點,以便在出現錯誤時不會執行任何可能導致響應傳送到客戶端並提交的操作。例如,如果目標端點是帶註釋的控制器,則目標控制器方法不應返回ResponseEntity錯誤狀態程式碼。相反,它應該丟擲一個Exception或發出錯誤訊號,例如通過Mono.error(ex)返回值,重試過濾器可以配置為通過重試來處理。這裡是不是可以理解使用前向協議的 URI 不支援使用重試過濾器。
//2.1.0.M3版本新增該過濾器,在這裡我們也做一下了解
-
RequestSize 閘道器過濾器工廠
當請求大小大於允許的限制時,RequestSize 閘道器過濾器可以限制請求到達下游服務。過濾器RequestSize作為引數,該引數是以位元組為單位定義的請求的允許大小限制。
application.yml。
spring:
cloud:
gateway:
routes:
- id:request_size_route
uri:http:// localhost:8080 / upload
predicates:
- Path = / upload
filters:
- name:RequestSize
args:
maxSize:5000000
當請求因大小而被拒絕時,RequestSize 閘道器過濾器將響應狀態設定為 413 Payload Too Large(有效負載太大),並附加標頭 errorMessage。以下是此類 errorMessage 的示例。
errorMessage : 請求大小大於允許的限制。請求大小為 6.0 MB,允許的限制為 5.0 MB。
注意:如果未在路由定義中提供過濾器引數,則預設請求大小將設定為5 MB。
如有疑惑,關注公眾號獲取更多內容,下一章將一起討論全域性過濾器。