1.依赖引入
maven依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
yml
spring:
application:
name: gateway
cloud:
gateway:
enabled: true
routes:
- id: data
uri: http://localhost:8000
predicates:
- Path=/deptService/**
filters:
- StripPrefix=1
server:
port: 9999
yml(整合nacos)
spring:
application:
name: gateway
cloud:
gateway:
enabled: true
routes:
- id: data
uri: lb://dataProvider8000
predicates:
- Path=/deptService/**
filters:
- StripPrefix=1
server:
port: 9999
2.依赖冲突
spring自家的gateway基于非响应式,与MVC、spring-web、tomcat等冲突,gateway模块需要排除(exclude)上述依赖或选择flux等。
3.重要名词解释
Route 路由:gateway的基本构建模块。它由ID、目标URI、断言集合和过滤器集合组成。如果聚合断言结果为真,则匹配到该路由。
Predicate 断言:这是一个Java 8 Function Predicate。输入类型是 Spring Framework ServerWebExchange
。这允许开发人员可以匹配来自HTTP请求的任何内容,例如Header或参数。
Filter 过滤器:这些是使用特定工厂构建的 Spring FrameworkGatewayFilter
实例。所以可以在返回请求之前或之后修改请求和响应的内容。
4. RoutePredicateFactories
Spring Cloud Gateway将路由作为Spring WebFlux HandlerMapping
基础结构的一部分进行匹配。Spring Cloud Gateway包含许多内置的RoutePredicateFactoriesFactories。这些断言都匹配HTTP请求的不同属性。多个RoutePredicateFactoriesFactories可以通过 and
组合使用。
4.1 After RoutePredicateFactories Factory
After Route Predicate Factory采用一个参数——日期时间。在该日期时间之后发生的请求都将被匹配。
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 RoutePredicateFactories Factory
Before Route Predicate Factory采用一个参数——日期时间。在该日期时间之前发生的请求都将被匹配。
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 RoutePredicateFactories Factory
Between RoutePredicateFactories Factory有两个参数,datetime1和datetime2。在datetime1和datetime2之间的请求将被匹配。datetime2参数的实际时间必须在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 RoutePredicateFactories Factory
Cookie RoutePredicateFactories Factory有两个参数,cookie名称和正则表达式。请求包含次cookie名称且正则表达式为真的将会被匹配。
application.yml
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: http://example.org
predicates:
- Cookie=chocolate, ch.p
4.5 Header RoutePredicateFactories Factory
Header RoutePredicateFactories Factory有两个参数,header名称和正则表达式。请求包含次header名称且正则表达式为真的将会被匹配。
application.yml.
spring:
cloud:
gateway:
routes:
- id: header_route
uri: http://example.org
predicates:
- Header=X-Request-Id, \d+
4.6 Host RoutePredicateFactories Factory
Host RoutePredicateFactories Factory包括一个参数:host name列表。使用Ant路径匹配规则,.
作为分隔符。
application.yml.
spring:
cloud:
gateway:
routes:
- id: host_route
uri: http://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org
4.7 Method RoutePredicateFactories Factory
Method RoutePredicateFactories Factory只包含一个参数: 需要匹配的HTTP请求方式
application.yml.
spring:
cloud:
gateway:
routes:
- id: method_route
uri: http://example.org
predicates:
- Method=GET
所有GET请求都将被路由
4.8 Path RoutePredicateFactories Factory
Path RoutePredicateFactories Factory 有2个参数: 一个Spring PathMatcher
表达式列表和可选matchOptionalTrailingSeparator
标识 .
application.yml.
spring:
cloud:
gateway:
routes:
- id: host_route
uri: http://example.org
predicates:
- Path=/foo/{segment},/bar/{segment}
例如: /foo/1
or /foo/bar
or /bar/baz
的请求都将被匹配
URI 模板变量 (如上例中的 segment
) 将以Map的方式保存于ServerWebExchange.getAttributes()
key为ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE
. 这些值将在GatewayFilter Factories使用
可以使用以下方法来更方便地访问这些变量。
Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
String segment = uriVariables.get("segment");
4.9 Query RoutePredicateFactories Factory
Query RoutePredicateFactories Factory 有2个参数: 必选项 param
和可选项 regexp
.
application.yml.
spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://example.org
predicates:
- Query=baz
则包含了请求参数 baz
的都将被匹配。
application.yml.
spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://example.org
predicates:
- Query=foo, ba.
如果请求参数里包含foo
参数,并且值匹配为ba.
表达式,则将会被路由,如:bar
and baz
4.10 RemoteAddr RoutePredicateFactories Factory
RemoteAddr RoutePredicateFactories Factory的参数为 一个CIDR符号(IPv4或IPv6)字符串的列表,最小值为1,例如192.168.0.1/16(其中192.168.0.1是IP地址并且16是子网掩码)。
application.yml.
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: http://example.org
predicates:
- RemoteAddr=192.168.1.1/24
如果请求的remote address 为 192.168.1.10
则将被路由
4.10.1 修改远程地址的解析方式
默认情况下,RemoteAddr RoutePredicateFactories Factory使用传入请求中的remote address。如果Spring Cloud Gateway位于代理层后面,则可能与实际客户端IP地址不匹配。
可以通过设置自定义RemoteAddressResolver
来自定义解析远程地址的方式。Spring Cloud Gateway网关附带一个非默认远程地址解析程序,它基于X-Forwarded-For header, XForwardedRemoteAddressResolver
.
XForwardedRemoteAddressResolver
有两个静态构造函数方法,采用不同的安全方法:
XForwardedRemoteAddressResolver::TrustAll
返回一个RemoteAddressResolver
,它始终采用X-Forwarded-for
头中找到的第一个IP地址。这种方法容易受到欺骗,因为恶意客户端可能会为解析程序接受的“x-forwarded-for”设置初始值。XForwardedRemoteAddressResolver::MaxTrustedIndex
获取一个索引,该索引与在Spring Cloud网关前运行的受信任基础设施数量相关。例如,如果SpringCloudGateway只能通过haproxy访问,则应使用值1。如果在访问Spring Cloud Gateway之前需要两个受信任的基础架构跃点,那么应该使用2。
给定以下的header值:
X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3
下面的` maxTrustedIndex值将生成以下远程地址:
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")
)
4.11权重路径断言Factory
Weight
RoutePredicateFactoriesFactory接受两个参数:group
和weight
(一个 INT)。权重是按组计算的。下面的示例配置了权重路由谓词:
示例 12.application.yml
spring:
cloud:
gateway:
routes:
- id: weight_high
uri: https://weighthigh.org
predicates:
- Weight=group1, 8
- id: weight_low
uri: https://weightlow.org
predicates:
- Weight=group1, 2
此路由将把 80% 的流量转发给weighthigh.org (opens new window),并将 20% 的流量转发给weighlow.org (opens new window)
5. GatewayFilter Factories
过滤器允许以某种方式修改传入的HTTP请求或返回的HTTP响应。过滤器的作用域是某些特定路由。Spring Cloud Gateway包括许多内置的 Filter工厂。
注意:有关如何使用以下任何过滤器的更详细示例,请查看unit tests.。
5.0全局过滤器(自定义)
下面是一个模拟日志记录的例程
package com.tony.cloudgateway.config;
import cn.hutool.core.date.DateUtil;
import lombok.extern.log4j.Log4j2;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Log4j2
@Component
public class GatewayLogFilter implements GlobalFilter, Ordered {
private static final String BEGIN_TIME = "beginTime";
@Override
public Mono<Void> filter(final ServerWebExchange exchange, GatewayFilterChain chain) {
exchange.getAttributes().put(BEGIN_TIME, DateUtil.current());
return chain.filter(exchange).then(
Mono.fromRunnable(() -> {
Long startTime = exchange.getAttribute(BEGIN_TIME);
if (startTime != null) {
log.info("=============================Gateway打印日志开始===============================");
log.info("访问接口host: " + exchange.getRequest().getURI().getHost());
log.info("访问接口端口: " + exchange.getRequest().getURI().getPort());
log.info("访问接口URL: " + exchange.getRequest().getURI().getPath());
log.info("访问接口URL参数: " + exchange.getRequest().getURI().getRawQuery());
log.info("访问接口时间: " + (DateUtil.current() - startTime) + "ms");
log.info("=============================Gateway打印日志结束===============================");
}
})
);
}
@Override
public int getOrder() {
return -10000;
}
}
5.1 AddRequestHeader GatewayFilter Factory
采用一对名称和值作为参数
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
header
5.2 AddRequestParameter GatewayFilter Factory
采用一对名称和值作为参数
application.yml.
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: http://example.org
filters:
- AddRequestParameter=foo, bar
对于所有匹配的请求,这将向下游请求添加foo=bar
查询字符串
5.3 AddResponseHeader GatewayFilter Factory
采用一对名称和值作为参数
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
头添加到下游响应的header中
5.4 Hystrix GatewayFilter Factory
Hystrix 是Netflix开源的断路器组件。Hystrix GatewayFilter允许你向网关路由引入断路器,保护你的服务不受级联故障的影响,并允许你在下游故障时提供fallback响应。
要在项目中启用Hystrix网关过滤器,需要添加对 spring-cloud-starter-netflix-hystrix
的依赖 Spring Cloud Netflix.
Hystrix GatewayFilter Factory 需要一个name参数,即HystrixCommand
的名称。
application.yml.
spring:
cloud:
gateway:
routes:
- id: hystrix_route
uri: http://example.org
filters:
- Hystrix=myCommandName
这将剩余的过滤器包装在命令名为“myCommandName”的HystrixCommand
中。
hystrix过滤器还可以接受可选的fallbackUri
参数。目前,仅支持forward:
预设的URI,如果调用fallback,则请求将转发到与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 fallback时,这将转发到/incaseoffailureusethis
uri。注意,这个示例还演示了(可选)通过目标URI上的’lb`前缀,使用Spring Cloud Netflix Ribbon 客户端负载均衡。
主要场景是使用fallbackUri
到网关应用程序中的内部控制器或处理程序。但是,也可以将请求重新路由到外部应用程序中的控制器或处理程序,如:
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应用程序中没有 fallback
实现,但是另一个应用程序中有一个接口实现,注册为“http://localhost:9994”。
在将请求转发到fallback的情况下,Hystrix Gateway过滤还支持直接抛出Throwable
。它被作为ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR
属性添加到ServerWebExchange
中,可以在处理网关应用程序中的fallback时使用。
对于外部控制器/处理程序方案,可以添加带有异常详细信息的header。可以在 FallbackHeaders GatewayFilter Factory section.中找到有关它的更多信息。
hystrix配置参数(如 timeouts)可以使用全局默认值配置,也可以使用Hystrix wiki中所述属性进行配置。
要为上面的示例路由设置5秒超时,将使用以下配置:
application.yml.
hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000
5.5 FallbackHeaders GatewayFilter Factory
FallbackHeaders
允许在转发到外部应用程序中的FallbackUri
的请求的header中添加Hystrix异常详细信息,如下所示:
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
在本例中,在运行HystrixCommand
发生执行异常后,请求将被转发到 localhost:9994
应用程序中的 fallback
终端或程序。异常类型、消息(如果可用)cause exception类型和消息的头,将由FallbackHeaders
filter添加到该请求中。
通过设置下面列出的参数值及其默认值,可以在配置中覆盖headers的名称:
executionExceptionTypeHeaderName
("Execution-Exception-Type"
)executionExceptionMessageHeaderName
("Execution-Exception-Message"
)rootCauseExceptionTypeHeaderName
("Root-Cause-Exception-Type"
)rootCauseExceptionMessageHeaderName
("Root-Cause-Exception-Message"
)
Hystrix 如何实现的更多细节可以参考 Hystrix GatewayFilter Factory section.
5.6 PrefixPath GatewayFilter Factory
PrefixPath GatewayFilter 只有一个 prefix
参数.
application.yml.
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: http://example.org
filters:
- PrefixPath=/mypath
这将给所有匹配请求的路径加前缀/mypath
。因此,向/hello
发送的请求将发送到/mypath/hello
。
5.7 PreserveHostHeader GatewayFilter Factory
该filter没有参数。设置了该Filter后,GatewayFilter将不使用由HTTP客户端确定的host header ,而是发送原始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
实现是否允许继续执行当前请求。如果不允许继续执行,则返回HTTP 429 - Too Many Requests
(默认情况下)。
这个过滤器可以配置一个可选的keyResolver
参数和rate limiter参数(见下文)。
keyResolver
是 KeyResolver
接口的实现类.在配置中,按名称使用SpEL引用bean。#{@myKeyResolver}
是引用名为’myKeyResolver’的bean的SpEL表达式。
KeyResolver.java.
public interface KeyResolver {
Mono<String> resolve(ServerWebExchange exchange);
}
KeyResolver
接口允许使用可插拔策略来派生限制请求的key。在未来的里程碑版本中,将有一些KeyResolver
实现。
KeyResolver
的默认实现是PrincipalNameKeyResolver
,它从ServerWebExchange
检索Principal
并调用Principal.getName()
。
默认情况下,如果KeyResolver
没有获取到key,请求将被拒绝。此行为可以使用 spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key
(true or false) 和 spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code
属性进行调整。
说明
无法通过"shortcut" 配置RequestRateLimiter。以下示例无效
application.properties.
# INVALID SHORTCUT CONFIGURATION
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}
5.8.1 Redis RateLimiter
Redis的实现基于 Stripe实现。它需要使用 spring-boot-starter-data-redis-reactive
Spring Boot starter。
使用的算法是Token Bucket Algorithm.。
redis-rate-limiter.replenishRate
是你允许用户每秒执行多少请求,而丢弃任何请求。这是令牌桶的填充速率。
``redis-rate-limiter.burstCapacity`是允许用户在一秒钟内执行的最大请求数。这是令牌桶可以保存的令牌数。将此值设置为零将阻止所有请求。
稳定速率是通过在replenishRate
和 burstCapacity
中设置相同的值来实现的。可通过设置burstCapacity
高于replenishRate
来允许临时突发流浪。在这种情况下,限流器需要在两次突发之间留出一段时间(根据replenishRate
),因为连续两次突发将导致请求丢失 (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
是一个简单的获取user
请求参数的工具(注意:不建议用于生产)。
限流器也可以定义为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}"
5.9 RedirectTo GatewayFilter Factory
该过滤器有一个 status
和一个 url
参数。status是300类重定向HTTP代码,如301。该URL应为有效的URL,这将是 Location
header的值。
application.yml.
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: http://example.org
filters:
- RedirectTo=302, http://acme.org
这将发送一个302状态码和一个Location:http://acme.org
header来执行重定向。
5.10 RemoveNonProxyHeaders GatewayFilter Factory
RemoveNonProxyHeaders GatewayFilter Factory 从转发请求中删除headers。删除的默认头列表来自 IETF.
The default removed headers are:
- Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- TE
- Trailer
- Transfer-Encoding
- Upgrade
要更改此设置,请将spring.cloud.gateway.filter.remove-non-proxy-headers.headers
属性设置为要删除的header名称。
5.11 RemoveRequestHeader GatewayFilter Factory
有一个name
参数. 这是要删除的header的名称。
application.yml.
spring:
cloud:
gateway:
routes:
- id: removerequestheader_route
uri: http://example.org
filters:
- RemoveRequestHeader=X-Request-Foo
这将在X-Request-Foo
header被发送到下游之前删除它。
5.12 RemoveResponseHeader GatewayFilter Factory
有一个name
参数. 这是要删除的header的名称。
application.yml.
spring:
cloud:
gateway:
routes:
- id: removeresponseheader_route
uri: http://example.org
filters:
- RemoveResponseHeader=X-Response-Foo
这将在返回到网关client之前从响应中删除x-response-foo
头。
5.13 RewritePath GatewayFilter Factory
包含一个 regexp
正则表达式参数和一个 replacement
参数. 通过使用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规范,请使用 $\
替换 $
。
5.14 RewriteResponseHeader GatewayFilter Factory
包含 name
, regexp
和 replacement
参数.。通过使用Java正则表达式灵活地重写响应头的值。
application.yml.
spring:
cloud:
gateway:
routes:
- id: rewriteresponseheader_route
uri: http://example.org
filters:
- RewriteResponseHeader=X-Response-Foo, , password=[^&]+, password=***
对于一个/42?user=ford&password=omg!what&flag=true
的header值,在做下游请求时将被设置为/42?user=ford&password=***&flag=true
,由于YAML规范,请使用 $\
替换 $
。
5.15 SaveSession GatewayFilter Factory
SaveSession GatewayFilter Factory将调用转发到下游之前强制执行WebSession::save
操作。这在使用 Spring Session 之类时特别有用,需要确保会话状态在进行转发调用之前已保存。
application.yml.
spring:
cloud:
gateway:
routes:
- id: save_session
uri: http://example.org
predicates:
- Path=/foo/**
filters:
- SaveSession
如果你希望要将[Spring Security](https://projects.spring.io/Spring Security/)与Spring Session集成,并确保安全详细信息已转发到远程的进程,这一点至关重要。
5.16 SecureHeaders GatewayFilter Factory
SecureHeaders GatewayFilter Factory 将许多headers添加到reccomedation处的响应中,从this blog post.
添加以下标题(使用默认值分配):
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 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
路径参数。它提供了一种通过允许路径的模板化segments来操作请求路径的简单方法。使用Spring Framework中的URI模板,允许多个匹配segments。
application.yml.
spring:
cloud:
gateway:
routes:
- id: setpath_route
uri: http://example.org
predicates:
- Path=/foo/{segment}
filters:
- SetPath=/{segment}
对于一个 /foo/bar
请求,在做下游请求前,路径将被设置为/bar
5.18 SetResponseHeader GatewayFilter Factory
SetResponseHeader GatewayFilter Factory 包括 name
和 value
参数.
application.yml.
spring:
cloud:
gateway:
routes:
- id: setresponseheader_route
uri: http://example.org
filters:
- SetResponseHeader=X-Response-Foo, Bar
此GatewayFilter使用给定的名称替换所有header,而不是添加。因此,如果下游服务器响应为X-Response-Foo:1234
,则会将其替换为X-Response-Foo:Bar
,这是网关客户端将接收的内容。
5.19 SetStatus GatewayFilter Factory
SetStatus GatewayFilter Factory 包括唯一的 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.
5.20 StripPrefix GatewayFilter Factory
StripPrefix GatewayFilter Factory 包括一个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
。
5.21 Retry GatewayFilter Factory
Retry GatewayFilter Factory包括 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
注意
retry filter 不支持body请求的重试,如通过body的POST 或 PUT请求
注意
在使用带有前缀为forward:
的retry filter
时,应仔细编写目标端点,以便在出现错误时不会执行任何可能导致将响应发送到客户端并提交的操作。例如,如果目标端点是带注解的controller,则目标controller方法不应返回带有错误状态代码的ResponseEntity
。相反,它应该抛出一个Exception
,或者发出一个错误信号,例如通过Mono.error(ex)
返回值,重试过滤器可以配置为通过重试来处理。
5.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
当请求因大小而被拒绝时, RequestSize GatewayFilter Factory 将响应状态设置为413 Payload Too Large
,并带有额外的header errorMessage
。下面是一个 errorMessage
的例子。
errorMessage` : `Request size is larger than permissible limit. Request size is 6.0 MB where permissible limit is 5.0 MB
注意
如果未在路由定义中作为filter参数提供,则默认请求大小将设置为5 MB。
5.23 Modify Request Body GatewayFilter Factory
这个过滤器被定义为beta版本,将来API可能会改变。
此过滤器可用于在请求主体被网关发送到下游之前对其进行修改。
注意
只能使用Java DSL配置此过滤器
@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;
}
}
5.24 Modify Response Body GatewayFilter Factory
这个过滤器被定义为beta版本,将来API可能会改变。
此过滤器可用于在将响应正文发送回客户端之前对其进行修改。
注意
只能使用Java DSL配置此过滤器
@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();
}
6. Global Filters
GlobalFilter
接口与GatewayFilter
具有相同的签名。是有条件地应用于所有路由的特殊过滤器。(此接口和用法可能在将来的里程碑版本中发生更改)。
6.1 全局Filter和GatewayFilter组合排序
当请求进入(并与路由匹配)时,筛选Web Handler 会将GlobalFilter
的所有实例和所有的GatewayFilter
路由特定实例添加到 filter chain。filter组合的排序由org.springframework.core.Ordered
接口决定,可以通过实现getOrde()
方法或使用@Order
注释来设置。
由于Spring Cloud Gateway将用于执行过滤器逻辑区分为“前置”和“后置”阶段,具有最高优先级的过滤器将是“前置”阶段的第一个,而“后置”阶段的最后一个。
ExampleConfiguration.java.
@Bean
@Order(-1)
public GlobalFilter a() {
return (exchange, chain) -> {
log.info("first pre filter");
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("third post filter");
}));
};
}
@Bean
@Order(0)
public GlobalFilter b() {
return (exchange, chain) -> {
log.info("second pre filter");
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("second post filter");
}));
};
}
@Bean
@Order(1)
public GlobalFilter c() {
return (exchange, chain) -> {
log.info("third pre filter");
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("first post filter");
}));
};
}
6.2 Forward Routing Filter
ForwardRoutingFilter
在exchange属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
中查找URI。如果URL有一个forward
scheme (如 forward:///localendpoint
),它将使用Spring DispatcherHandler
来处理请求。请求URL的路径部分将被转发URL中的路径覆盖。未修改的原始URL将附加到 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR
属性中的列表中。
6.3 LoadBalancerClient Filter
LoadBalancerClientFilter
在exchange属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
中查找URI。如果URL有一个lb
scheme (如 lb://myservice
),它将使用Spring Cloud LoadBalancerClient
将名称(在前一个示例中为’myservice)解析为实际主机和端口,并替换URI。未修改的原始URL将附加到
ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。过滤器还将查看
ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR属性,查看它是否等于
lb`,然后应用相同的规则。
application.yml.
spring:
cloud:
gateway:
routes:
- id: myRoute
uri: lb://service
predicates:
- Path=/service/**
注意
默认情况下,如果一个服务实例在LoadBalancer
中没有发现,则返回503。可以通过设置spring.cloud.gateway.loadbalancer.use404=true
来让网管返回404.
注意
从LoadBalancer
返回的ServiceInstance
的isSecure
值将覆盖在对网关发出的请求中指定的scheme。例如,如果请求通过HTTPS
进入网关,但ServiceInstance
表示它不安全,则下游请求将通过HTTP
协议。相反的情况也适用。但是,如果在网关配置中为路由指定了GATEWAY_SCHEME_PREFIX_ATTR
,则前缀将被删除,并且路由URL生成的scheme将覆盖ServiceInstance
配置。
6.4 Netty Routing Filter
如果位于 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
属性中的URL具有http
或https
模式,则会运行Netty Routing Filter。它使用Netty HttpClient
发出下游代理请求。响应放在 ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR
exchange属性中,以便在以后的过滤器中使用。(有一个实验阶段不需要Netty的相同的功能的Filter,WebClientHttpRoutingFilter
)
6.5 Netty Write Response Filter
如果ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR
exchange属性中存在 Netty HttpClientResponse
,则运行 NettyWriteResponseFilter
。它在其他所有过滤器完成后将代理响应写回网关客户端响应之后运行。(有一个不需要netty的实验性的WebClientWriteResponseFilter
执行相同的功能)
6.6 RouteToRequestUrl Filter
如果ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR
exchange属性中存在Route
对象,RouteToRequestUrlFilter
将运行。它基于请求URI创建一个新的URI,使用Route
对象的uri属性进行更新。新的URI被放置在ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
exchange属性中。
如果该URI有一个前缀scheme,例如lb:ws://serviceid
,则会从该URI中剥离该 lb
scheme,并将其放置在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR
中,以便稍后在过滤器链中使用。
6.7 Websocket Routing Filter
如果ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
exchange属性中有 ws
、 wss
scheme,则Websocket Routing Filter将被运行。它使用Spring Web Socket基础模块将Websocket转发到下游。
URI前缀为lb
的Websockets可以被负载均衡,如 lb:ws://serviceid
.
注意
如果使用 SockJS 作为普通HTTP的fallback,则应配置普通HTTP路由以及WebSocket路由。
application.yml.
spring:
cloud:
gateway:
routes:
# SockJS route
- id: websocket_sockjs_route
uri: http://localhost:3001
predicates:
- Path=/websocket/info/**
# Normwal Websocket route
- id: websocket_route
uri: ws://localhost:3001
predicates:
- Path=/websocket/**
6.8 Gateway Metrics Filter
要启用网关指标,请将spring-boot-starter-actuator添加为项目依赖项。然后,默认情况下,只要属性spring.cloud.gateway.metrics.enabled
未设置为false
,网关指标过滤器就会运行。此过滤器添加名为“gateway.requests”的计时器指标,并带有以下标记:
routeId
: The route idrouteUri
: API 将被转发的URIoutcome
: 结果分类依据 HttpStatus.Seriesstatus
: 返回client的请求的Http Status
这些指标可以从/actuator/metrics/gateway.requests
中获取,可以很容易地与Prometheus集成以创建Grafana dashboard.
注意
要将pometheus启用,需要添加 micrometer-registry-prometheus为项目依赖。
6.9 Making An Exchange As Routed
网关路由ServerWebExchange
之后,它将通过向Exchange属性添加gatewayAlreadyRouted
,将该exchange标记为“routed”。一旦一个请求被标记为routed,其他路由过滤器将不会再次路由该请求,将跳过该过滤器。有一些方便的方法可以用来将exchange标记为routed,或者检查exchange是否已经routed。
ServerWebExchangeUtils.isAlreadyRouted
有一个ServerWebExchange
对象并检查它是否已"routed"ServerWebExchangeUtils.setAlreadyRouted
有一个ServerWebExchange
对象并将其标记为"routed"
7.CORS 配置(cors-configuration)
你可以配置网关来控制 CORS 行为。“全局”CORS 配置是 URL 模式到[[ Spring FrameworkCorsConfiguration
](https://DOCS. Spring.io/ Spring/DOCS/5.0.x/javadoc-api/org/springframework/web/cors/corsconfiguration.html)的映射。以下示例配置 CORS:
示例 .application.yml
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]': #允许跨域访问的资源
allowedOrigins: "https://docs.spring.io" #允许跨域访问的请求来源
allowedMethods:
- GET
在前面的示例中,对于所有 GET 请求的路径,允许从源自docs.spring.io
的请求发出 CORS 请求。
要为某些网关路由谓词不处理的请求提供相同的 CORS 配置,请将spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping
属性设置为spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping
。当你试图支持 CORS 的 Preflight 请求,而你的路由谓词不求值到true
时,这是有用的,因为 HTTP 方法是options
。
用Bean的方法:
@Bean
public CorsFilter corsFilter() {
logger.debug("CORS限制打开");
CorsConfiguration config = new CorsConfiguration();
# 仅在开发环境设置为*
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
return new CorsFilter(configSource);
}