spring cloud gateway系列教程2——Gatew
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的案例和使用,可以点击查看