Spring Cloud Gateway
2.2.0.BUILD-快照
该项目提供了一个建立在Spring Ecosystem之上的API网关,包括:Spring 5,Spring Boot 2和Project Reactor。Spring Cloud Gateway旨在提供一种简单而有效的方式来路由到API,并为他们提供横切关注点,例如:安全性,监控/指标和弹性。
如何包含Spring Cloud Gateway
要在项目中包含Spring Cloud Gateway,请使用具有组org.springframework.cloud
和工件ID 的启动器spring-cloud-starter-gateway
。有关 使用当前Spring Cloud Release Train设置构建系统的详细信息,请参阅Spring Cloud Project页面。
如果包含启动器,但由于某种原因,您不希望启用网关,请进行设置spring.cloud.gateway.enabled=false
。
Spring Cloud Gateway基于Spring Boot 2.0, Spring WebFlux和Project Reactor 构建。因此,许多熟悉的同步库(例如Spring Data和Spring Security)和模式在使用Spring Cloud Gateway时可能不适用。如果您不熟悉这些项目,我们建议您在使用Spring Cloud Gateway之前先阅读他们的文档以熟悉一些新概念。
Spring Cloud Gateway需要Spring Boot和Spring Webflux提供的Netty运行时。它不能在传统的Servlet容器中工作或构建为WAR。
词汇表
- Route: 路由网关的基本构建块。它由ID,目标URI,谓词集合和过滤器集合定义。如果聚合谓词为真,则匹配路由。
- Predicate: 这是一个Java 8函数谓词。输入类型是Spring Framework
ServerWebExchange
。这允许开发人员匹配来自HTTP请求的任何内容,例如标头或参数。 - Filter: 这是使用特定工厂构建的Spring Framework
GatewayFilter
实例。这里,可以在发送下游请求之前或之后修改请求和响应。
运行原理
客户端向Spring Cloud Gateway发出请求。如果网关处理程序映射确定请求与路由匹配,则将其发送到网关Web处理程序。此处理程序运行通过特定于请求的过滤器链发送请求。滤波器被虚线划分的原因是滤波器可以在发送代理请求之前或之后执行逻辑。执行所有“预”过滤器逻辑,然后进行代理请求。在发出代理请求之后,执行“post”过滤器逻辑。
在没有端口的路由中定义的URI将分别为HTTP和HTTPS URI获取默认端口设置为80和443。
Route Predicate Factories
Spring Cloud Gateway将路由作为Spring WebFlux HandlerMapping
基础结构的一部分进行匹配。Spring Cloud Gateway包含许多内置的Route Predicate工厂。所有这些谓词都匹配HTTP请求的不同属性。多路线谓词工厂可以组合并通过逻辑组合and
。
After
After Route谓词工厂采用一个参数,一个日期时间。此谓词匹配在当前日期时间之后发生的请求。
1 | spring: |
此路由在2017年1月20日17:42 Mountain Time(Denver)之后的所有请求相匹配。
Before
Before Route Predicate Factory采用一个参数,一个日期时间。此谓词匹配在当前日期时间之前发生的请求。
1 | spring: |
此路由在2017年1月20日17:42 Mountain Time(Denver)之前的任何请求相匹配。
Between
Between Route Predicate Factory有两个参数,datetime1和datetime2。此谓词匹配datetime1之后和datetime2之前发生的请求。datetime2参数必须在datetime1之后。
1 | spring: |
此路路由在2017年1月20日17:42山地时间(丹佛)之后和2017年1月21日17:42山区时间(丹佛)之前的任何请求相匹配。这对维护窗口很有用。
Cookie
Cookie Route Predicate Factory有两个参数,cookie名称和正则表达式。此谓词匹配具有给定名称且值与正则表达式匹配的cookie。
1 | spring: |
此路由匹配请求具有名为chocolate
who的值与ch.p
正则表达式匹配的cookie 。
Header
Header Route谓词工厂采用两个参数,标题名称和正则表达式。此谓词与具有给定名称且值与正则表达式匹配的标头匹配。
1 | spring: |
如果请求具有名称,X-Request-Id
其值与\d+
正则表达式匹配(具有一个或多个数字的值),则此路由匹配。
Host
Host Route Predicate Factory采用一个参数:主机名模式列表。该模式是一个Ant样式模式,.
作为分隔符。此谓词匹配Host
与模式匹配的标头。
1 | spring: |
如果请求的Host
标头具有值www.somehost.org
或beta.somehost.org
或www.anotherhost.org
,则此路由将匹配。
此谓词将URI模板变量(sub
如上例中定义的)提取为名称和值的映射,并将其放在ServerWebExchange.getAttributes()
带有定义的键的位置ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE
。然后,这些值可供GatewayFilter Factories使用
Method
Method Route Predicate Factory采用一个参数:要匹配的HTTP方法。
1 | spring: |
如果请求方法是GET
,则此路由将匹配。
Path
Path Route Predicate Factory有两个参数:Spring PathMatcher
模式列表和一个可选标志matchOptionalTrailingSeparator
。
1 | spring: |
如果请求路径是例如:/foo/1
或/foo/bar
或/bar/baz
,则此路由将匹配。
此Predicate将URI模板变量(segment
如上例中定义的)提取为名称和值的映射,并将其放在ServerWebExchange.getAttributes()
带有定义的键的位置ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE
。然后,这些值可供GatewayFilter Factories使用
可以使用实用程序方法来更轻松地访问这些变量。
1 | Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange); |
Query
Query Route Predicate Factory有两个参数:必需param
和可选regexp
。
1 | spring: |
如果请求包含baz
查询参数,则此路由将匹配。
1 | spring: |
如果请求包含foo
其值为ba.
regexp 匹配的查询参数,则此路由将匹配,因此bar
并且baz
将匹配。
RemoteAddr
RemoteAddr Route Predicate Factory采用CIDR符号(IPv4或IPv6)字符串的列表(最小值为1),例如192.168.0.1/16
(其中192.168.0.1
是IP地址并且16
是子网掩码)。
1 | spring: |
例如,如果请求的远程地址是192.168.1.10
,则此路由将匹配。
修改远程地址的解析方式
默认情况下,RemoteAddr Route Predicate Factory使用传入请求中的远程地址。如果Spring Cloud Gateway位于代理层后面,则可能与实际客户端IP地址不匹配。
您可以通过设置自定义来自定义解析远程地址的方式RemoteAddressResolver
。春季云网关来与基于关闭的一个非默认的远程地址解析器X -转发,对于头,XForwardedRemoteAddressResolver
。
XForwardedRemoteAddressResolver
有两个静态构造函数方法,采用不同的安全方法:
XForwardedRemoteAddressResolver::trustAll
返回一个RemoteAddressResolver
始终采用X-Forwarded-For
标头中找到的第一个IP地址的a 。这种方法容易受到欺骗,因为恶意客户端可以设置X-Forwarded-For
解析器可以接受的初始值。
XForwardedRemoteAddressResolver::maxTrustedIndex
获取与Spring Cloud Gateway前运行的可信基础架构数量相关的索引。例如,如果只能通过HAProxy访问Spring Cloud Gateway,则应使用值1。如果在可访问Spring Cloud Gateway之前需要两跳可信基础架构,则应使用值2。
给出以下标头值:
1 | X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3 |
以下maxTrustedIndex
值将产生以下远程地址。
maxTrustedIndex |
结果 |
---|---|
[ Integer.MIN_VALUE ,0] |
(IllegalArgumentException 初始化期间无效) |
1 | 0.0.0.3 |
2 | 0.0.0.2 |
3 | 0.0.0.1 |
[4,Integer.MAX_VALUE ] |
0.0.0.1 |
使用Java配置:
GatewayConfig.java
1 | RemoteAddressResolver resolver = XForwardedRemoteAddressResolver |
Gateway Filter Factory
路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。路径过滤器的范围限定为特定路径。Spring Cloud Gateway包含许多内置的GatewayFilter工厂。
注意有关如何使用以下任何过滤器的更详细示例,请查看单元测试。
AddRequestHeader
AddRequestHeader GatewayFilter Factory采用名称和值参数。
1 | spring: |
这将为所有匹配请求的下游请求标头添加X-Request-Foo:Bar
标头。
AddRequestParameter
AddRequestParameter GatewayFilter Factory采用名称和值参数。
1 | spring: |
这将为所有匹配请求添加下游请求的查询字符串foo=bar
。
AddResponseHeader
AddResponseHeader GatewayFilter Factory采用名称和值参数。
1 | spring: |
DedupeResponseHeader
DedupeResponseHeader GatewayFilter Factory接受name
参数和可选strategy
参数。name
可以包含标题名称列表,空格分隔。
1 | spring: |
在网关CORS逻辑和下游添加它们的情况下,这将删除重复的值Access-Control-Allow-Credentials
和Access-Control-Allow-Origin
响应头。
DedupeResponseHeader过滤器还接受可选strategy
参数。接受的值是RETAIN_FIRST
(默认)、RETAIN_LAST
和RETAIN_UNIQUE
。
Hystrix
Hystrix是Netflix的一个库,它实现了断路器模式。Hystrix GatewayFilter允许您将断路器引入网关路由,保护您的服务免受级联故障的影响,并允许您在下游故障时提供回退响应。
要在项目中启用Hystrix GatewayFilters,请spring-cloud-starter-netflix-hystrix
从Spring Cloud Netflix添加依赖项。
Hystrix GatewayFilter Factory需要一个name
参数,即该参数的名称HystrixCommand
。
1 | spring: |
这将HystrixCommand
使用命令名称包装剩余的过滤器myCommandName
。
Hystrix过滤器也可以接受可选fallbackUri
参数。目前,仅forward:
支持计划的URI。如果调用了回退,则请求将被转发到与URI匹配的控制器。
1 | spring: |
这将/incaseoffailureusethis
在调用Hystrix回退时转发到URI。请注意,此示例还通过lb
目标URI 上的前缀演示(可选)Spring Cloud Netflix Ribbon负载平衡。
主要方案是使用fallbackUri
网关应用程序中的内部控制器或处理程序。但是,也可以将请求重新路由到外部应用程序中的控制器或处理程序,如下所示:
1 | spring: |
在此示例中,fallback
网关应用程序中没有端点或处理程序,但是,在另一个应用程序中有一个,在其下注册http://localhost:9994
。
如果请求被转发到回退,Hystrix网关过滤器也会提供Throwable
导致它的原因。它被添加到ServerWebExchange
作为ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR
在网关应用程序中处理回退时可以使用的 属性。
对于外部控制器/处理程序方案,可以添加包含异常详细信息的标头。您可以在FallbackHeaders GatewayFilter Factory部分中找到有关它的更多信息。
Hystrix设置(例如超时)可以使用全局默认值配置,也可以使用应用程序属性逐个路径配置,如Hystrix wiki中所述。
要为上面的示例路由设置5秒超时,将使用以下配置:
1 | hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000 |
FallbackHeaders
该FallbackHeaders
工厂可以让你在转发到请求的头部添加猬执行异常的详细信息fallbackUri
在以下情况下在外部应用程序,如:
1 | spring: |
在此示例中,在运行执行异常后HystrixCommand
,请求将被转发到fallback
运行的应用程序中的端点或处理程序localhost:9994
。具有异常类型,消息和-if available-root的标头将导致异常类型和消息被FallbackHeaders
过滤器添加到该请求中。
通过设置下面列出的参数的值及其默认值,可以在配置中覆盖标头的名称:
executionExceptionTypeHeaderName
("Execution-Exception-Type"
)executionExceptionMessageHeaderName
("Execution-Exception-Message"
)rootCauseExceptionTypeHeaderName
("Root-Cause-Exception-Type"
)rootCauseExceptionMessageHeaderName
("Root-Cause-Exception-Message"
)
您可以在Hystrix GatewayFilter Factory部分中找到有关Hystrix如何与Gateway配合使用的更多信息。
PrefixPath
PrefixPath GatewayFilter Factory采用单个prefix
参数。
1 | spring: |
这将为/mypath
所有匹配请求的路径添加前缀。所以请求/hello
,将发送给/mypath/hello
。
PreserveHostHeader
PreserveHostHeader GatewayFilter Factory没有参数。此过滤器设置路由过滤器将检查的请求属性,以确定是否应发送原始主机头,而不是http客户端确定的主机头。
1 | spring: |
RequestRateLimiter
RequestRateLimiter GatewayFilter Factory使用RateLimiter
实现来确定是否允许当前请求继续。如果不是,HTTP 429 - Too Many Requests
则返回(默认情况下)状态。
此过滤器采用keyResolver
特定于速率限制器的可选参数和参数(参见下文)。
keyResolver
是一个实现KeyResolver
接口的bean 。在配置中,使用SpEL按名称引用bean。#{@myKeyResolver}
是一个引用具有名称的bean的SpEL表达式myKeyResolver
。
KeyResolver.java
1 | public interface KeyResolver { |
该KeyResolver
接口允许可插拔策略导出用于限制请求的密钥。在未来的里程碑中,将会有一些KeyResolver
实现。
默认实现KeyResolver
是从和调用中PrincipalNameKeyResolver
检索。Principal`
ServerWebExchangePrincipal.getName()`
默认情况下,如果KeyResolver
找不到密钥,将拒绝请求。可以使用spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key
(true或false)和spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code
属性调整此行为。
RequestRateLimiter不能通过“快捷方式”表示法进行配置。以下示例无效
1 | #INVALID SHORTCUT CONFIGURATION spring.cloud.gateway.routes [0] .filters [0] = RequestRateLimiter = 2,2,#{@ userkeyresolver} |
Redis RateLimiter
redis实现基于Stripe完成的工作。它需要使用spring-boot-starter-data-redis-reactive
Spring Boot启动器。
使用的算法是令牌桶算法。
这redis-rate-limiter.replenishRate
是您希望允许用户每秒执行多少请求,而不会丢弃任何请求。这是令牌桶填充的速率。
这redis-rate-limiter.burstCapacity
是用户在一秒钟内允许执行的最大请求数。这是令牌桶可以容纳的令牌数。将此值设置为零将阻止所有请求。
通过在replenishRate
和中设置相同的值来实现稳定的速率burstCapacity
。设置burstCapacity
高于时,可以允许临时突发replenishRate
。在这种情况下,需要在突发之间允许速率限制器一段时间(根据replenishRate
),因为2次连续突发将导致请求被丢弃(HTTP 429 - Too Many Requests
)。
1 | spring: |
Config.java
1 |
|
这定义了每个用户10的请求率限制。允许突发20,但下一秒只有10个请求可用。这KeyResolver
是一个获取user
请求参数的简单方法(注意:这不建议用于生产)。
速率限制器也可以定义为实现RateLimiter
接口的bean 。在配置中,使用SpEL按名称引用bean。#{@myRateLimiter}
是一个引用具有名称的bean的SpEL表达式myRateLimiter
。
1 | spring: |
RedirectTo
RedirectTo GatewayFilter Factory采用a status
和url
参数。状态应该是300系列重定向http代码,例如301. url应该是有效的URL。这将是Location
标题的值。
1 | spring: |
这将发送带有Location:http://acme.org
标题的状态302 以执行重定向。
RemoveHopByHopHeadersFilter
RemoveHopByHopHeadersFilter GatewayFilter Factory从转发的请求中删除标头。删除的标头列表来自IETF。
默认删除的标头是:
- Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- TE
- Trailer
- Transfer-Encoding
- Upgrade
要更改此设置,请将该spring.cloud.gateway.filter.remove-non-proxy-headers.headers
属性设置为要删除的标题名称列表。
RemoveRequestHeader
RemoveRequestHeader GatewayFilter Factory接受一个name
参数。它是要删除的标头的名称。
1 | spring: |
这将在向下游发送之前删除标头X-Request-Foo
。
RemoveResponseHeader
RemoveResponseHeader GatewayFilter Factory接受一个name
参数。它是要删除的标头的名称。
1 | spring: |
这将X-Response-Foo
在响应返回到网关客户端之前从响应中删除标头。
要删除任何类型的敏感标头,您应该为您可能要执行此操作的任何路由配置此过滤器。此外,您可以使用一次配置此过滤器spring.cloud.gateway.default-filters
并将其应用于所有路径。
RewritePath
RewritePath GatewayFilter Factory采用路径regexp
参数和replacement
参数。这使用Java正则表达式来灵活地重写请求路径。
1 | spring: |
对于请求路径/foo/bar
,这将设置/bar
进行下游请求之前的路径。注意由于YAML规范而将$\
替换$
。
RewriteResponseHeader
RewriteResponseHeader GatewayFilter工厂需要name
,regexp
和replacement
参数。它使用Java正则表达式以灵活的方式重写响应头值。
1 | spring: |
对于标头值/42?user=ford&password=omg!what&flag=true
,它将在发出下游请求后设置为/42?user=ford&password=***&flag=true
。由于YAML规范,请用$\
替换$
。
SaveSession
SaveSession GatewayFilter Factory 在转发下游呼叫之前强制执行WebSession::save
操作。当使用Spring Session与惰性数据存储之类的东西时,这是特别有用的,并且需要确保在转发调用之前已保存会话状态。
1 | spring: |
如果要将Spring Security与Spring Session 集成,并且希望确保将安全性详细信息转发到远程进程,则这很关键。
SecureHeaders
SecureHeaders GatewayFilter Factory在此博客文章的推荐中为响应添加了许多标题。
添加以下标头(以及默认值):
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
SetPath GatewayFilter Factory采用路径template
参数。它提供了一种通过允许模板化路径段来操作请求路径的简单方法。这使用了Spring Framework中的uri模板。允许多个匹配的段。
1 | spring: |
对于请求路径/foo/bar
,这将设置/bar
进行下游请求之前的路径。
SetResponseHeader
1 | spring: |
GatewayFilter用给定名称替换所有标头,而不是添加。因此,如果下游服务器以响应X-Response-Foo:1234
,则将替换为X-Response-Foo:Bar
,这是网关客户端将接收的内容。
SetStatus
SetStatus GatewayFilter Factory采用单个status
参数。它必须是有效的Spring HttpStatus
。它可以是整数值404
或枚举的字符串表示形式NOT_FOUND
。
1 | spring: |
在任何一种情况下,响应的HTTP状态都将设置为401。
StripPrefix
StripPrefix GatewayFilter Factory采用一个参数parts
。该parts
参数指示在向下游发送之前从请求中剥离的路径中的部分数。
1 | spring: |
当通过网关/name/bar/foo
发出请求时,nameservice
会发出请求http://nameservice/foo
。
Retry
Retry GatewayFilter 工厂采用retries
,statuses
,methods
,和series
作为参数。
retries
:应尝试的重试次数statuses
:应使用重试的HTTP状态代码org.springframework.http.HttpStatus
methods
:应该重试的HTTP方法,使用表示org.springframework.http.HttpMethod
series
:要重试的一系列状态代码,使用表示org.springframework.http.HttpStatus.Series
1 | spring: |
重试过滤器当前不支持使用正文重试(例如,对于带有正文的POST或PUT请求)。
当使用带有
forward:
前缀URL 的重试过滤器时,应仔细编写目标端点,以便在出现错误时不会执行任何可能导致响应发送到客户端并提交的操作。例如,如果目标端点是带注释的控制器,则目标控制器方法不应返回ResponseEntity
错误状态代码。相反,它应该抛出一个Exception
或发出错误信号,例如通过Mono.error(ex)
返回值,重试过滤器可以配置为通过重试来处理。
RequestSize
当请求大小大于允许的限制时,RequestSize GatewayFilter Factory可以限制请求到达下游服务。过滤器RequestSize
作为参数,该参数是以字节为单位定义的请求的允许大小限制。
1 | spring: |
当Request因大小而被拒绝时,RequestSize GatewayFilter Factory将响应状态设置为413 Payload Too Large
附加标头errorMessage
。以下是这样的一个例子errorMessage
。
1 | errorMessage : Request size is larger than permissible limit. Request size is 6.0 MB where permissible limit is 5.0 MB |
如果未在路由定义中将过滤参数提供,则默认请求大小将设置为5 MB。
Modify Request Body
此过滤器被视为BETA,API可能在将来发生变化
此过滤器可用于在网关向下游发送请求主体之前对其进行修改。
此过滤器只能使用Java DSL进行配置
1 |
|
Modify Response Body
此过滤器被视为BETA,API可能在将来发生变化
此过滤器可用于在将响应主体发送回客户端之前对其进行修改。
此过滤器只能使用Java DSL进行配置
1 |
|
Default Filters
如果您想添加过滤器并将其应用于您可以使用的所有路线spring.cloud.gateway.default-filters
。此属性采用过滤器列表
1 | spring: |
Global Filters
该GlobalFilter
接口具有相同的签名GatewayFilter
。这些是有条件地应用于所有路线的特殊过滤器。(此界面和用法可能会在未来的里程碑中发生变化)。
组合全局过滤器和GatewayFilter排序
当请求进入(并匹配路由)时,Filtering Web Handler会将所有实例GlobalFilter
和所有路由特定实例添加GatewayFilter
到过滤器链中。这个组合的过滤器链按org.springframework.core.Ordered
接口排序,可以通过实现getOrder()
方法或使用@Order
注释来设置。
由于Spring Cloud Gateway区分了过滤器逻辑执行的“前”和“后”阶段(请参阅:工作原理),具有最高优先级的过滤器将是“pre”阶段中的第一个和“post”中的最后一个“-相。
1 |
|
Forward Routing Filter
将ForwardRoutingFilter
在交换属性查找一个URI ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
。如果url有一个forward
方案(即forward:///localendpoint
),它将使用Spring DispatcherHandler
来处理请求。请求URL的路径部分将被转发URL中的路径覆盖。未修改的原始URL将附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR
属性中的列表中。
LoadBalancerClient过滤器
将LoadBalancerClientFilter
在交换属性查找一个URI ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
。如果url有一个lb
方案(即lb://myservice
),它将使用Spring Cloud LoadBalancerClient
将名称(myservice
在前面的示例中)解析为实际的主机和端口,并替换相同属性中的URI。未修改的原始URL将附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR
属性中的列表中。过滤器还将查看ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR
属性以查看它是否等于lb
,然后应用相同的规则。
1 | spring: |
默认情况下,当某个服务实例不能在找到
LoadBalancer
一个503
将被退回。您可以将网关配置为404
按设置返回spring.cloud.gateway.loadbalancer.use404=true
。
从中返回 的
isSecure
值将覆盖在对网关发出的请求中指定的方案。例如,如果请求进入网关, 但表示它不安全,则下游请求将被终止 。相反的情况也适用。但是,如果为网关配置中的路由指定,则将剥离前缀,并且路由URL中的结果方案将覆盖配置。ServiceInstance
LoadBalancer
HTTPS
ServiceInstance
HTTP
GATEWAY_SCHEME_PREFIX_ATTR
ServiceInstance
Netty Routing Filter
如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
exchange属性中的url 具有http
或https
scheme ,则运行Netty Routing Filter 。它使用Netty HttpClient
发出下游代理请求。响应将放在ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR
exchange属性中,以便在以后的过滤器中使用。(有一个实验WebClientHttpRoutingFilter
执行相同的功能,但不需要netty)
Netty Write Response Filter
在NettyWriteResponseFilter
运行,如果有一个的Netty HttpClientResponse
在ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR
交换属性。它在所有其他过滤器完成后运行,并将代理响应写回网关客户端响应。(有一个实验WebClientWriteResponseFilter
执行相同的功能,但不需要netty)
RouteToRequestUrl过滤器
在RouteToRequestUrlFilter
运行,如果有一个Route
在对象ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR
交换属性。它根据请求URI创建一个新URI,但使用该Route
对象的URI属性进行更新。新URI放在ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
exchange属性`中。
如果URI具有方案前缀,例如lb:ws://serviceid
,该lb
方案将从URI中剥离并放置在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR
稍后用于过滤器链中。
Websocket路由过滤器
如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
exchange属性中的url 具有ws
或wss
scheme ,则运行Websocket路由过滤器。它使用Spring Web Socket基础结构将Websocket请求转发到下游。
可以通过为URI添加前缀来对Websockets进行负载平衡lb
,例如lb:ws://serviceid
。
如果您使用SockJS作为普通http的后备,则应配置正常的HTTP路由以及Websocket路由。
1 | spring: |
Gateway Metrics Filter
要启用Gateway Metrics,请将spring-boot-starter-actuator添加为项目依赖项。然后,默认情况下,只要spring.cloud.gateway.metrics.enabled
未将属性设置为,网关指标筛选器就会运行false
。此过滤器添加名为“gateway.requests”的计时器度量标准,其中包含以下标记:
routeId
:路由IDrouteUri
:API将路由到的URIoutcome
:由HttpStatus.Series分类的结果status
:请求的Http状态返回给客户端
然后可以从这些指标中删除这些指标,/actuator/metrics/gateway.requests
并且可以轻松地与Prometheus 集成 以创建Grafana 仪表板。
要启用pometheus端点,请将micrometer-registry-prometheus添加为项目依赖项。
Marking An Exchange As Routed
在网关路由后ServerWebExchange
,它将通过添加gatewayAlreadyRouted
到交换属性将该交换标记为“路由” 。一旦请求被标记为路由,其他路由过滤器将不会再次路由请求,实质上是跳过过滤器。您可以使用便捷方法将交换标记为路由,或检查交换是否已路由。
ServerWebExchangeUtils.isAlreadyRouted
获取一个ServerWebExchange
对象并检查它是否已被“路由”ServerWebExchangeUtils.setAlreadyRouted
获取一个ServerWebExchange
对象并将其标记为“路由”
TLS / SSL
网关可以通过遵循通常的Spring服务器配置来监听https上的请求。例:
1 | server: |
网关路由可以路由到http和https后端。如果路由到https后端,则可以将网关配置为信任具有以下配置的所有下游证书:
1 | spring: |
使用不安全的信任管理器不适合生产。对于生产部署,可以使用以下配置为Gateway配置一组可信任的已知证书:
1 | spring: |
如果Spring Cloud Gateway未配置受信任证书,则使用默认信任库(可以使用系统属性javax.net.ssl.trustStore覆盖)。
TLS Handshake
网关维护一个客户端池,用于路由到后端。通过https进行通信时,客户端会启动TLS握手。此握手与许多超时有关。可以配置这些超时(显示默认值):
1 | spring: |
Configuration
Spring Cloud Gateway的配置由RouteDefinitionLocator
s的集合驱动。
RouteDefinitionLocator.java
1 | public interface RouteDefinitionLocator { |
默认情况下,PropertiesRouteDefinitionLocator
使用Spring Boot的@ConfigurationProperties
机制加载属性。
上面的配置示例都使用了一个使用位置参数而不是命名参数的快捷符号。以下两个例子是等效的:
1 | spring: |
对于网关的一些用法,属性是足够的,但是一些生产用例将受益于从外部源(例如数据库)加载配置。未来的里程碑版本将RouteDefinitionLocator
基于Spring Data Repositories实现,例如:Redis,MongoDB和Cassandra。
流畅的Java Routes API
为了允许在Java中进行简单配置,在RouteLocatorBuilder
bean中定义了一个流畅的API 。
GatewaySampleApplication.java
1 | // static imports from GatewayFilters and RoutePredicates |
此样式还允许更多自定义谓词断言。RouteDefinitionLocator
bean 定义的谓词使用逻辑组合and
。通过使用流利的Java API,你可以使用and()
,or()
并且negate()
对运营Predicate
类。
DiscoveryClient路由定义定位器
可以将网关配置为基于使用DiscoveryClient
兼容服务注册表注册的服务来创建路由。
要启用此功能,请设置spring.cloud.gateway.discovery.locator.enabled=true
并确保DiscoveryClient
实现位于类路径上并启用(例如Netflix Eureka,Consul或Zookeeper)。
配置DiscoveryClient路由的谓词和过滤器
默认情况下,网关为通过a创建的路由定义单个谓词和过滤器DiscoveryClient
。
默认谓词是使用模式定义的路径谓词/serviceId/**
,其中serviceId
是来自的服务的id DiscoveryClient
。
默认过滤器是带有正则表达式/serviceId/(?<remaining>.*)
和替换的 重写路径过滤器/${remaining}
。这只是在向下游发送请求之前从路径中剥离服务ID。
如果您想自定义DiscoveryClient
路由使用的谓词和/或过滤器,可以通过设置spring.cloud.gateway.discovery.locator.predicates[x]
和来自定义spring.cloud.gateway.discovery.locator.filters[y]
。执行此操作时,如果要保留该功能,则需要确保包含上面的默认谓词和过滤器。下面是一个这样的例子。
1 | spring.cloud.gateway.discovery.locator.predicates[0].name: Path |
Reactor Netty访问日志
要启用Reactor Netty访问日志,请进行设置-Dreactor.netty.http.server.accessLogEnabled=true
。(它必须是Java System属性,而不是Spring Boot属性)。
可以将日志记录系统配置为具有单独的访问日志文件。以下是一个示例logback配置:
logback.xml
1 | <appender name="accessLog" class="ch.qos.logback.core.FileAppender"> |
CORS配置
网关可以配置为控制CORS行为。“全局”CORS配置是Spring FrameworkCorsConfiguration
的URL模式映射。
1 | spring: |
在上面的示例中,对于所有GET请求的路径,将允许来自docs.spring.io的请求的CORS请求。
Actuator API
该/gateway
驱动器的端点允许监视和使用Spring的云网关应用程序进行交互。要进行远程访问,必须在应用程序属性中通过HTTP或JMX 启用和公开端点。
1 | management.endpoint.gateway.enabled=true # default value |
检索路由过滤器
全球过滤器
要检索应用于所有路由的全局过滤器,请发出GET请求/actuator/gateway/globalfilters。结果响应类似于以下内容:
1 | { |
响应包含有关全局过滤器的详细信息。对于每个全局过滤器,提供过滤器对象的字符串表示(例如org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@77856cc5
)和过滤器链中的对应顺序。
Route过滤器
要检索应用于路由的GatewayFilter工厂,请发出GET
请求/actuator/gateway/routefilters
。结果响应类似于以下内容:
1 | { |
响应包含应用于任何特定路由的GatewayFilter工厂的详细信息。为每个工厂提供相应对象的字符串表示(例如[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]
)。请注意,该null
值是由于端点控制器的实现不完整,因为它尝试设置过滤器链中对象的顺序,这不适用于GatewayFilter工厂对象。
刷新路由缓存
要清除路由缓存,请发出POST
请求/actuator/gateway/refresh
。请求返回200没有响应正文
检索网关中定义的路由
要检索网关中定义的路由,请发出GET
请求/actuator/gateway/routes
。结果响应类似于以下内容:
1 | [{ |
响应包含网关中定义的所有路由的详细信息。下表描述了响应的每个元素(即路由)的结构。
路径 | 类型 | 描述 |
---|---|---|
route_id | String | 路由ID |
route_object.predicate | Object | 路由断言 |
route_object.filters | Array | 该GatewayFilter工厂工厂使用的路由 |
order | Number | 路由顺序 |
检索有关特定路线的信息
要检索有关单个路径的信息,GET
请向/actuator/gateway/routes/{id}
(例如/actuator/gateway/routes/first_route
)发出请求。结果响应类似于以下内容:
1 | { |
下表描述了响应的结构:
路径 | 类型 | 描述 |
---|---|---|
id |
String | 路由ID |
predicates |
Array | 路由断言的集合。每个项目定义给定断言的名称和参数 |
filters |
Array | 应用于路径的过滤器集合 |
uri |
String | 路由的目标URI |
order |
Number | 路由顺序 |
创建和删除特定路线
要创建路由,POST
请/gateway/routes/{id_route_to_create}
使用指定路径字段的JSON主体发出请求(请参阅上一小节)。
要删除路线,请发出DELETE
请求/gateway/routes/{id_route_to_delete}
。
回顾:所有端点的列表
下表总结了Spring Cloud Gateway执行器端点。请注意,每个端点都具有/actuator/gateway
基本路径。
ID | HTTP方法 | 描述 |
---|---|---|
globalfilters |
GET | 显示应用于路径的全局过滤器列表 |
routefilters |
GET | 显示应用于特定路由的GatewayFilter工厂列表 |
refresh |
POST | 清除路由缓存 |
routes |
GET | 显示网关中定义的路由列表 |
routes/{id} |
GET | 显示有关特定路径的信息 |
routes/{id} |
POST | 添加到网关的新路由 |
routes/{id} |
DELETE | 从网关中删除现有路由 |
开发者指南
TODO:编写自定义集成的概述
编写自定义路由断言工厂
TODO:撰写Custom Route Predicate Factories的文档
编写自定义GatewayFilter工厂
要编写GatewayFilter,您需要实现GatewayFilterFactory
。有一个AbstractGatewayFilterFactory
可以扩展的抽象类:
PreGatewayFilterFactory.java
1 | public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory<PreGatewayFilterFactory.Config> { |
PostGatewayFilterFactory.java
1 | public class PostGatewayFilterFactory extends AbstractGatewayFilterFactory<PostGatewayFilterFactory.Config> { |
编写定制全局过滤器
要编写自定义全局过滤器,您需要实现GlobalFilter
接口。这将过滤器应用于所有请求。
分别如何设置全局前置和后置过滤器的示例
1 |
|
编写自定义路由定位器和写入器
TODO:编写自定义路由定位器和写入器的文档
使用Spring MVC或Webflux构建简单网关
Spring Cloud Gateway提供了一个实用程序对象ProxyExchange
,可以在常规Spring Web处理程序中将其用作方法参数。它通过镜像HTTP谓词的方法支持基本的下游HTTP交换。使用MVC,它还支持通过该forward()
方法转发到本地处理程序。要ProxyExchange
在类路径中使用恰好包含正确的模块(spring-cloud-gateway-mvc
或者spring-cloud-gateway-webflux
)。
MVC示例(代理向远程服务器下游“/test”的请求):
1 |
|
Webflux也是如此:
1 |
|
有一些方便的方法ProxyExchange
可以使处理程序方法发现和增强传入请求的URI路径。例如,您可能希望提取路径的尾随元素以将其传递到下游:
1 | "/proxy/path/**") ( |
Spring MVC或Webflux的所有功能都可用于Gateway处理程序方法。例如,您可以注入请求标头和查询参数,并且您可以使用映射注释中的声明来约束传入的请求。有关@RequestMapping
这些功能的更多详细信息,请参阅Spring MVC中的文档。
可以使用header()
方法将标头添加到下游响应中ProxyExchange
。
您还可以通过向get()
etc方法添加映射器来操作响应标头(以及响应中您喜欢的任何其他内容)。映射器是一个Function
接收传入ResponseEntity
并将其转换为传出映射器的映射器。
为“敏感”标题(默认情况下为“cookie”和“授权”)提供了第一类支持,这些标题未传递到下游,而“代理”标题(x-forwarded-*
)也是如此。