spring cloud gateway系列教程目錄
- spring cloud gateway系列教程1—Route Predicate
- spring cloud gateway系列教程2——GatewayFilter_上篇
- spring cloud gateway系列教程2——GatewayFilter_下篇
- spring cloud gateway系列教程3—Global Filters
- spring cloud gateway系列教程4—其他配置
接上篇
8. RequestRateLimiter GatewayFilter Factory
RequestRateLimiter GatewayFilter Factory使用RateLimiter
來決定當前請求是否允許通過,如果不允許,則默認返回狀態碼HTTP 429 - Too Many Requests
。
RequestRateLimiter GatewayFilter可以使用一個可選參數keyResolver
來做速率限制。
keyResolver
是KeyResolver
接口的一個實現bean,在配置里面,通過SpEL表達式#{@myKeyResolver}
來管理bean的名字myKeyResolver
。
KeyResolver.java.
public interface KeyResolver {
Mono<String> resolve(ServerWebExchange exchange);
}
KeyResolver
接口允許你使用不同的策略來得出限制請求的key,未來,官方也會推出一些KeyResolver
的不同實現。
KeyResolver
默認實現是PrincipalNameKeyResolver
,通過ServerWebExchange
中獲取Principal
,并以Principal.getName()
作為限流的key。
如果KeyResolver
拿不到key,請求默認都會被限制,你也可以自己配置spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key
:是否允許空key,spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code
:空key時返回的狀態碼。
RequestRateLimiter不支持捷徑配置,如下面的配置是非法的
application.properties.
# INVALID SHORTCUT CONFIGURATION
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}
8.1 Redis RateLimiter
基于 Stripe的redis實現方案,依賴spring-boot-starter-data-redis-reactive
Spring Boot starter,使用的是令牌桶算法。
redis-rate-limiter.replenishRate
配置的是每秒允許通過的請求數,其實就是令牌桶的填充速率。
redis-rate-limiter.burstCapacity
配置的是一秒內最大的請求數,其實就是令牌桶的最大容量,如果設置為0,則會阻塞所有請求。
所以可以通過設置相同的replenishRate
和burstCapacity
來實現勻速的速率控制,通過設置burstCapacity
大于replenishRate
來允許系統流量瞬間突發,但是對于這種情況,突發周期為burstCapacity / replenishRate
秒,如果周期內有兩次請求突發的情況,則第二次會有部分請求丟失,返回HTTP 429 - Too Many Requests
。
application.yml.
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: http://www.google.com
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
定義了通過請求獲取請求參數user
作為key。
你也可以實現RateLimiter
接口自定義自己的請求速率限制器,在配置文件中使用SpEL表達式配置對應的bean的名字即可。
application.yml.
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: http://www.google.com
filters:
- name: RequestRateLimiter
args:
rate-limiter: "#{@myRateLimiter}"
key-resolver: "#{@userKeyResolver}"
9. RedirectTo GatewayFilter Factory
RedirectTo GatewayFilter Factory使用status
和url
兩個參數,其中status
必須是300系列的HTTP狀態碼,url
則是跳轉的地址,會放在響應的Location
的header中(http協議中轉跳的header)。
application.yml.
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: http://www.google.cn
filters:
- RedirectTo=302, http://www.edjdhbb.com
上面路由會執行302重定向到http://www.edjdhbb.com。
10. RemoveNonProxyHeaders GatewayFilter Factory
RemoveNonProxyHeaders GatewayFilter Factory轉發請求是會根據IETF的定義,默認會移除下列的http頭信息:
- Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- TE
- Trailer
- Transfer-Encoding
- Upgrade
你也可以通過配置spring.cloud.gateway.filter.remove-non-proxy-headers.headers
來更改需要移除的header列表。
11. RemoveRequestHeader GatewayFilter Factory
RemoveRequestHeader GatewayFilter Factory配置header的name,即可以移除請求的header。
application.yml.
spring:
cloud:
gateway:
routes:
- id: removerequestheader_route
uri: http://www.google.com
filters:
- RemoveRequestHeader=X-Request-Foo
上面路由在發送請求給下游時,會將請求中的X-Request-Foo
頭信息去掉。
12. RemoveResponseHeader GatewayFilter Factory
RemoveResponseHeader GatewayFilter Factory通過配置header的name,會在響應返回時移除header。
application.yml.
spring:
cloud:
gateway:
routes:
- id: removeresponseheader_route
uri: http://www.google.com
filters:
- RemoveResponseHeader=X-Response-Foo
上面路由會在響應返回給gateway的客戶端時,將X-Response-Foo
響應頭信息去掉。
13. RewritePath GatewayFilter Factory
RewritePath GatewayFilter Factory使用路徑regexp
和替換路徑replacement
兩個參數做路徑重寫,兩個都可以靈活地使用java的正則表達式。
application.yml.
spring:
cloud:
gateway:
routes:
- id: rewritepath_route
uri: http://www.google.com
predicates:
- Path=/foo/**
filters:
- RewritePath=/foo/(?<segment>.*), /$\{segment}
對于上面的例子,如果請求的路徑是/foo/bar
,則gateway會將請求路徑改為/bar
發送給下游。
注:在YAML 的格式中使用
$\
來代替$
。
14. RewriteResponseHeader GatewayFilter Factory
RewriteResponseHeader GatewayFilter Factory的作用是修改響應返回的header內容,需要配置響應返回的header的name
,匹配規則regexp
和替換詞replacement
,也是支持java的正則表達式。
application.yml.
spring:
cloud:
gateway:
routes:
- id: rewriteresponseheader_route
uri: http://www.google.com
filters:
- RewriteResponseHeader=X-Response-Foo, , password=[^&]+, password=***
舉個例子,對于上面的filter,如果響應的headerX-Response-Foo
的內容是/42?user=ford&password=omg!what&flag=true
,這個內容會修改為/42?user=ford&password=***&flag=true
。
15. SaveSession GatewayFilter Factory
SaveSession GatewayFilter Factory會在請求下游時強制執行WebSession::save
方法,用在那種像Spring Session
延遲數據存儲的,并在請求轉發前確保session狀態保存情況。
application.yml.
spring:
cloud:
gateway:
routes:
- id: save_session
uri: http://www.google.com
predicates:
- Path=/foo/**
filters:
- SaveSession
如果你將Spring Secutiry
于Spring Session
集成使用,并想確保安全信息都傳到下游機器,你就需要配置這個filter。
16. SecureHeaders GatewayFilter Factory
SecureHeaders GatewayFilter Factory會添加在返回響應中一系列安全作用的header,至于為什么,英文好的可以看一下這篇博客。
默認會添加這些頭信息和默認內容:
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
上面的header對應的后綴:
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.xss-protection-header
17. SetPath GatewayFilter Factory
SetPath GatewayFilter Factory采用路徑template
參數,通過請求路徑的片段的模板化,來達到操作修改路徑的母的,運行多個路徑片段模板化。
application.yml.
spring:
cloud:
gateway:
routes:
- id: setpath_route
uri: http://www.google.com
predicates:
- Path=/foo/{segment}
filters:
- SetPath=/{segment}
對于上面的例子,如果路徑是/foo/bar
,則對于下游的請求路徑會修改為/bar
。
18. SetResponseHeader GatewayFilter Factory
SetResponseHeader GatewayFilter Factory通過設置name
和value
來替換響應對于的header。
application.yml.
spring:
cloud:
gateway:
routes:
- id: setresponseheader_route
uri: http://www.google.com
filters:
- SetResponseHeader=X-Response-Foo, Bar
對于上面的例子,如果下游的返回帶有頭信息為X-Response-Foo:1234
,則會gateway會替換為X-Response-Foo:Bar
,在返回給客戶端。
19. SetStatus GatewayFilter Factory
SetStatus GatewayFilter Factory通過配置有效的Spring HttpStatus
枚舉參數,可以是類似于404的這些數字,也可以是枚舉的name字符串,來修改響應的返回碼。
application.yml.
spring:
cloud:
gateway:
routes:
- id: setstatusstring_route
uri: http://www.google.com
filters:
- SetStatus=BAD_REQUEST
- id: setstatusint_route
uri: http://www.google.com
filters:
- SetStatus=401
上面例子中,兩種路由都會將響應的狀態碼設置為401。
20. StripPrefix GatewayFilter Factory
StripPrefix GatewayFilter Factory通過配置parts
來表示截斷路徑前綴的數量。
application.yml.
spring:
cloud:
gateway:
routes:
- id: nameRoot
uri: http://nameservice
predicates:
- Path=/name/**
filters:
- StripPrefix=2
如上面例子中,如果請求的路徑為/name/bar/foo
,則路徑會修改為/foo
,即將路徑的兩個前綴去掉了。
21. Retry GatewayFilter Factory
Retry GatewayFilter Factory可以配置針對不同的響應做請求重試,可以配置如下參數:
-
retries
: 重試次數 -
statuses
: 需要重試的狀態碼,需要根據枚舉org.springframework.http.HttpStatus
來配置 -
methods
: 需要重試的請求方法,需要根據枚舉org.springframework.http.HttpMethod
來配置 -
series
: HTTP狀態碼系列,詳情見枚舉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
上面例子,當下游服務返回502狀態碼時,gateway會重試3次。
22. RequestSize GatewayFilter Factory
RequestSize GatewayFilter Factory會限制客戶端請求包的大小,通過參數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
如果請求大小超過5000kb限制,則會返回狀態碼413 Payload Too Large
。
如果不設置這個filter,默認限制5M的請求大小。
23. Modify Request Body GatewayFilter Factory
官方說這個filter目前只是beta版本,API以后可能會修改。
Modify Request Body GatewayFilter Factory可以修改請求體內容,這個只能通過java來配置。
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.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) -> return Mono.just(new Hello(s.toUpperCase())))).uri(uri))
.build();
}
static class Hello {
String message;
public Hello() { }
public Hello(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
24. Modify Response Body GatewayFilter Factory
官方說這個filter目前只是beta版本,API以后可能會修改。
Modify Response Body GatewayFilter Factory用于修改響應返回的內容,同樣只能通過java配置。
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.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();
}
這一章接著上一章介紹了Spring Cloud Gateway官方的Gateway Filter使用場景,下一章講Global Filters的使用。
如果想查看其他spring cloud gateway的案例和使用,可以點擊查看