目錄
1.How to Include Spring Cloud Gateway2.Glossary3.How It Works4.Route Predicate Factories5.GatewayFilter Factories6.Global Filters7.TLS/SSL8.Configuration9.Reactor Netty Access Logs10.CORS Configuration11.Actuator API12.Developer Guide
該項(xiàng)目提供了一個(gè)建立在Spring Ecosystem之上的API網(wǎng)關(guān),包括:Spring 5,Spring Boot 2和Project Reactor。Spring Cloud Gateway旨在提供一種簡(jiǎn)單而有效的方式來(lái)對(duì)API進(jìn)行路由,并為他們提供切面,例如:安全性,監(jiān)控/指標(biāo) 和彈性等。
1. 如何在工程中引用Spring Cloud Gateway
要在項(xiàng)目中引入Spring Cloud Gateway,需要引用 grouporg.springframework.cloud和 artifact id為spring-cloud-starter-gatewaystarter。最新的Spring Cloud Release 構(gòu)建信息,請(qǐng)參閱Spring Cloud Project page。
如果應(yīng)用了該starter,但由于某種原因不希望啟用網(wǎng)關(guān),請(qǐng)進(jìn)行設(shè)置spring.cloud.gateway.enabled=false。
重要
Spring Cloud Gateway依賴Spring Boot和Spring Webflux提供的Netty runtime。它不能在傳統(tǒng)的Servlet容器中工作或構(gòu)建為WAR
2. 詞匯表
Route 路由:gateway的基本構(gòu)建模塊。它由ID、目標(biāo)URI、斷言集合和過(guò)濾器集合組成。如果聚合斷言結(jié)果為真,則匹配到該路由。
Predicate 斷言:這是一個(gè)Java 8 Function Predicate。輸入類型是Spring FrameworkServerWebExchange。這允許開(kāi)發(fā)人員可以匹配來(lái)自HTTP請(qǐng)求的任何內(nèi)容,例如Header或參數(shù)。
Filter 過(guò)濾器:這些是使用特定工廠構(gòu)建的Spring FrameworkGatewayFilter實(shí)例。所以可以在返回請(qǐng)求之前或之后修改請(qǐng)求和響應(yīng)的內(nèi)容。
3. 如何工作的

Spring Cloud Gateway Diagram
客戶端向Spring Cloud Gateway發(fā)出請(qǐng)求。如果Gateway Handler Mapping確定請(qǐng)求與路由匹配,則將其發(fā)送到Gateway Web Handler。此handler通過(guò)特定于該請(qǐng)求的過(guò)濾器鏈處理請(qǐng)求。圖中filters被虛線劃分的原因是filters可以在發(fā)送代理請(qǐng)求之前或之后執(zhí)行邏輯。先執(zhí)行所有“pre filter”邏輯,然后進(jìn)行請(qǐng)求代理。在請(qǐng)求代理執(zhí)行完后,執(zhí)行“post filter”邏輯。
注意
HTTP和HTTPS URI默認(rèn)端口設(shè)置是80和443。
4. 路由斷言Factories
Spring Cloud Gateway將路由作為Spring WebFluxHandlerMapping基礎(chǔ)結(jié)構(gòu)的一部分進(jìn)行匹配。Spring Cloud Gateway包含許多內(nèi)置的路由斷言Factories。這些斷言都匹配HTTP請(qǐng)求的不同屬性。多個(gè)路由斷言Factories可以通過(guò)and組合使用。
4.1 After 路由斷言 Factory
After Route Predicate Factory采用一個(gè)參數(shù)——日期時(shí)間。在該日期時(shí)間之后發(fā)生的請(qǐng)求都將被匹配。
application.yml
spring:cloud:gateway:routes:-id:after_route? ? ? ? uri:http://example.org? ? ? ? predicates:-After=2017-01-20T17:42:47.789-07:00[America/Denver]
4.2 Before 路由斷言 Factory
Before Route Predicate Factory采用一個(gè)參數(shù)——日期時(shí)間。在該日期時(shí)間之前發(fā)生的請(qǐng)求都將被匹配。
application.yml.
spring:cloud:gateway:routes:-id:before_route? ? ? ? uri:http://example.org? ? ? ? predicates:-Before=2017-01-20T17:42:47.789-07:00[America/Denver]
4.3 Between 路由斷言 Factory
Between 路由斷言 Factory有兩個(gè)參數(shù),datetime1和datetime2。在datetime1和datetime2之間的請(qǐng)求將被匹配。datetime2參數(shù)的實(shí)際時(shí)間必須在datetime1之后。
application.yml.
spring:cloud:gateway:routes:-id:between_route? ? ? ? uri:http://example.org? ? ? ? predicates:-Between=2017-01-20T17:42:47.789-07:00[America/Denver],2017-01-21T17:42:47.789-07:00[America/Denver]
4.4 Cookie 路由斷言 Factory
Cookie 路由斷言 Factory有兩個(gè)參數(shù),cookie名稱和正則表達(dá)式。請(qǐng)求包含次cookie名稱且正則表達(dá)式為真的將會(huì)被匹配。
application.yml
spring:cloud:gateway:routes:-id:cookie_route? ? ? ? uri:http://example.org? ? ? ? predicates:-Cookie=chocolate,ch.p
4.5 Header? 路由斷言 Factory
Header 路由斷言 Factory有兩個(gè)參數(shù),header名稱和正則表達(dá)式。請(qǐng)求包含次header名稱且正則表達(dá)式為真的將會(huì)被匹配。
application.yml.
spring:cloud:gateway:routes:-id:header_route? ? ? uri:http://example.org? ? ? predicates:-Header=X-Request-Id,\d+
4.6 Host 路由斷言 Factory
Host 路由斷言 Factory包括一個(gè)參數(shù):host name列表。使用Ant路徑匹配規(guī)則,.作為分隔符。application.yml.
spring:cloud:gateway:routes:-id:host_route? ? ? ? uri:http://example.org? ? ? ? predicates:-Host=**.somehost.org,**.anotherhost.org
4.7 Method 路由斷言 Factory
Method 路由斷言 Factory只包含一個(gè)參數(shù): 需要匹配的HTTP請(qǐng)求方式
application.yml.
spring:cloud:gateway:routes:-id:method_route? ? ? ? uri:http://example.org? ? ? ? predicates:-Method=GET
所有GET請(qǐng)求都將被路由
4.8 Path 路由斷言 Factory
Path 路由斷言 Factory 有2個(gè)參數(shù): 一個(gè)SpringPathMatcher表達(dá)式列表和可選matchOptionalTrailingSeparator標(biāo)識(shí) .
application.yml.
spring:cloud:gateway:routes:-id:host_route? ? ? ? uri:http://example.org? ? ? ? predicates:-Path=/foo/{segment},/bar/{segment}
例如:/foo/1or/foo/baror/bar/baz的請(qǐng)求都將被匹配
URI 模板變量 (如上例中的segment) 將以Map的方式保存于ServerWebExchange.getAttributes()key為ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE. 這些值將在GatewayFilter Factories使用
可以使用以下方法來(lái)更方便地訪問(wèn)這些變量。
Map<String,String>uriVariables=ServerWebExchangeUtils.getPathPredicateVariables(exchange);String segment=uriVariables.get("segment");
4.9 Query 路由斷言 Factory
Query 路由斷言 Factory 有2個(gè)參數(shù): 必選項(xiàng)param和可選項(xiàng)regexp.
application.yml.
spring:cloud:gateway:routes:-id:query_route? ? ? ? uri:http://example.org? ? ? ? predicates:-Query=baz
則包含了請(qǐng)求參數(shù)baz的都將被匹配。
application.yml.
spring:cloud:gateway:routes:-id:query_route? ? ? ? uri:http://example.org? ? ? ? predicates:-Query=foo,ba.
如果請(qǐng)求參數(shù)里包含foo參數(shù),并且值匹配為ba.表達(dá)式,則將會(huì)被路由,如:barandbaz
4.10 RemoteAddr 路由斷言 Factory
RemoteAddr 路由斷言 Factory的參數(shù)為 一個(gè)CIDR符號(hào)(IPv4或IPv6)字符串的列表,最小值為1,例如192.168.0.1/16(其中192.168.0.1是IP地址并且16是子網(wǎng)掩碼)。
application.yml.
spring:cloud:gateway:routes:-id:remoteaddr_route? ? ? ? uri:http://example.org? ? ? ? predicates:-RemoteAddr=192.168.1.1/24
如果請(qǐng)求的remote address 為192.168.1.10則將被路由
4.10.1 修改遠(yuǎn)程地址的解析方式
默認(rèn)情況下,RemoteAddr 路由斷言 Factory使用傳入請(qǐng)求中的remote address。如果Spring Cloud Gateway位于代理層后面,則可能與實(shí)際客戶端IP地址不匹配。
可以通過(guò)設(shè)置自定義RemoteAddressResolver來(lái)自定義解析遠(yuǎn)程地址的方式。Spring Cloud Gateway網(wǎng)關(guān)附帶一個(gè)非默認(rèn)遠(yuǎn)程地址解析程序,它基于X-Forwarded-For header,XForwardedRemoteAddressResolver.
XForwardedRemoteAddressResolver有兩個(gè)靜態(tài)構(gòu)造函數(shù)方法,采用不同的安全方法:
XForwardedRemoteAddressResolver::TrustAll返回一個(gè)RemoteAddressResolver,它始終采用X-Forwarded-for頭中找到的第一個(gè)IP地址。這種方法容易受到欺騙,因?yàn)閻阂饪蛻舳丝赡軙?huì)為解析程序接受的“x-forwarded-for”設(shè)置初始值。
XForwardedRemoteAddressResolver::MaxTrustedIndex獲取一個(gè)索引,該索引與在Spring Cloud網(wǎng)關(guān)前運(yùn)行的受信任基礎(chǔ)設(shè)施數(shù)量相關(guān)。例如,如果SpringCloudGateway只能通過(guò)haproxy訪問(wèn),則應(yīng)使用值1。如果在訪問(wèn)Spring Cloud Gateway之前需要兩個(gè)受信任的基礎(chǔ)架構(gòu)躍點(diǎn),那么應(yīng)該使用2。
給定以下的header值:
X-Forwarded-For:0.0.0.1,0.0.0.2,0.0.0.3
下面的` maxTrustedIndex值將生成以下遠(yuǎn)程地址:

Java 配置方式:
GatewayConfig.java
RemoteAddressResolver resolver=XForwardedRemoteAddressResolver.maxTrustedIndex(1);....route("direct-route",r->r.remoteAddr("10.1.1.1","10.10.1.1/24").uri("https://downstream1").route("proxied-route",r->r.remoteAddr(resolver,"10.10.1.1","10.10.1.1/24").uri("https://downstream2"))
5. GatewayFilter Factories
過(guò)濾器允許以某種方式修改傳入的HTTP請(qǐng)求或返回的HTTP響應(yīng)。過(guò)濾器的作用域是某些特定路由。Spring Cloud Gateway包括許多內(nèi)置的 Filter工廠。
注意:有關(guān)如何使用以下任何過(guò)濾器的更詳細(xì)示例,請(qǐng)查看unit tests.。
5.1 AddRequestHeader GatewayFilter Factory
采用一對(duì)名稱和值作為參數(shù)application.yml.
spring:cloud:gateway:routes:-id:add_request_header_route? ? ? ? uri:http://example.org? ? ? ? filters:-AddRequestHeader=X-Request-Foo,Bar
對(duì)于所有匹配的請(qǐng)求,這將向下游請(qǐng)求的頭中添加x-request-foo:barheader
5.2 AddRequestParameter GatewayFilter Factory
采用一對(duì)名稱和值作為參數(shù)application.yml.
spring:cloud:gateway:routes:-id:add_request_parameter_route? ? ? ? uri:http://example.org? ? ? ? filters:-AddRequestParameter=foo,bar
對(duì)于所有匹配的請(qǐng)求,這將向下游請(qǐng)求添加foo=bar查詢字符串
5.3 AddResponseHeader GatewayFilter Factory
采用一對(duì)名稱和值作為參數(shù)
application.yml.
spring:cloud:gateway:routes:-id:add_request_header_route? ? ? ? uri:http://example.org? ? ? ? filters:-AddResponseHeader=X-Response-Foo,Bar
對(duì)于所有匹配的請(qǐng)求,這會(huì)將x-response-foo:bar頭添加到下游響應(yīng)的header中
5.4 Hystrix GatewayFilter Factory
Hystrix是Netflix開(kāi)源的斷路器組件。Hystrix GatewayFilter允許你向網(wǎng)關(guān)路由引入斷路器,保護(hù)你的服務(wù)不受級(jí)聯(lián)故障的影響,并允許你在下游故障時(shí)提供fallback響應(yīng)。
要在項(xiàng)目中啟用Hystrix網(wǎng)關(guān)過(guò)濾器,需要添加對(duì)spring-cloud-starter-netflix-hystrix的依賴Spring Cloud Netflix.
Hystrix GatewayFilter Factory 需要一個(gè)name參數(shù),即HystrixCommand的名稱。
application.yml.
spring:cloud:gateway:routes:-id:hystrix_route? ? ? ? uri:http://example.org? ? ? ? filters:-Hystrix=myCommandName
這將剩余的過(guò)濾器包裝在命令名為“myCommandName”的HystrixCommand中。
hystrix過(guò)濾器還可以接受可選的fallbackUri參數(shù)。目前,僅支持forward:預(yù)設(shè)的URI,如果調(diào)用fallback,則請(qǐng)求將轉(zhuǎn)發(fā)到與URI匹配的控制器。
application.yml.
spring:cloud:gateway:routes:-id:hystrix_route? ? ? ? uri:lb://backing-service:8088predicates:-Path=/consumingserviceendpoint? ? ? ? filters:-name:Hystrix? ? ? ? ? args:name:fallbackcmd? ? ? ? ? ? fallbackUri:forward:/incaseoffailureusethis-RewritePath=/consumingserviceendpoint,/backingserviceendpoint
當(dāng)調(diào)用hystrix fallback時(shí),這將轉(zhuǎn)發(fā)到/incaseoffailureusethisuri。注意,這個(gè)示例還演示了(可選)通過(guò)目標(biāo)URI上的'lb`前綴,使用Spring Cloud Netflix Ribbon 客戶端負(fù)載均衡。
主要場(chǎng)景是使用fallbackUri到網(wǎng)關(guān)應(yīng)用程序中的內(nèi)部控制器或處理程序。但是,也可以將請(qǐng)求重新路由到外部應(yīng)用程序中的控制器或處理程序,如:
application.yml.
spring:cloud:gateway:routes:-id:ingredients? ? ? ? uri:lb://ingredients? ? ? ? predicates:-Path=//ingredients/**
? ? ? ? filters:
? ? ? ? - name: Hystrix
? ? ? ? ? args:
? ? ? ? ? ? name: fetchIngredients
? ? ? ? ? ? fallbackUri: forward:/fallback
? ? ? - id: ingredients-fallback
? ? ? ? uri: http://localhost:9994
? ? ? ? predicates:
? ? ? ? - Path=/fallback
在本例中,gateway應(yīng)用程序中沒(méi)有fallback實(shí)現(xiàn),但是另一個(gè)應(yīng)用程序中有一個(gè)接口實(shí)現(xiàn),注冊(cè)為“http://localhost:9994”。
在將請(qǐng)求轉(zhuǎn)發(fā)到fallback的情況下,Hystrix Gateway過(guò)濾還支持直接拋出Throwable。它被作為ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR屬性添加到ServerWebExchange中,可以在處理網(wǎng)關(guān)應(yīng)用程序中的fallback時(shí)使用。
對(duì)于外部控制器/處理程序方案,可以添加帶有異常詳細(xì)信息的header??梢栽?a target="_blank">FallbackHeaders GatewayFilter Factory section.中找到有關(guān)它的更多信息。
hystrix配置參數(shù)(如 timeouts)可以使用全局默認(rèn)值配置,也可以使用Hystrix wiki中所述屬性進(jìn)行配置。
要為上面的示例路由設(shè)置5秒超時(shí),將使用以下配置:
application.yml.
hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds:5000
5.5 FallbackHeaders GatewayFilter Factory
FallbackHeaders允許在轉(zhuǎn)發(fā)到外部應(yīng)用程序中的FallbackUri的請(qǐng)求的header中添加Hystrix異常詳細(xì)信息,如下所示:
application.yml.
spring:cloud:gateway:routes:-id:ingredients? ? ? ? uri:lb://ingredients? ? ? ? predicates:-Path=//ingredients/**
? ? ? ? filters:
? ? ? ? - name: Hystrix
? ? ? ? ? args:
? ? ? ? ? ? name: fetchIngredients
? ? ? ? ? ? fallbackUri: forward:/fallback
? ? ? - id: ingredients-fallback
? ? ? ? uri: http://localhost:9994
? ? ? ? predicates:
? ? ? ? - Path=/fallback
? ? ? ? filters:
? ? ? ? - name: FallbackHeaders
? ? ? ? ? args:
? ? ? ? ? ? executionExceptionTypeHeaderName: Test-Header
在本例中,在運(yùn)行HystrixCommand發(fā)生執(zhí)行異常后,請(qǐng)求將被轉(zhuǎn)發(fā)到localhost:9994應(yīng)用程序中的fallback終端或程序。異常類型、消息(如果可用)cause exception類型和消息的頭,將由FallbackHeadersfilter添加到該請(qǐng)求中。
通過(guò)設(shè)置下面列出的參數(shù)值及其默認(rèn)值,可以在配置中覆蓋headers的名稱:
executionExceptionTypeHeaderName("Execution-Exception-Type")
executionExceptionMessageHeaderName("Execution-Exception-Message")
rootCauseExceptionTypeHeaderName("Root-Cause-Exception-Type")
rootCauseExceptionMessageHeaderName("Root-Cause-Exception-Message")
Hystrix 如何實(shí)現(xiàn)的更多細(xì)節(jié)可以參考Hystrix GatewayFilter Factory section.
5.6 PrefixPath GatewayFilter Factory
PrefixPath GatewayFilter 只有一個(gè)prefix參數(shù).
application.yml.
spring:cloud:gateway:routes:-id:prefixpath_route? ? ? ? uri:http://example.org? ? ? ? filters:-PrefixPath=/mypath
這將給所有匹配請(qǐng)求的路徑加前綴/mypath。因此,向/hello發(fā)送的請(qǐng)求將發(fā)送到/mypath/hello。
5.7 PreserveHostHeader GatewayFilter Factory
該filter沒(méi)有參數(shù)。設(shè)置了該Filter后,GatewayFilter將不使用由HTTP客戶端確定的host header ,而是發(fā)送原始host header 。
application.yml.
spring:cloud:gateway:routes:-id:preserve_host_route? ? ? ? uri:http://example.org? ? ? ? filters:-PreserveHostHeader
5.8 RequestRateLimiter GatewayFilter Factory
RequestRateLimiter使用RateLimiter實(shí)現(xiàn)是否允許繼續(xù)執(zhí)行當(dāng)前請(qǐng)求。如果不允許繼續(xù)執(zhí)行,則返回HTTP 429 - Too Many Requests(默認(rèn)情況下)。
這個(gè)過(guò)濾器可以配置一個(gè)可選的keyResolver參數(shù)和rate limiter參數(shù)(見(jiàn)下文)。
keyResolver是KeyResolver接口的實(shí)現(xiàn)類.在配置中,按名稱使用SpEL引用bean。#{@myKeyResolver}是引用名為'myKeyResolver'的bean的SpEL表達(dá)式。
KeyResolver.java.
publicinterfaceKeyResolver{Mono<String>resolve(ServerWebExchange exchange);}
KeyResolver接口允許使用可插拔策略來(lái)派生限制請(qǐng)求的key。在未來(lái)的里程碑版本中,將有一些KeyResolver實(shí)現(xiàn)。
KeyResolver的默認(rèn)實(shí)現(xiàn)是PrincipalNameKeyResolver,它從ServerWebExchange檢索Principal并調(diào)用Principal.getName()。
默認(rèn)情況下,如果KeyResolver沒(méi)有獲取到key,請(qǐng)求將被拒絕。此行為可以使用spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key(true or false) 和spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code屬性進(jìn)行調(diào)整。
說(shuō)明 無(wú)法通過(guò)"shortcut" 配置RequestRateLimiter。以下示例無(wú)效
application.properties.
# INVALID SHORTCUT CONFIGURATIONspring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2,2,#{@userkeyresolver}
5.8.1RedisRateLimiter
Redis的實(shí)現(xiàn)基于Stripe實(shí)現(xiàn)。它需要使用spring-boot-starter-data-redis-reactiveSpring Boot starter。
使用的算法是Token Bucket Algorithm.。
redis-rate-limiter.replenishRate是你允許用戶每秒執(zhí)行多少請(qǐng)求,而丟棄任何請(qǐng)求。這是令牌桶的填充速率。
``redis-rate-limiter.burstCapacity`是允許用戶在一秒鐘內(nèi)執(zhí)行的最大請(qǐng)求數(shù)。這是令牌桶可以保存的令牌數(shù)。將此值設(shè)置為零將阻止所有請(qǐng)求。
穩(wěn)定速率是通過(guò)在replenishRate和burstCapacity中設(shè)置相同的值來(lái)實(shí)現(xiàn)的??赏ㄟ^(guò)設(shè)置burstCapacity高于replenishRate來(lái)允許臨時(shí)突發(fā)流浪。在這種情況下,限流器需要在兩次突發(fā)之間留出一段時(shí)間(根據(jù)replenishRate),因?yàn)檫B續(xù)兩次突發(fā)將導(dǎo)致請(qǐng)求丟失 (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:10redis-rate-limiter.burstCapacity:20
Config.java.
@BeanKeyResolveruserKeyResolver(){returnexchange->Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));}
這定義了每個(gè)用戶10個(gè)請(qǐng)求的限制。允許20個(gè)突發(fā),但下一秒只有10個(gè)請(qǐng)求可用。KeyResolver是一個(gè)簡(jiǎn)單的獲取user請(qǐng)求參數(shù)的工具(注意:不建議用于生產(chǎn))。
限流器也可以定義為RateLimiter接口的實(shí)現(xiàn) bean。在配置中,按名稱使用SpEL引用bean。#{@myRateLimiter}是引用名為'myRateLimiter'的bean的SpEL表達(dá)式。
application.yml.
spring:cloud:gateway:routes:-id:requestratelimiter_route? ? ? ? uri:http://example.org? ? ? ? filters:-name:RequestRateLimiter? ? ? ? ? args:rate-limiter:"#{@myRateLimiter}"key-resolver:"#{@userKeyResolver}"
5.9 RedirectTo GatewayFilter Factory
該過(guò)濾器有一個(gè)status和一個(gè)url參數(shù)。status是300類重定向HTTP代碼,如301。該URL應(yīng)為有效的URL,這將是Locationheader的值。
application.yml.
spring:cloud:gateway:routes:-id:prefixpath_route? ? ? ? uri:http://example.org? ? ? ? filters:-RedirectTo=302,http://acme.org
這將發(fā)送一個(gè)302狀態(tài)碼和一個(gè)Location:http://acme.orgheader來(lái)執(zhí)行重定向。
5.10 RemoveNonProxyHeaders GatewayFilter Factory
RemoveNonProxyHeaders GatewayFilter Factory 從轉(zhuǎn)發(fā)請(qǐng)求中刪除headers。刪除的默認(rèn)頭列表來(lái)自IETF.
The default removed headers are:
Connection
Keep-Alive
Proxy-Authenticate
Proxy-Authorization
TE
Trailer
Transfer-Encoding
Upgrade 要更改此設(shè)置,請(qǐng)將spring.cloud.gateway.filter.remove-non-proxy-headers.headers屬性設(shè)置為要?jiǎng)h除的header名稱。
5.11 RemoveRequestHeader GatewayFilter Factory
有一個(gè)name參數(shù). 這是要?jiǎng)h除的header的名稱。
application.yml.
spring:cloud:gateway:routes:-id:removerequestheader_route? ? ? ? uri:http://example.org? ? ? ? filters:-RemoveRequestHeader=X-Request-Foo
這將在X-Request-Fooheader被發(fā)送到下游之前刪除它。
5.12 RemoveResponseHeader GatewayFilter Factory
有一個(gè)name參數(shù). 這是要?jiǎng)h除的header的名稱。
application.yml.
spring:cloud:gateway:routes:-id:removeresponseheader_route? ? ? ? uri:http://example.org? ? ? ? filters:-RemoveResponseHeader=X-Response-Foo
這將在返回到網(wǎng)關(guān)client之前從響應(yīng)中刪除x-response-foo頭。
5.13 RewritePath GatewayFilter Factory
包含一個(gè)regexp正則表達(dá)式參數(shù)和一個(gè)replacement參數(shù). 通過(guò)使用Java正則表達(dá)式靈活地重寫(xiě)請(qǐng)求路徑。
application.yml.
spring:cloud:gateway:routes:-id:rewritepath_route? ? ? ? uri:http://example.org? ? ? ? predicates:-Path=/foo/**
? ? ? ? filters:
? ? ? ? - RewritePath=/foo/(?<segment>.*), /$\{segment}
對(duì)于請(qǐng)求路徑/foo/bar,將在發(fā)出下游請(qǐng)求之前將路徑設(shè)置為/bar。注意,由于YAML規(guī)范,請(qǐng)使用$\替換$。
5.14 RewriteResponseHeader GatewayFilter Factory
包含name,regexp和replacement參數(shù).。通過(guò)使用Java正則表達(dá)式靈活地重寫(xiě)響應(yīng)頭的值。
application.yml.
spring:cloud:gateway:routes:-id:rewriteresponseheader_route? ? ? ? uri:http://example.org? ? ? ? filters:-RewriteResponseHeader=X-Response-Foo,,password=[^&]+,password=***
對(duì)于一個(gè)/42?user=ford&password=omg!what&flag=true的header值,在做下游請(qǐng)求時(shí)將被設(shè)置為/42?user=ford&password=***&flag=true,由于YAML規(guī)范,請(qǐng)使用$\替換$。
5.15 SaveSession GatewayFilter Factory
SaveSession GatewayFilter Factory將調(diào)用轉(zhuǎn)發(fā)到下游之前強(qiáng)制執(zhí)行WebSession::save操作。這在使用Spring Session之類時(shí)特別有用,需要確保會(huì)話狀態(tài)在進(jìn)行轉(zhuǎn)發(fā)調(diào)用之前已保存。
application.yml.
spring:cloud:gateway:routes:-id:save_session? ? ? ? uri:http://example.org? ? ? ? predicates:-Path=/foo/**
? ? ? ? filters:
? ? ? ? - SaveSession
如果你希望要將[Spring Security](https://projects.spring.io/SpringSecurity/)與Spring Session集成,并確保安全詳細(xì)信息已轉(zhuǎn)發(fā)到遠(yuǎn)程的進(jìn)程,這一點(diǎn)至關(guān)重要。
5.16 SecureHeaders GatewayFilter Factory
SecureHeaders GatewayFilter Factory 將許多headers添加到reccomedation處的響應(yīng)中,從this blog post.
添加以下標(biāo)題(使用默認(rèn)值分配):
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
要更改默認(rèn)值,請(qǐng)?jiān)趕pring.cloud.gateway.filter.secure-headers命名空間中設(shè)置相應(yīng)的屬性:
Property to change:
xss-protection-header
strict-transport-security
frame-options
content-type-options
referrer-policy
content-security-policy
download-options
permitted-cross-domain-policies
5.17 SetPath GatewayFilter Factory
SetPath GatewayFilter Factory 采用template路徑參數(shù)。它提供了一種通過(guò)允許路徑的模板化segments來(lái)操作請(qǐng)求路徑的簡(jiǎn)單方法。使用Spring Framework中的URI模板,允許多個(gè)匹配segments。
application.yml.
spring:cloud:gateway:routes:-id:setpath_route? ? ? ? uri:http://example.org? ? ? ? predicates:-Path=/foo/{segment}filters:-SetPath=/{segment}
對(duì)于一個(gè)/foo/bar請(qǐng)求,在做下游請(qǐng)求前,路徑將被設(shè)置為/bar
5.18 SetResponseHeader GatewayFilter Factory
SetResponseHeader GatewayFilter Factory 包括name和value參數(shù).
application.yml.
spring:cloud:gateway:routes:-id:setresponseheader_route? ? ? ? uri:http://example.org? ? ? ? filters:-SetResponseHeader=X-Response-Foo,Bar
此GatewayFilter使用給定的名稱替換所有header,而不是添加。因此,如果下游服務(wù)器響應(yīng)為X-Response-Foo:1234,則會(huì)將其替換為X-Response-Foo:Bar,這是網(wǎng)關(guān)客戶端將接收的內(nèi)容。
5.19 SetStatus GatewayFilter Factory
SetStatus GatewayFilter Factory 包括唯一的status參數(shù).必須是一個(gè)可用的SpringHttpStatus。它可以是整數(shù)值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
在這個(gè)例子中,HTTP返回碼將設(shè)置為401.
5.20 StripPrefix GatewayFilter Factory
StripPrefix GatewayFilter Factory 包括一個(gè)parts參數(shù)。parts參數(shù)指示在將請(qǐng)求發(fā)送到下游之前,要從請(qǐng)求中去除的路徑中的節(jié)數(shù)。
application.yml.
spring:cloud:gateway:routes:-id:nameRoot? ? ? ? uri:http://nameservice? ? ? ? predicates:-Path=/name/**
? ? ? ? filters:
? ? ? ? - StripPrefix=2
當(dāng)通過(guò)網(wǎng)關(guān)發(fā)出/name/bar/foo請(qǐng)求時(shí),向nameservice發(fā)出的請(qǐng)求將是http://nameservice/foo。
5.21 Retry GatewayFilter Factory
Retry GatewayFilter Factory包括retries,statuses,methods和series參數(shù).
retries: 應(yīng)嘗試的重試次數(shù)
statuses: 應(yīng)該重試的HTTP狀態(tài)代碼,用org.springframework.http.HttpStatus標(biāo)識(shí)
methods: 應(yīng)該重試的HTTP方法,用org.springframework.http.HttpMethod標(biāo)識(shí)
series: 要重試的一系列狀態(tài)碼,用org.springframework.http.HttpStatus.Series標(biāo)識(shí)
application.yml.
spring: cloud: gateway: routes: - id: retry_test uri:http://localhost:8080/flakeypredicates: - Host=*.retry.com filters: - name: Retry args: retries: 3 statuses: BAD_GATEWAY
注意
retry filter 不支持body請(qǐng)求的重試,如通過(guò)body的POST 或 PUT請(qǐng)求
注意 在使用帶有前綴為forward:的retry filter時(shí),應(yīng)仔細(xì)編寫(xiě)目標(biāo)端點(diǎn),以便在出現(xiàn)錯(cuò)誤時(shí)不會(huì)執(zhí)行任何可能導(dǎo)致將響應(yīng)發(fā)送到客戶端并提交的操作。例如,如果目標(biāo)端點(diǎn)是帶注解的controller,則目標(biāo)controller方法不應(yīng)返回帶有錯(cuò)誤狀態(tài)代碼的ResponseEntity。相反,它應(yīng)該拋出一個(gè)Exception,或者發(fā)出一個(gè)錯(cuò)誤信號(hào),例如通過(guò)Mono.error(ex)返回值,重試過(guò)濾器可以配置為通過(guò)重試來(lái)處理。
5.22 RequestSize GatewayFilter Factory
當(dāng)請(qǐng)求大小大于允許的限制時(shí),RequestSize GatewayFilter Factory可以限制請(qǐng)求不到達(dá)下游服務(wù)。過(guò)濾器以RequestSize作為參數(shù),這是定義請(qǐng)求的允許大小限制(以字節(jié)為單位)。
application.yml.
spring:cloud:gateway:routes:-id:request_size_route? ? ? uri:http://localhost:8080/upload? ? ? predicates:-Path=/upload? ? ? filters:-name:RequestSize? ? ? ? args:maxSize:5000000
當(dāng)請(qǐng)求因大小而被拒絕時(shí), RequestSize GatewayFilter Factory 將響應(yīng)狀態(tài)設(shè)置為413 Payload Too Large,并帶有額外的headererrorMessage。下面是一個(gè)errorMessage的例子。
errorMessage:Request size is larger than permissible limit. Request size is 6.0 MB where permissible limit is 5.0 MB
注意
如果未在路由定義中作為filter參數(shù)提供,則默認(rèn)請(qǐng)求大小將設(shè)置為5 MB。
5.23 Modify Request Body GatewayFilter Factory
這個(gè)過(guò)濾器被定義為beta版本,將來(lái)API可能會(huì)改變。
此過(guò)濾器可用于在請(qǐng)求主體被網(wǎng)關(guān)發(fā)送到下游之前對(duì)其進(jìn)行修改。
注意
只能使用Java DSL配置此過(guò)濾器
@BeanpublicRouteLocatorroutes(RouteLocatorBuilder builder){returnbuilder.routes().route("rewrite_request_obj",r->r.host("*.rewriterequestobj.org").filters(f->f.prefixPath("/httpbin").modifyRequestBody(String.class,Hello.class,MediaType.APPLICATION_JSON_VALUE,(exchange,s)->returnMono.just(newHello(s.toUpperCase())))).uri(uri)).build();}staticclassHello{String message;publicHello(){}publicHello(String message){this.message=message;}publicStringgetMessage(){returnmessage;}publicvoidsetMessage(String message){this.message=message;}}
5.24 Modify Response Body GatewayFilter Factory
這個(gè)過(guò)濾器被定義為beta版本,將來(lái)API可能會(huì)改變。
此過(guò)濾器可用于在將響應(yīng)正文發(fā)送回客戶端之前對(duì)其進(jìn)行修改。
注意
只能使用Java DSL配置此過(guò)濾器
@BeanpublicRouteLocatorroutes(RouteLocatorBuilder builder){returnbuilder.routes().route("rewrite_response_upper",r->r.host("*.rewriteresponseupper.org").filters(f->f.prefixPath("/httpbin").modifyResponseBody(String.class,String.class,(exchange,s)->Mono.just(s.toUpperCase()))).uri(uri).build();}
6. Global Filters
GlobalFilter接口與GatewayFilter具有相同的簽名。是有條件地應(yīng)用于所有路由的特殊過(guò)濾器。(此接口和用法可能在將來(lái)的里程碑版本中發(fā)生更改)。
6.1 全局Filter和GatewayFilter組合排序
當(dāng)請(qǐng)求進(jìn)入(并與路由匹配)時(shí),篩選Web Handler 會(huì)將GlobalFilter的所有實(shí)例和所有的GatewayFilter路由特定實(shí)例添加到 filter chain。filter組合的排序由org.springframework.core.Ordered接口決定,可以通過(guò)實(shí)現(xiàn)getOrde()方法或使用@Order注釋來(lái)設(shè)置。
由于Spring Cloud Gateway將用于執(zhí)行過(guò)濾器邏輯區(qū)分為“前置”和“后置”階段,具有最高優(yōu)先級(jí)的過(guò)濾器將是“前置”階段的第一個(gè),而“后置”階段的最后一個(gè)。
ExampleConfiguration.java.
@Bean@Order(-1)publicGlobalFiltera(){return(exchange,chain)->{log.info("first pre filter");returnchain.filter(exchange).then(Mono.fromRunnable(()->{log.info("third post filter");}));};}@Bean@Order(0)publicGlobalFilterb(){return(exchange,chain)->{log.info("second pre filter");returnchain.filter(exchange).then(Mono.fromRunnable(()->{log.info("second post filter");}));};}@Bean@Order(1)publicGlobalFilterc(){return(exchange,chain)->{log.info("third pre filter");returnchain.filter(exchange).then(Mono.fromRunnable(()->{log.info("first post filter");}));};}
6.2 Forward Routing Filter
ForwardRoutingFilter在exchange屬性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR中查找URI。如果URL有一個(gè)forwardscheme (如forward:///localendpoint),它將使用SpringDispatcherHandler來(lái)處理請(qǐng)求。請(qǐng)求URL的路徑部分將被轉(zhuǎn)發(fā)URL中的路徑覆蓋。未修改的原始URL將附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR屬性中的列表中。
6.3 LoadBalancerClient Filter
LoadBalancerClientFilter在exchange屬性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR中查找URI。如果URL有一個(gè)lbscheme (如lb://myservice),它將使用Spring CloudLoadBalancerClient將名稱(在前一個(gè)示例中為'myservice)解析為實(shí)際主機(jī)和端口,并替換URI。未修改的原始URL將附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR屬性中的列表中。過(guò)濾器還將查看ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR屬性,查看它是否等于lb`,然后應(yīng)用相同的規(guī)則。
application.yml.
spring:cloud:gateway:routes:-id:myRoute? ? ? ? uri:lb://service? ? ? ? predicates:-Path=/service/**
注意 默認(rèn)情況下,如果一個(gè)服務(wù)實(shí)例在LoadBalancer中沒(méi)有發(fā)現(xiàn),則返回503??梢酝ㄟ^(guò)設(shè)置spring.cloud.gateway.loadbalancer.use404=true來(lái)讓網(wǎng)管返回404.
注意
從LoadBalancer返回的ServiceInstance的isSecure值將覆蓋在對(duì)網(wǎng)關(guān)發(fā)出的請(qǐng)求中指定的scheme。例如,如果請(qǐng)求通過(guò)HTTPS進(jìn)入網(wǎng)關(guān),但ServiceInstance表示它不安全,則下游請(qǐng)求將通過(guò)HTTP協(xié)議。相反的情況也適用。但是,如果在網(wǎng)關(guān)配置中為路由指定了GATEWAY_SCHEME_PREFIX_ATTR,則前綴將被刪除,并且路由URL生成的scheme將覆蓋ServiceInstance配置。
6.4 Netty Routing Filter
如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR屬性中的URL具有http或https模式,則會(huì)運(yùn)行Netty Routing Filter。它使用NettyHttpClient發(fā)出下游代理請(qǐng)求。響應(yīng)放在ServerWebExchangeUtils.CLIENT_RESPONSE_ATTRexchange屬性中,以便在以后的過(guò)濾器中使用。(有一個(gè)實(shí)驗(yàn)階段不需要Netty的相同的功能的Filter,WebClientHttpRoutingFilter)
6.5 Netty Write Response Filter
如果ServerWebExchangeUtils.CLIENT_RESPONSE_ATTRexchange屬性中存在 NettyHttpClientResponse,則運(yùn)行NettyWriteResponseFilter。它在其他所有過(guò)濾器完成后將代理響應(yīng)寫(xiě)回網(wǎng)關(guān)客戶端響應(yīng)之后運(yùn)行。(有一個(gè)不需要netty的實(shí)驗(yàn)性的WebClientWriteResponseFilter執(zhí)行相同的功能)
6.6 RouteToRequestUrl Filter
如果ServerWebExchangeUtils.GATEWAY_ROUTE_ATTRexchange屬性中存在Route對(duì)象,RouteToRequestUrlFilter將運(yùn)行。它基于請(qǐng)求URI創(chuàng)建一個(gè)新的URI,使用Route對(duì)象的uri屬性進(jìn)行更新。新的URI被放置在ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTRexchange屬性中。
如果該URI有一個(gè)前綴scheme,例如lb:ws://serviceid,則會(huì)從該URI中剝離該lbscheme,并將其放置在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR中,以便稍后在過(guò)濾器鏈中使用。
6.7 Websocket Routing Filter
如果ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTRexchange屬性中有ws、wssscheme,則Websocket Routing Filter將被運(yùn)行。它使用Spring Web Socket基礎(chǔ)模塊將Websocket轉(zhuǎn)發(fā)到下游。
URI前綴為lb的Websockets可以被負(fù)載均衡,如lb:ws://serviceid.
注意 如果使用SockJS作為普通HTTP的fallback,則應(yīng)配置普通HTTP路由以及WebSocket路由。
application.yml.
spring:cloud:gateway:routes:# SockJS route-id:websocket_sockjs_route? ? ? ? uri:http://localhost:3001predicates:-Path=/websocket/info/**
? ? ? # Normwal Websocket route
? ? ? - id: websocket_route
? ? ? ? uri: ws://localhost:3001
? ? ? ? predicates:
? ? ? ? - Path=/websocket/**
6.8 Gateway Metrics Filter
要啟用網(wǎng)關(guān)指標(biāo),請(qǐng)將spring-boot-starter-actuator添加為項(xiàng)目依賴項(xiàng)。然后,默認(rèn)情況下,只要屬性spring.cloud.gateway.metrics.enabled未設(shè)置為false,網(wǎng)關(guān)指標(biāo)過(guò)濾器就會(huì)運(yùn)行。此過(guò)濾器添加名為“gateway.requests”的計(jì)時(shí)器指標(biāo),并帶有以下標(biāo)記:
routeId: The route id
routeUri:? API 將被轉(zhuǎn)發(fā)的URI
outcome: 結(jié)果分類依據(jù)HttpStatus.Series
status: 返回client的請(qǐng)求的Http Status
這些指標(biāo)可以從/actuator/metrics/gateway.requests中獲取,可以很容易地與Prometheus集成以創(chuàng)建Grafanadashboard.
注意
要將pometheus啟用,需要添加 micrometer-registry-prometheus為項(xiàng)目依賴。
6.9 Making An Exchange As Routed
網(wǎng)關(guān)路由ServerWebExchange之后,它將通過(guò)向Exchange屬性添加gatewayAlreadyRouted,將該exchange標(biāo)記為“routed”。一旦一個(gè)請(qǐng)求被標(biāo)記為routed,其他路由過(guò)濾器將不會(huì)再次路由該請(qǐng)求,將跳過(guò)該過(guò)濾器。有一些方便的方法可以用來(lái)將exchange標(biāo)記為routed,或者檢查exchange是否已經(jīng)routed。
ServerWebExchangeUtils.isAlreadyRouted有一個(gè)ServerWebExchange對(duì)象并檢查它是否已"routed"
ServerWebExchangeUtils.setAlreadyRouted有一個(gè)ServerWebExchange對(duì)象并將其標(biāo)記為"routed"
7. TLS / SSL
網(wǎng)關(guān)可以通過(guò)常規(guī)的 Spring server configuration 來(lái)偵聽(tīng)HTTPS上的請(qǐng)求。例子:
application.yml.
server:ssl:enabled:truekey-alias:scg? ? key-store-password:scg1234? ? key-store:classpath:scg-keystore.p12? ? key-store-type:PKCS12
網(wǎng)關(guān)路由可以路由到HTTP和HTTPS后端。如果路由到HTTPS后端,則可以將網(wǎng)關(guān)配置為信任所有具有證書(shū)的下游服務(wù):
application.yml.
spring:cloud:gateway:httpclient:ssl:useInsecureTrustManager:true
不建議在生產(chǎn)環(huán)境使用不安全的信任管理器。對(duì)于生產(chǎn)部署,可以使用一組已知證書(shū)配置網(wǎng)關(guān),這些證書(shū)可以通過(guò)以下方式進(jìn)行配置:
application.yml.
spring:cloud:gateway:httpclient:ssl:trustedX509Certificates:-cert1.pem-cert2.pem
如果Spring Cloud Gateway未配置受信任證書(shū),則使用默認(rèn)信任庫(kù)(可以使用系統(tǒng)屬性javax.net.ssl.trustStore覆蓋)。
7.1 TLS 握手
網(wǎng)關(guān)維護(hù)一個(gè)用于路由到后端的client池。當(dāng)通過(guò)HTTPS通信時(shí),客戶端啟動(dòng)一個(gè)TLS握手,其中可能會(huì)有很多超時(shí)。這些超時(shí)可以這樣配置(顯示默認(rèn)值):
application.yml.
spring:cloud:gateway:httpclient:ssl:handshake-timeout-millis:10000close-notify-flush-timeout-millis:3000close-notify-read-timeout-millis:0
8. Configuration
Spring Cloud Gateway的配置由RouteDefinitionLocator的集合驅(qū)動(dòng)。
RouteDefinitionLocator.java.
publicinterfaceRouteDefinitionLocator{Flux<RouteDefinition>getRouteDefinitions();}
默認(rèn)情況下,PropertiesRouteDefinitionLocator使用Spring Boot的@ConfigurationProperties機(jī)制加載屬性。
以下兩個(gè)示例是等效的:
application.yml.
spring:cloud:gateway:routes:-id:setstatus_route? ? ? ? uri:http://example.org? ? ? ? filters:-name:SetStatus? ? ? ? ? args:status:401-id:setstatusshortcut_route? ? ? ? uri:http://example.org? ? ? ? filters:-SetStatus=401
對(duì)于網(wǎng)關(guān)的大部分用法,配置文件方式是夠用的,但一些生產(chǎn)用例更建議從外部源(如數(shù)據(jù)庫(kù))加載配置。未來(lái)的里程碑版本將有基于Spring Data Repositories (如Redis、MongoDB和Cassandra)的RouteDefinitionLocator實(shí)現(xiàn)。
8.1 Fluent Java Routes API
為了可以更簡(jiǎn)單在Java中配置,在RouteLocatorBuilderbean中定義了一個(gè)fluent API。
GatewaySampleApplication.java.
// static imports from GatewayFilters and RoutePredicates@BeanpublicRouteLocatorcustomRouteLocator(RouteLocatorBuilder builder,ThrottleGatewayFilterFactory throttle){returnbuilder.routes().route(r->r.host("**.abc.org").and().path("/image/png").filters(f->f.addResponseHeader("X-TestHeader","foobar")).uri("http://httpbin.org:80")).route(r->r.path("/image/webp").filters(f->f.addResponseHeader("X-AnotherHeader","baz")).uri("http://httpbin.org:80")).route(r->r.order(-1).host("**.throttle.org").and().path("/get").filters(f->f.filter(throttle.apply(1,1,10,TimeUnit.SECONDS))).uri("http://httpbin.org:80")).build();}
這種樣式還允許使用更多的自定義斷言。由RouteDefinitionLocatorbeans定義的斷言使用邏輯and組合。通過(guò)使用fluent Java API,可以在Predicate類上使用and()、or()、negate()運(yùn)算符。
8.2 DiscoveryClient Route Definition Locator
可以將網(wǎng)關(guān)配置為基于使用兼容DiscoveryClient注冊(cè)中心注冊(cè)的服務(wù)來(lái)創(chuàng)建路由。
要啟用此功能,請(qǐng)?jiān)O(shè)置spring.cloud.gateway.discovery.locator.enabled=true,并確保DiscoveryClient實(shí)現(xiàn)位于classpath上并已啟用(如netflix eureka、consul或zookeeper)。
8.2.1 Configuring Predicates and Filters For DiscoveryClient Routes
默認(rèn)情況下,網(wǎng)關(guān)為通過(guò)DiscoveryClient創(chuàng)建的路由定義單個(gè)斷言和過(guò)濾器。
默認(rèn)斷言是使用/serviceId/**定義的path斷言,其中serviceId是DiscoveryClient中服務(wù)的ID。
默認(rèn)過(guò)濾器是使用正則表達(dá)式/serviceId/(?<remaining>.*)和替換的/${remaining}進(jìn)行重寫(xiě)。這只是在請(qǐng)求被發(fā)送到下游之前從路徑中截取掉 service id 。
可以通過(guò)設(shè)置spring.cloud.gateway.discovery.locator.predicates[x]andspring.cloud.gateway.discovery.locator.filters[y]來(lái)實(shí)現(xiàn)自定義DiscoveryClient路由使用的斷言and/or過(guò)濾器。當(dāng)你這樣做時(shí),如果你想要保留這個(gè)功能,你需要確保包括上面的默認(rèn)斷言和過(guò)濾器。下面是這樣一個(gè)例子。
application.properties.
spring.cloud.gateway.discovery.locator.predicates[0].name:Pathspring.cloud.gateway.discovery.locator.predicates[0].args[pattern]:"'/'+serviceId+'/**'"spring.cloud.gateway.discovery.locator.predicates[1].name:Hostspring.cloud.gateway.discovery.locator.predicates[1].args[pattern]:"'**.foo.com'"spring.cloud.gateway.discovery.locator.filters[0].name:Hystrixspring.cloud.gateway.discovery.locator.filters[0].args[name]:serviceIdspring.cloud.gateway.discovery.locator.filters[1].name:RewritePathspring.cloud.gateway.discovery.locator.filters[1].args[regexp]:"'/' + serviceId + '/(?<remaining>.*)'"spring.cloud.gateway.discovery.locator.filters[1].args[replacement]:"'/${remaining}'"
9. Reactor Netty Access Logs
設(shè)置-Dreactor.netty.http.server.accessLogEnabled=true來(lái)開(kāi)啟Reactor Netty access logs,注意必須是Java System Property而不是Spring Boot property。
logging 模塊也可以通過(guò)配置單獨(dú)輸出一個(gè)access log文件,下面是logback的配置例子:
logback.xml.
<appender name="accessLog"class="ch.qos.logback.core.FileAppender"><file>access_log.log</file><encoder><pattern>%msg%n</pattern></encoder></appender><appender name="async"class="ch.qos.logback.classic.AsyncAppender"><appender-ref ref="accessLog"/></appender><logger name="reactor.netty.http.server.AccessLog"level="INFO"additivity="false"><appender-ref ref="async"/></logger>
10. CORS Configuration
我們可以通過(guò)配置網(wǎng)關(guān)來(lái)控制CORS行為,全局CORS配置是Spring FrameworkCorsConfiguration模式的URL MAP。
application.yml.
spring:cloud:gateway:globalcors:corsConfigurations:'[/**]':allowedOrigins:"http://docs.spring.io"allowedMethods:-GET
例子中將允許從docs.spring.io發(fā)出的所有GET請(qǐng)求進(jìn)行CORS請(qǐng)求。
11. Actuator API
/gateway的actuator端點(diǎn)允許監(jiān)視Spring Cloud Gateway應(yīng)用程序并與之交互。要進(jìn)行遠(yuǎn)程訪問(wèn),必須在應(yīng)用程序?qū)傩灾斜┞禜TTP或JMX 端口。
application.properties.
management.endpoint.gateway.enabled=true#defaultvaluemanagement.endpoints.web.exposure.include=gateway
11.1 Retrieving route filters
11.1.1 Global Filters
要檢索應(yīng)用于所有路由的 [global filters],請(qǐng)get請(qǐng)求/actuator/gateway/globalfilters。返回的結(jié)果類似于以下內(nèi)容:
{"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}
返回結(jié)果包含已就緒的global filters的詳細(xì)信息(如org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@77856cc5)。對(duì)于每個(gè)global filters,返回結(jié)果字符串對(duì)應(yīng)過(guò)濾器鏈中的相應(yīng)順序。
11.1.2 Route Filters
要檢索應(yīng)用于路由的 [GatewayFilter factories] ,請(qǐng)get請(qǐng)求/actuator/gateway/routefilters。返回結(jié)果類似于以下內(nèi)容:
{"[AddRequestHeaderGatewayFilterFactory@570ed9c configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]":null,"[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]":null,"[SaveSessionGatewayFilterFactory@4449b273 configClass = Object]":null}
返回結(jié)果包含應(yīng)用于所有路由的GatewayFilter的詳細(xì)信息。顯示每個(gè)工廠提供字符串格式的相應(yīng)對(duì)象(例如,[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object])。請(qǐng)注意,null值是由于endpoint controller實(shí)現(xiàn)不完整造成的,因?yàn)樗鼑L試在filter chain中設(shè)置對(duì)象的順序,這不適用于GatewayFilter工廠對(duì)象。
11.2 Refreshing the route cache
如果要清理路由的緩存,請(qǐng)POST請(qǐng)求/actuator/gateway/refresh。該請(qǐng)求將返回一個(gè)沒(méi)有body的200返回碼。
11.3 Retrieving the routes defined in the gateway
要檢索網(wǎng)關(guān)中定義的路由,發(fā)送GET請(qǐng)求/actuator/gateway/routes,返回結(jié)果如下所示:
[{"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}]
返回結(jié)果中包含網(wǎng)關(guān)中所有定義的路由信息,下面表格中描述了返回結(jié)果信息:
image.png
11.4 Retrieving information about a particular route
要獲取單個(gè)路由的信息,發(fā)送GET請(qǐng)求/actuator/gateway/routes/{id}(如:/actuator/gateway/routes/first_route),返回結(jié)果如下所示:
{"id":"first_route","predicates":[{"name":"Path","args":{"_genkey_0":"/first"}}],"filters":[],"uri":"http://www.uri-destination.org","order":0}]
下面表格中描述了返回結(jié)果信息:
image.png
11.5 Creating and deleting a particular route
要?jiǎng)?chuàng)建一個(gè)路由,發(fā)送POST請(qǐng)求/gateway/routes/{id_route_to_create},參數(shù)為JSON結(jié)構(gòu),具體參數(shù)數(shù)據(jù)結(jié)構(gòu)參考上面章節(jié)。
要?jiǎng)h除一個(gè)路由,發(fā)送DELETE請(qǐng)求/gateway/routes/{id_route_to_delete}。
11.6 Recap: list of all endpoints
下表總結(jié)了Spring Cloud Gateway actuator endpoints。注意,每個(gè)endpoint都是/actuator/gateway作為基本路徑。
image.png
12. Developer Guide
TODO: overview of writing custom integrations
12.1 Writing Custom Route Predicate Factories
TODO: document writing Custom Route Predicate Factories
12.2 Writing Custom GatewayFilter Factories
如果要自定義一個(gè)GatewayFilter,需要實(shí)現(xiàn)GatewayFilterFactory。下面是一個(gè)你需要集成的抽象類AbstractGatewayFilterFactory。
PreGatewayFilterFactory.java.
publicclassPreGatewayFilterFactoryextendsAbstractGatewayFilterFactory<PreGatewayFilterFactory.Config>{publicPreGatewayFilterFactory(){super(Config.class);}@OverridepublicGatewayFilterapply(Config config){// grab configuration from Config objectreturn(exchange,chain)->{//If you want to build a "pre" filter you need to manipulate the//request before calling chain.filterServerHttpRequest.Builder builder=exchange.getRequest().mutate();//use builder to manipulate the requestreturnchain.filter(exchange.mutate().request(request).build());};}publicstaticclassConfig{//Put the configuration properties for your filter here}}
PostGatewayFilterFactory.java.
publicclassPostGatewayFilterFactoryextendsAbstractGatewayFilterFactory<PostGatewayFilterFactory.Config>{publicPostGatewayFilterFactory(){super(Config.class);}@OverridepublicGatewayFilterapply(Config config){// grab configuration from Config objectreturn(exchange,chain)->{returnchain.filter(exchange).then(Mono.fromRunnable(()->{ServerHttpResponse response=exchange.getResponse();//Manipulate the response in some way}));};}publicstaticclassConfig{//Put the configuration properties for your filter here}}
12.3 Writing Custom Global Filters
TODO: document writing Custom Global Filters
12.4 Writing Custom Route Locators and Writers
TODO: document writing Custom Route Locators and Writers