4.0.7
该项目提供了一个构建在 Spring 生态系统之上的 API 网关,包括:Spring 6、Spring Boot 3 和 Project Reactor。Spring Cloud Gateway 旨在提供一种简单而有效的方法来路由到 API 并为其提供横切关注点,例如:安全性、监控/指标和弹性。
1. 如何包含Spring Cloud Gateway
要将 Spring Cloud Gateway 包含在您的项目中,请使用组 ID 为org.springframework.cloud、工件 ID 为 的启动器spring-cloud-starter-gateway。有关使用当前 Spring Cloud 发布系列设置构建系统的详细信息,请参阅Spring Cloud 项目页面。
如果您包含启动器,但不希望启用网关,请设置spring.cloud.gateway.enabled=false。
| Spring Cloud Gateway 构建于Spring Boot、Spring WebFlux和Project Reactor之上。因此,当您使用 Spring Cloud Gateway 时,您所知道的许多熟悉的同步库(例如 Spring Data 和 Spring Security)和模式可能不适用。如果您不熟悉这些项目,我们建议您在使用 Spring Cloud Gateway 之前首先阅读他们的文档以熟悉一些新概念。 |
| Spring Cloud Gateway 需要 Spring Boot 和 Spring Webflux 提供的 Netty 运行时。它不适用于传统的 Servlet 容器或构建为 WAR 时。 |
2. 术语表
-
路由:网关的基本构建块。它由 ID、目标 URI、谓词集合和过滤器集合定义。如果聚合谓词为真,则匹配路由。
-
谓词:这是一个Java 8 函数谓词。输入类型是Spring Framework
ServerWebExchange。这使您可以匹配 HTTP 请求中的任何内容,例如标头或参数。 -
Filter:这些是
GatewayFilter使用特定工厂构建的实例。在这里,您可以在发送下游请求之前或之后修改请求和响应。
3. 工作原理
下图提供了 Spring Cloud Gateway 工作原理的高级概述:
客户端向 Spring Cloud Gateway 发出请求。如果网关处理程序映射确定请求与路由匹配,则会将其发送到网关 Web 处理程序。该处理程序通过特定于请求的过滤器链运行请求。过滤器被虚线分开的原因是过滤器可以在发送代理请求之前和之后运行逻辑。执行所有“预”过滤器逻辑。然后发出代理请求。发出代理请求后,将运行“post”过滤器逻辑。
| 在没有端口的路由中定义的 URI 的 HTTP 和 HTTPS URI 的默认端口值分别为 80 和 443。 |
4. 配置路由谓词工厂和网关过滤工厂
配置谓词和过滤器有两种方法:快捷方式和完全扩展的参数。下面的大多数例子都使用快捷方式。
code名称和参数名称在每个部分的第一句或第二句中列出。这些参数通常按照快捷方式配置所需的顺序列出。
4.1. 快捷方式配置
快捷方式配置由过滤器名称识别,后跟等号 ( =),然后是用逗号 ( ,) 分隔的参数值。
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- Cookie=mycookie,mycookievalue
前面的示例Cookie使用两个参数定义 Route Predicate Factory:cookie 名称mycookie和要匹配的值mycookievalue。
4.2. 完全扩展的参数
完全扩展的参数看起来更像是带有名称/值对的标准 yaml 配置。通常,会有一把name钥匙和一把args钥匙。键args是用于配置谓词或过滤器的键值对的映射。
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- name: Cookie
args:
name: mycookie
regexp: mycookievalue
Cookie这是上面显示的谓词快捷方式配置的完整配置。
5. 路由谓词工厂
Spring Cloud Gateway 将路由作为 Spring WebFluxHandlerMapping基础设施的一部分进行匹配。Spring Cloud Gateway 包含许多内置的路由谓词工厂。所有这些谓词都匹配 HTTP 请求的不同属性。您可以将多个路由谓词工厂与逻辑and语句组合起来。
5.1. After 路由谓词工厂
路由谓词工厂After采用一个参数 a datetime(它是一个 java ZonedDateTime)。此谓词匹配指定日期时间之后发生的请求。以下示例配置后路由谓词:
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
此路线与 2017 年 1 月 20 日 17:42 山地时间(丹佛)之后提出的任何请求匹配。
5.2. Before 路由谓词工厂
路由谓词工厂Before采用一个参数 a datetime(它是一个 java ZonedDateTime)。该谓词匹配在指定的 之前发生的请求datetime。以下示例配置 before 路由谓词:
spring:
cloud:
gateway:
routes:
- id: before_route
uri: https://example.org
predicates:
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
此路线与 2017 年 1 月 20 日 17:42 山地时间(丹佛)之前提出的任何请求匹配。
5.3. 路由之间谓词工厂
路由谓词工厂Between有两个参数,datetime1它们datetime2
是javaZonedDateTime对象。datetime1该谓词匹配 之前和之后发生的请求datetime2。参数datetime2必须在 后面datetime1。以下示例配置了 Between 路由谓词:
spring:
cloud:
gateway:
routes:
- id: between_route
uri: https://example.org
predicates:
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
此路线与 2017 年 1 月 20 日 17:42 山地时间(丹佛)之后和 2017 年 1 月 21 日 17:42 山地时间(丹佛)之前提出的任何请求匹配。这对于维护窗口可能很有用。
5.4. Cookie 路由谓词工厂
路由Cookie谓词工厂采用两个参数:cookiename和 a regexp(这是一个 Java 正则表达式)。此谓词匹配具有给定名称且其值与正则表达式匹配的 cookie。以下示例配置 cookie 路由谓词工厂:
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=chocolate, ch.p
此路由匹配具有名为 cookie 且chocolate其值与ch.p正则表达式匹配的 cookie 的请求。
5.5. 标头路由谓词工厂
路由Header谓词工厂采用两个参数:theheader和 a regexp(这是一个 Java 正则表达式)。此谓词与具有给定名称且其值与正则表达式匹配的标头匹配。以下示例配置标头路由谓词:
spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
如果请求具有名为 且X-Request-Id其值与\d+正则表达式匹配的标头(即,它具有一位或多位数字的值),则此路由匹配。
5.6. 主机路由谓词工厂
路由谓词工厂Host采用一个参数:主机名列表patterns。该模式是 Ant 风格的模式,以 为.分隔符。该谓词匹配Host与模式匹配的标头。以下示例配置主机路由谓词:
spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org
{sub}.myhost.org还支持URI 模板变量(例如)。
如果请求的Host标头值为www.somehost.orgorbeta.somehost.org或,则此路由匹配www.anotherhost.org。
该谓词提取 URI 模板变量(例如sub,在前面的示例中定义的)作为名称和值的映射,并将其放置在 中,ServerWebExchange.getAttributes()并使用 中定义的键ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE。这些值可供GatewayFilter工厂使用
5.7. 方法路由谓词工厂
路由Method谓词工厂采用一个methods参数,该参数是一个或多个参数:要匹配的 HTTP 方法。以下示例配置方法路由谓词:
spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET,POST
如果请求方法是 aGET或 a ,则此路由匹配POST。
5.8. 路径路由谓词工厂
路由Path谓词工厂采用两个参数:一个 Spring 列表PathMatcher patterns和一个名为 的可选标志matchTrailingSlash(默认为true)。以下示例配置路径路由谓词:
spring:
cloud:
gateway:
routes:
- id: path_route
uri: https://example.org
predicates:
- Path=/red/{segment},/blue/{segment}
如果请求路径是,则此路由匹配,例如:/red/1or /red/1/or /red/blueor /blue/green。
如果matchTrailingSlash设置为,则不会匹配false请求路径。/red/1/
该谓词提取 URI 模板变量(例如segment,在前面的示例中定义的)作为名称和值的映射,并将其放置在 中,ServerWebExchange.getAttributes()并使用 中定义的键ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE。这些值可供GatewayFilter工厂使用
可以使用实用程序方法(称为get)来更轻松地访问这些变量。以下示例展示了如何使用该get方法:
Map<String, String> uriVariables = ServerWebExchangeUtils.getUriTemplateVariables(exchange);
String segment = uriVariables.get("segment");
5.9. 查询路由谓词工厂
路由Query谓词工厂有两个参数:一个必需参数param和一个可选参数regexp(这是一个 Java 正则表达式)。以下示例配置查询路由谓词:
spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=green
如果请求包含green查询参数,则前面的路由匹配。
spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=red, gree.
如果请求包含red其值与gree.正则表达式匹配的查询参数,则前面的路由匹配,因此green和 也greet将匹配。
5.10. RemoteAddr 路由谓词工厂
路由RemoteAddr谓词工厂采用 的列表(最小大小为 1)sources,它们是 CIDR 表示法(IPv4 或 IPv6)字符串,例如192.168.0.1/16(其中192.168.0.1是 IP 地址,16是子网掩码)。以下示例配置 RemoteAddr 路由谓词:
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: https://example.org
predicates:
- RemoteAddr=192.168.1.1/24
例如,如果请求的远程地址是 ,则该路由匹配192.168.1.10。
5.10.1. 修改远程地址解析方式
默认情况下,RemoteAddr 路由谓词工厂使用传入请求中的远程地址。如果 Spring Cloud Gateway 位于代理层后面,这可能与实际的客户端 IP 地址不匹配。
您可以通过设置自定义来自定义远程地址的解析方式RemoteAddressResolver。Spring Cloud Gateway 附带一个非默认远程地址解析器,该解析器基于X-Forwarded-For 标头, XForwardedRemoteAddressResolver。
XForwardedRemoteAddressResolver有两个静态构造函数方法,它们采用不同的安全方法:
-
XForwardedRemoteAddressResolver::trustAllRemoteAddressResolver返回始终采用标头中找到的第一个 IP 地址的aX-Forwarded-For。这种方法很容易受到欺骗,因为恶意客户端可以为 设定一个初始值X-Forwarded-For,该值将被解析器接受。 -
XForwardedRemoteAddressResolver::maxTrustedIndex采用与 Spring Cloud Gateway 前面运行的可信基础设施数量相关的索引。例如,如果 Spring Cloud Gateway 只能通过 HAProxy 访问,则应使用值 1。如果在访问 Spring Cloud Gateway 之前需要可信基础设施的两跳,则应使用值 2。
考虑以下标头值:
X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3
以下maxTrustedIndex值产生以下远程地址:
maxTrustedIndex |
结果 |
|---|---|
[ |
(无效, |
1 |
0.0.0.3 |
2 |
0.0.0.2 |
3 |
0.0.0.1 |
[4, |
0.0.0.1 |
以下示例展示了如何使用 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.11. 权重路由谓词工厂
路由谓词工厂Weight有两个参数:group和weight(一个 int)。权重按每组计算。以下示例配置权重路由谓词:
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,将约 20% 的流量转发到Weightlow.org
5.12. XForwarded 远程地址路由谓词工厂
路由XForwarded Remote Addr谓词工厂采用 的列表(最小大小为 1)sources,它们是 CIDR 表示法(IPv4 或 IPv6)字符串,例如192.168.0.1/16(其中192.168.0.1是 IP 地址,16是子网掩码)。
此路由谓词允许根据 HTTP 标头过滤请求X-Forwarded-For。
这可以与反向代理(例如负载均衡器或 Web 应用程序防火墙)一起使用,其中仅当请求来自这些反向代理所使用的可信 IP 地址列表时才应允许请求。
以下示例配置 XForwardedRemoteAddr 路由谓词:
spring:
cloud:
gateway:
routes:
- id: xforwarded_remoteaddr_route
uri: https://example.org
predicates:
- XForwardedRemoteAddr=192.168.1.1/24
X-Forwarded-For如果标头包含(例如),则此路由匹配192.168.1.10。
6.GatewayFilter工厂
路由过滤器允许以某种方式修改传入的 HTTP 请求或传出的 HTTP 响应。路由过滤器的范围仅限于特定路由。Spring Cloud Gateway 包含许多内置的 GatewayFilter Factory。
| 有关如何使用以下任何过滤器的更详细示例,请查看单元测试。 |
6.1. 工厂AddRequestHeader GatewayFilter_
工厂AddRequestHeader GatewayFilter采用name和value参数。以下示例配置AddRequestHeader GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
filters:
- AddRequestHeader=X-Request-red, blue
此列表将X-Request-red:blue标头添加到所有匹配请求的下游请求标头中。
AddRequestHeader知道用于匹配路径或主机的 URI 变量。URI 变量可以在值中使用并在运行时扩展。以下示例配置AddRequestHeader GatewayFilter使用变量的 :
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- AddRequestHeader=X-Request-Red, Blue-{segment}
6.2. 工厂AddRequestHeadersIfNotPresent GatewayFilter_
工厂AddRequestHeadersIfNotPresent GatewayFilter采用冒号分隔的name和对的集合。value以下示例配置AddRequestHeadersIfNotPresent GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: add_request_headers_route
uri: https://example.org
filters:
- AddRequestHeadersIfNotPresent=X-Request-Color-1:blue,X-Request-Color-2:green
此列表将 2 个标头添加X-Request-Color-1:blue到X-Request-Color-2:green所有匹配请求的下游请求标头中。这与工作方式类似AddRequestHeader,但与AddRequestHeader它不同的是,只有当标头不存在时才会执行此操作。否则,发送客户端请求中的原始值。
此外,要设置多值标头,请多次使用标头名称,例如AddRequestHeadersIfNotPresent=X-Request-Color-1:blue,X-Request-Color-1:green.
AddRequestHeadersIfNotPresent还支持用于匹配路径或主机的 URI 变量。URI 变量可以在值中使用并在运行时扩展。以下示例配置AddRequestHeadersIfNotPresent GatewayFilter使用变量的 :
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- AddRequestHeadersIfNotPresent=X-Request-Red:Blue-{segment}
6.3. 工厂AddRequestParameter GatewayFilter_
FactoryAddRequestParameter GatewayFilter采用name和value参数。以下示例配置AddRequestParameter GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
filters:
- AddRequestParameter=red, blue
这将添加red=blue到所有匹配请求的下游请求的查询字符串中。
AddRequestParameter知道用于匹配路径或主机的 URI 变量。URI 变量可以在值中使用并在运行时扩展。以下示例配置AddRequestParameter GatewayFilter使用变量的 :
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- AddRequestParameter=foo, bar-{segment}
6.4. 工厂AddResponseHeader GatewayFilter_
FactoryAddResponseHeader GatewayFilter采用name和value参数。以下示例配置AddResponseHeader GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: add_response_header_route
uri: https://example.org
filters:
- AddResponseHeader=X-Response-Red, Blue
这会将X-Response-Red:Blue标头添加到所有匹配请求的下游响应标头中。
AddResponseHeader知道用于匹配路径或主机的 URI 变量。URI 变量可以在值中使用并在运行时扩展。以下示例配置AddResponseHeader GatewayFilter使用变量的 :
spring:
cloud:
gateway:
routes:
- id: add_response_header_route
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- AddResponseHeader=foo, bar-{segment}
6.5. 工厂CircuitBreaker GatewayFilter_
Spring Cloud CircuitBreaker GatewayFilter 工厂使用 Spring Cloud CircuitBreaker API 将网关路由包装在断路器中。Spring Cloud CircuitBreaker 支持多个可与 Spring Cloud Gateway 一起使用的库。Spring Cloud 开箱即用地支持 Resilience4J。
要启用 Spring Cloud CircuitBreaker 过滤器,您需要将其放在spring-cloud-starter-circuitbreaker-reactor-resilience4j类路径上。以下示例配置 Spring Cloud CircuitBreaker GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: circuitbreaker_route
uri: https://example.org
filters:
- CircuitBreaker=myCircuitBreaker
要配置断路器,请参阅您正在使用的底层断路器实现的配置。
Spring Cloud CircuitBreaker 过滤器还可以接受可选fallbackUri参数。目前,仅forward:支持方案 URI。如果调用后备,则请求将转发到与 URI 匹配的控制器。以下示例配置了此类后备:
spring:
cloud:
gateway:
routes:
- id: circuitbreaker_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingServiceEndpoint
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/inCaseOfFailureUseThis
- RewritePath=/consumingServiceEndpoint, /backingServiceEndpoint
下面的清单在 Java 中做了同样的事情:
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint")
.filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis"))
.rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088")
.build();
}
/inCaseofFailureUseThis当调用断路器回退时,此示例转发到URI。请注意,此示例还演示了(可选)Spring Cloud LoadBalancer 负载均衡(由lb目标 URI 上的前缀定义)。
CircuitBreaker 还支持fallbackUri. 这允许更复杂的路由选项,例如使用PathPattern 表达式转发原始主机或 url 路径的部分 。
在下面的示例中,呼叫consumingServiceEndpoint/users/1将被重定向到inCaseOfFailureUseThis/users/1。
spring:
cloud:
gateway:
routes:
- id: circuitbreaker_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingServiceEndpoint/{*segments}
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/inCaseOfFailureUseThis/{segments}
主要场景是使用fallbackUri在网关应用程序中定义内部控制器或处理程序。但是,您也可以将请求重新路由到外部应用程序中的控制器或处理程序,如下所示:
spring:
cloud:
gateway:
routes:
- id: ingredients
uri: lb://ingredients
predicates:
- Path=//ingredients/**
filters:
- name: CircuitBreaker
args:
name: fetchIngredients
fallbackUri: forward:/fallback
- id: ingredients-fallback
uri: http://localhost:9994
predicates:
- Path=/fallback
fallback在此示例中,网关应用程序中没有端点或处理程序。然而,另一份应用程序中有一个,注册在localhost:9994.
如果请求被转发到回退,Spring Cloud CircuitBreaker Gateway 过滤器还会提供Throwable导致该请求的原因。它被添加到ServerWebExchange作为ServerWebExchangeUtils.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR在网关应用程序内处理回退时可以使用的属性。
对于外部控制器/处理程序场景,可以添加带有异常详细信息的标头。您可以在FallbackHeaders GatewayFilter Factory 部分中找到有关执行此操作的更多信息。
6.5.1. 根据状态代码使断路器跳闸
在某些情况下,您可能希望根据从其包装的路由返回的状态代码来使断路器跳闸。断路器配置对象采用状态代码列表,如果返回这些状态代码将导致断路器跳闸。设置想要使断路器跳闸的状态代码时,可以使用带有状态代码值的整数或枚举的字符串表示形式HttpStatus。
spring:
cloud:
gateway:
routes:
- id: circuitbreaker_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingServiceEndpoint
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/inCaseOfFailureUseThis
statusCodes:
- 500
- "NOT_FOUND"
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint")
.filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis").addStatusCode("INTERNAL_SERVER_ERROR"))
.rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088")
.build();
}
6.6。工厂CacheRequestBody GatewayFilter_
有些情况需要读取请求正文。由于请求只能读取一次,因此我们需要缓存请求体。您可以使用CacheRequestBody过滤器缓存请求正文,然后再将其发送到下游并从exchange属性获取正文。
以下清单显示了如何缓存请求正文GatewayFilter:
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("cache_request_body_route", r -> r.path("/downstream/**")
.filters(f -> f.prefixPath("/httpbin")
.cacheRequestBody(String.class).uri(uri))
.build();
}
spring:
cloud:
gateway:
routes:
- id: cache_request_body_route
uri: lb://downstream
predicates:
- Path=/downstream/**
filters:
- name: CacheRequestBody
args:
bodyClass: java.lang.String
CacheRequestBody提取请求正文并将其转换为正文类(例如java.lang.String,在前面的示例中定义)。
CacheRequestBody然后将其放置在 可用的属性中ServerWebExchange.getAttributes(),并使用 中定义的键ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR。
| 此过滤器仅适用于 HTTP(包括 HTTPS)请求。 |
6.7. 工厂DedupeResponseHeader GatewayFilter_
GatewayFilter工厂DedupeResponseHeader采用一个name参数和一个可选strategy参数。name可以包含以空格分隔的标头名称列表。以下示例配置DedupeResponseHeader GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: dedupe_response_header_route
uri: https://example.org
filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
当网关 CORS 逻辑和下游逻辑都添加重复值Access-Control-Allow-Credentials和响应标头时,这会删除它们。Access-Control-Allow-Origin
该DedupeResponseHeader过滤器还接受一个可选strategy参数。接受的值为RETAIN_FIRST(默认)、RETAIN_LAST和RETAIN_UNIQUE。
6.8。工厂FallbackHeaders GatewayFilter_
该FallbackHeaders工厂允许您在转发到外部应用程序的请求的标头中添加 Spring Cloud CircuitBreaker 执行异常详细信息fallbackUri,如下例所示:
spring:
cloud:
gateway:
routes:
- id: ingredients
uri: lb://ingredients
predicates:
- Path=//ingredients/**
filters:
- name: CircuitBreaker
args:
name: fetchIngredients
fallbackUri: forward:/fallback
- id: ingredients-fallback
uri: http://localhost:9994
predicates:
- Path=/fallback
filters:
- name: FallbackHeaders
args:
executionExceptionTypeHeaderName: Test-Header
在此示例中,在运行断路器时发生执行异常后,请求将转发到fallback在 上运行的应用程序中的端点或处理程序localhost:9994。带有异常类型、消息和(如果可用)根本原因异常类型和消息的标头将由过滤器添加到该请求中FallbackHeaders。
您可以通过设置以下参数的值(显示其默认值)来覆盖配置中标头的名称:
-
executionExceptionTypeHeaderName("Execution-Exception-Type") -
executionExceptionMessageHeaderName("Execution-Exception-Message") -
rootCauseExceptionTypeHeaderName("Root-Cause-Exception-Type") -
rootCauseExceptionMessageHeaderName("Root-Cause-Exception-Message")
有关断路器和网关的更多信息,请参阅Spring Cloud CircuitBreaker Factory 部分。
6.9。工厂JsonToGrpc GatewayFilter_
JSONToGRPCFilter GatewayFilter Factory 将 JSON 负载转换为 gRPC 请求。
该过滤器采用以下参数:
-
protoDescriptor:原始描述符文件。
该文件可以使用protoc并指定--descriptor_set_out标志来生成:
protoc --proto_path=src/main/resources/proto/ \
--descriptor_set_out=src/main/resources/proto/hello.pb \
src/main/resources/proto/hello.proto
-
protoFile:原型定义文件。 -
service:处理请求的服务的短名称。 -
method:处理请求的服务中的方法名称。
streaming不支持。
|
应用程序.yml。
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("json-grpc", r -> r.path("/json/hello").filters(f -> {
String protoDescriptor = "file:src/main/proto/hello.pb";
String protoFile = "file:src/main/proto/hello.proto";
String service = "HelloService";
String method = "hello";
return f.jsonToGRPC(protoDescriptor, protoFile, service, method);
}).uri(uri))
spring:
cloud:
gateway:
routes:
- id: json-grpc
uri: https://localhost:6565/testhello
predicates:
- Path=/json/**
filters:
- name: JsonToGrpc
args:
protoDescriptor: file:proto/hello.pb
protoFile: file:proto/hello.proto
service: HelloService
method: hello
当通过网关发出请求时/json/hello,请求将使用 中提供的定义进行转换hello.proto,发送至HelloService/hello,并且返回的响应将转换为 JSON。
默认情况下,它NettyChannel使用默认的TrustManagerFactory. 但是,您可以TrustManager通过创建类型的 bean来自定义它GrpcSslConfigurer:
@Configuration
public class GRPCLocalConfiguration {
@Bean
public GRPCSSLContext sslContext() {
TrustManager trustManager = trustAllCerts();
return new GRPCSSLContext(trustManager);
}
}
6.10。工厂LocalResponseCache GatewayFilter_
此过滤器允许缓存响应正文和标头以遵循以下规则:
-
它只能缓存无实体的 GET 请求。
-
它仅缓存以下状态代码之一的响应:HTTP 200(正常)、HTTP 206(部分内容)或 HTTP 301(永久移动)。
-
Cache-Control如果标头不允许(no-store存在于请求中或no-store存在private于响应中),则不会缓存响应数据。 -
如果响应已被缓存,并且在标头中使用无缓存值执行新请求
Cache-Control,则会返回带有 304(未修改)的无实体响应。
此过滤器配置每个路由的本地响应缓存,并且仅在spring.cloud.gateway.filter.local-response-cache.enabled启用该属性时才可用。全局配置的本地响应缓存也可作为功能使用。
s它接受第一个参数来覆盖缓存条目的过期时间(以秒、m分钟和h小时表示)和第二个参数来设置缓存的最大大小以逐出该路由的条目( KB、MB或GB) 。
以下清单显示了如何添加本地响应缓存GatewayFilter:
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")
.filters(f -> f.prefixPath("/httpbin")
.localResponseCache(Duration.ofMinutes(30), "500MB")
).uri(uri))
.build();
}
或这个
spring:
cloud:
gateway:
routes:
- id: resource
uri: http://localhost:9000
predicates:
- Path=/resource
filters:
- LocalResponseCache=30m,500MB
此过滤器还会自动计算max-ageHTTPCache-Control标头中的值。仅当max-age原始响应中存在 时,才会使用配置参数中设置的秒数重写该值timeToLive。在连续调用中,将使用响应到期之前剩余的秒数重新计算该值。
|
要启用此功能,请添加com.github.ben-manes.caffeine:caffeine和spring-boot-starter-cache作为项目依赖项。
|
如果您的项目创建自定义CacheManagerbean,则需要@Primary使用 进行标记或注入@Qualifier。
|
6.11. 工厂MapRequestHeader GatewayFilter_
工厂MapRequestHeader GatewayFilter采取fromHeader和toHeader参数。它创建一个新的命名标头 ( ),并从传入的 http 请求中的toHeader现有命名标头 ( ) 中提取该值。fromHeader如果输入标头不存在,则过滤器没有影响。如果新的命名标头已存在,则其值将使用新值进行扩充。以下示例配置MapRequestHeader:
spring:
cloud:
gateway:
routes:
- id: map_request_header_route
uri: https://example.org
filters:
- MapRequestHeader=Blue, X-Request-Red
这会将X-Request-Red:<values>标头添加到下游请求,并使用传入 HTTP 请求Blue标头中的更新值。
6.12. 工厂ModifyRequestBody GatewayFilter_
您可以使用ModifyRequestBody过滤器在网关向下游发送请求正文之前修改请求正文。
| 该过滤器只能使用 Java DSL 进行配置。 |
以下清单显示了如何修改请求正文GatewayFilter:
@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) -> 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;
}
}
如果请求没有正文,则RewriteFilter传递null。Mono.empty()应返回以分配请求中缺少的正文。
|
6.13。工厂ModifyResponseBody GatewayFilter_
您可以使用ModifyResponseBody过滤器在将响应正文发送回客户端之前修改它。
| 该过滤器只能使用 Java DSL 进行配置。 |
以下清单显示了如何修改响应正文GatewayFilter:
@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();
}
如果响应没有正文,则RewriteFilter传递null。Mono.empty()应该返回以分配响应中缺少的主体。
|
6.14。工厂PrefixPath GatewayFilter_
工厂PrefixPath GatewayFilter采用单个prefix参数。以下示例配置PrefixPath GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
- PrefixPath=/mypath
这/mypath是所有匹配请求的路径的前缀。因此,请求将/hello发送至/mypath/hello。
6.15。工厂PreserveHostHeader GatewayFilter_
工厂PreserveHostHeader GatewayFilter没有参数。此过滤器设置路由过滤器检查的请求属性,以确定是否应发送原始主机标头而不是 HTTP 客户端确定的主机标头。以下示例配置PreserveHostHeader GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: preserve_host_route
uri: https://example.org
filters:
- PreserveHostHeader
6.16。工厂RedirectTo GatewayFilter_
工厂RedirectTo GatewayFilter有两个参数,status和url。参数status应为300系列重定向HTTP代码,例如301。url参数应为有效的URL。这是标头的值Location。对于相对重定向,您应该使用uri: no://op路由定义的 uri。以下清单配置了RedirectTo GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
- RedirectTo=302, https://acme.org
这将发送带有标头的状态 302Location:https://acme.org以执行重定向。
6.17。RemoveJsonAttributesResponseBody GatewayFilter工厂
工厂RemoveJsonAttributesResponseBody GatewayFilter需要一个集合attribute names来搜索,列表中的可选最后一个参数可以是一个布尔值,用于删除根级别的属性(如果参数配置末尾不存在,则这是默认值,)或递归地false(true) 。它提供了一种方便的方法,通过删除 JSON 正文内容的属性来对其应用转换。
以下示例配置RemoveJsonAttributesResponseBody GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: removejsonattributes_route
uri: https://example.org
filters:
- RemoveJsonAttributesResponseBody=id,color
这将从根级别的 JSON 内容正文中删除属性“id”和“color”。
以下示例配置RemoveJsonAttributesResponseBody GatewayFilter使用可选的最后一个参数的 :
spring:
cloud:
gateway:
routes:
- id: removejsonattributes_recursively_route
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- RemoveJsonAttributesResponseBody=id,color,true
这将从任何级别的 JSON 内容正文中删除属性“id”和“color”。
6.18。RemoveRequestHeader网关过滤器工厂
工厂RemoveRequestHeader GatewayFilter接受一个name参数。它是要删除的标头的名称。以下清单配置了RemoveRequestHeader GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: removerequestheader_route
uri: https://example.org
filters:
- RemoveRequestHeader=X-Request-Foo
这会X-Request-Foo在将标头发送到下游之前删除标头。
6.19。工厂RemoveRequestParameter GatewayFilter_
工厂RemoveRequestParameter GatewayFilter接受一个name参数。它是要删除的查询参数的名称。以下示例配置RemoveRequestParameter GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: removerequestparameter_route
uri: https://example.org
filters:
- RemoveRequestParameter=red
red这将在参数发送到下游之前删除该参数。
6.20。工厂RemoveResponseHeader GatewayFilter_
工厂RemoveResponseHeader GatewayFilter接受一个name参数。它是要删除的标头的名称。以下清单配置了RemoveResponseHeader GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: removeresponseheader_route
uri: https://example.org
filters:
- RemoveResponseHeader=X-Response-Foo
X-Response-Foo这将在响应返回到网关客户端之前从响应中删除标头。
要删除任何类型的敏感标头,您应该为您可能想要执行此操作的任何路由配置此过滤器。此外,您可以通过使用配置此过滤器一次spring.cloud.gateway.default-filters并将其应用于所有路由。
6.21。工厂RequestHeaderSize GatewayFilter_
工厂RequestHeaderSize GatewayFilter采取maxSize和errorHeaderName参数。该maxSize参数为请求头允许的最大数据大小(包括key和value)。该errorHeaderName参数设置包含错误消息的响应头的名称,默认为“errorMessage”。以下清单配置了RequestHeaderSize GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: requestheadersize_route
uri: https://example.org
filters:
- RequestHeaderSize=1000B
如果任何请求标头的大小大于 1000 字节,这将发送状态 431。
6.22。工厂RequestRateLimiter GatewayFilter_
工厂RequestRateLimiter GatewayFilter使用一个RateLimiter实现来确定是否允许当前请求继续。如果不是,HTTP 429 - Too Many Requests则返回状态(默认情况下)。
该过滤器采用可选keyResolver参数和特定于速率限制器的参数(本节稍后介绍)。
keyResolver是一个实现该接口的bean KeyResolver。在配置中,使用 SpEL 按名称引用 bean。
#{@myKeyResolver}是引用名为 的 bean 的 SpEL 表达式myKeyResolver。下面的清单显示了该KeyResolver界面:
public interface KeyResolver {
Mono<String> resolve(ServerWebExchange exchange);
}
该KeyResolver接口允许可插入策略派生限制请求的密钥。在未来的里程碑版本中,将会有一些KeyResolver实现。
的默认实现KeyResolver是PrincipalNameKeyResolver,它Principal从ServerWebExchange和 调用中检索Principal.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属性来调整此行为。
|
不可 示例 43.application.properties
# INVALID SHORTCUT CONFIGURATION
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}
|
6.22.1. 雷迪斯RateLimiter
Redis 的实现基于Stripe所做的工作。它需要使用spring-boot-starter-data-redis-reactiveSpring Boot 启动器。
使用的算法是令牌桶算法。
该redis-rate-limiter.replenishRate属性定义每秒允许多少个请求(没有任何丢弃的请求)。这是令牌桶被填满的速率。
该redis-rate-limiter.burstCapacity属性是用户在一秒钟内允许的最大请求数(没有任何丢弃的请求)。这是令牌桶可以容纳的令牌数量。将此值设置为零会阻止所有请求。
该redis-rate-limiter.requestedTokens属性是请求花费多少令牌。这是每个请求从存储桶中获取的令牌数量,默认为1。
replenishRate通过在和中设置相同的值可以实现稳定的速率burstCapacity。burstCapacity通过设置高于可以允许临时突发replenishRate。在这种情况下,速率限制器需要在突发之间留出一定的时间(根据replenishRate),因为两个连续的突发会导致请求丢失 ( HTTP 429 - Too Many Requests)。以下清单配置了redis-rate-limiter:
下面的速率限制1 request/s是通过设置replenishRate所需的请求数量、requestedTokens以秒为单位的时间跨度以及和burstCapacity的乘积来实现的。例如,设置、和会导致限制为。.application.ymlreplenishRaterequestedTokensreplenishRate=1requestedTokens=60burstCapacity=601 request/min
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: https://example.org
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
redis-rate-limiter.requestedTokens: 1
以下示例KeyResolver在 Java 中配置 a:
@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}
这定义了每个用户 10 次的请求速率限制。允许突发 20 个,但下一秒只有 10 个请求可用。这KeyResolver是一个获取user请求参数的简单方法注意:不建议在生产中这样做
您还可以将速率限制器定义为实现该接口的 bean RateLimiter。在配置中,您可以使用 SpEL 按名称引用 bean。
#{@myRateLimiter}是一个 SpEL 表达式,它引用名为 的 bean myRateLimiter。以下清单定义了一个使用KeyResolver前面清单中定义的速率限制器:
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: https://example.org
filters:
- name: RequestRateLimiter
args:
rate-limiter: "#{@myRateLimiter}"
key-resolver: "#{@userKeyResolver}"
6.23。工厂RewriteLocationResponseHeader GatewayFilter_
工厂RewriteLocationResponseHeader GatewayFilter修改响应标头的值Location,通常是为了删除特定于后端的详细信息。它采用stripVersionMode、locationHeaderName、hostValue和protocolsRegex参数。以下清单配置了RewriteLocationResponseHeader GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: rewritelocationresponseheader_route
uri: http://example.org
filters:
- RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,
例如,对于 的请求,响应头值被重写为。POST api.example.com/some/object/nameLocationobject-service.prod.example.net/v2/some/object/idapi.example.com/some/object/id
该stripVersionMode参数具有以下可能的值:NEVER_STRIP、AS_IN_REQUEST(默认)和ALWAYS_STRIP。
-
NEVER_STRIP:即使原始请求路径不包含版本,版本也不会被剥离。 -
AS_IN_REQUEST:仅当原始请求路径不包含版本时,才会剥离版本。 -
ALWAYS_STRIP:版本始终被剥离,即使原始请求路径包含版本。
该hostValue参数(如果提供)用于替换host:port响应Location标头的部分。如果未提供,Host则使用请求标头的值。
该protocolsRegex参数必须是有效的 regex String,与协议名称相匹配。如果不匹配,则过滤器不执行任何操作。默认为http|https|ftp|ftps.
6.24。工厂RewritePath GatewayFilter_
工厂RewritePath GatewayFilter采用一个路径regexp参数和一个replacement参数。这使用 Java 正则表达式来灵活地重写请求路径。以下清单配置了RewritePath GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: rewritepath_route
uri: https://example.org
predicates:
- Path=/red/**
filters:
- RewritePath=/red/?(?<segment>.*), /$\{segment}
对于 的请求路径,这会在发出下游请求之前/red/blue将路径设置为。/blue请注意,由于 YAML 规范,$应将 替换为。$\
6.25。工厂RewriteResponseHeader GatewayFilter_
工厂RewriteResponseHeader GatewayFilter采用name、regexp和replacement参数。它使用 Java 正则表达式以灵活的方式重写响应标头值。以下示例配置RewriteResponseHeader GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: rewriteresponseheader_route
uri: https://example.org
filters:
- RewriteResponseHeader=X-Response-Red, , password=[^&]+, password=***
对于标头值,在发出下游请求后将/42?user=ford&password=omg!what&flag=true其设置为。由于 YAML 规范,/42?user=ford&password=***&flag=true您必须使用$\to 表示。$
6.26。工厂SaveSession GatewayFilter_
工厂在将调用转发到下游之前SaveSession GatewayFilter强制执行WebSession::save操作。当使用带有惰性数据存储的Spring Session之类的东西时,这特别有用,并且您需要确保在进行转发调用之前已保存会话状态。以下示例配置:SaveSession GatewayFilter
spring:
cloud:
gateway:
routes:
- id: save_session
uri: https://example.org
predicates:
- Path=/foo/**
filters:
- SaveSession
如果您将Spring Security与 Spring Session 集成,并希望确保安全详细信息已转发到远程进程,那么这一点至关重要。
6.27。工厂SecureHeaders GatewayFilter_
根据这篇博文中的建议,工厂SecureHeaders GatewayFilter在响应中添加了许多标头。
添加了以下标头(显示其默认值):
-
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
要禁用默认值,请spring.cloud.gateway.filter.secure-headers.disable使用逗号分隔值设置属性。以下示例展示了如何执行此操作:
spring.cloud.gateway.filter.secure-headers.disable=x-frame-options,strict-transport-security
| 需要使用安全标头的小写全名来禁用它。 |
6.28。工厂SetPath GatewayFilter_
工厂SetPath GatewayFilter采用路径template参数。它提供了一种通过允许路径的模板化段来操作请求路径的简单方法。这使用了 Spring Framework 中的 URI 模板。允许多个匹配段。以下示例配置SetPath GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: setpath_route
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- SetPath=/{segment}
对于 的请求路径,这会在发出下游请求之前/red/blue将路径设置为。/blue
6.29。工厂SetRequestHeader GatewayFilter_
工厂SetRequestHeader GatewayFilter采取name和value参数。以下清单配置了SetRequestHeader GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: setrequestheader_route
uri: https://example.org
filters:
- SetRequestHeader=X-Request-Red, Blue
这GatewayFilter将替换(而不是添加)具有给定名称的所有标头。因此,如果下游服务器响应X-Request-Red:1234,它将被替换为X-Request-Red:Blue,这是下游服务将收到的内容。
SetRequestHeader知道用于匹配路径或主机的 URI 变量。URI 变量可以在值中使用并在运行时扩展。以下示例配置SetRequestHeader GatewayFilter使用变量的 :
spring:
cloud:
gateway:
routes:
- id: setrequestheader_route
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- SetRequestHeader=foo, bar-{segment}
6.30。工厂SetResponseHeader GatewayFilter_
工厂SetResponseHeader GatewayFilter采取name和value参数。以下清单配置了SetResponseHeader GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: setresponseheader_route
uri: https://example.org
filters:
- SetResponseHeader=X-Response-Red, Blue
此 GatewayFilter 替换(而不是添加)具有给定名称的所有标头。因此,如果下游服务器响应X-Response-Red:1234,它将被替换为X-Response-Red:Blue,这是网关客户端将收到的内容。
SetResponseHeader知道用于匹配路径或主机的 URI 变量。URI 变量可以在值中使用,并将在运行时扩展。以下示例配置SetResponseHeader GatewayFilter使用变量的 :
spring:
cloud:
gateway:
routes:
- id: setresponseheader_route
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- SetResponseHeader=foo, bar-{segment}
6.31。工厂SetStatus GatewayFilter_
工厂SetStatus GatewayFilter采用单个参数status。它必须是一个有效的 Spring HttpStatus。404它可以是枚举的整数值或字符串表示形式: NOT_FOUND。以下清单配置了SetStatus GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: setstatusstring_route
uri: https://example.org
filters:
- SetStatus=UNAUTHORIZED
- id: setstatusint_route
uri: https://example.org
filters:
- SetStatus=401
无论哪种情况,响应的 HTTP 状态都会设置为 401。
您可以将其配置SetStatus GatewayFilter为从响应标头中的代理请求返回原始 HTTP 状态代码。如果配置了以下属性,则标头将添加到响应中:
spring:
cloud:
gateway:
set-status:
original-status-header-name: original-http-status
6.32。工厂StripPrefix GatewayFilter_
工厂StripPrefix GatewayFilter采用一个参数parts. 该parts参数指示在向下游发送请求之前要从请求中剥离的路径中的部分数量。以下清单配置了StripPrefix GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: nameRoot
uri: https://nameservice
predicates:
- Path=/name/**
filters:
- StripPrefix=2
当通过网关 to 发出请求时/name/blue/red,向 to 发出的请求nameservice如下所示nameservice/red。
6.33。工厂Retry GatewayFilter_
工厂Retry GatewayFilter支持以下参数:
-
retries:应尝试的重试次数。 -
statuses:需要重试的HTTP状态码,用 表示org.springframework.http.HttpStatus。 -
methods:应该重试的HTTP方法,用 表示org.springframework.http.HttpMethod。 -
series:要重试的一系列状态码,用 表示org.springframework.http.HttpStatus.Series。 -
exceptions:应重试的引发异常的列表。 -
backoff:配置的重试指数退避。在退避间隔 后执行重试firstBackoff * (factor ^ n),其中n是迭代次数。如果maxBackoff配置,则应用的最大退避限制为maxBackoff。如果basedOnPreviousValue为 true,则使用 计算退避prevBackoff * factor。
如果启用,则为过滤器配置以下默认值Retry:
-
retries: 三次 -
series:5XX系列 -
methods:获取方法 -
exceptions:IOException和TimeoutException -
backoff:禁用
以下清单配置了 Retry GatewayFilter:
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
methods: GET,POST
backoff:
firstBackoff: 10ms
maxBackoff: 50ms
factor: 2
basedOnPreviousValue: false
当使用带有前缀 URL 的重试过滤器时forward:,应仔细编写目标端点,以便在发生错误时,它不会执行任何可能导致响应发送到客户端并提交的操作。例如,如果目标端点是带注释的控制器,则目标控制器方法不应返回ResponseEntity错误状态代码。相反,它应该抛出一个Exception错误或发出错误信号(例如,通过Mono.error(ex)返回值),重试过滤器可以配置为通过重试来处理。
|
当对任何带有主体的 HTTP 方法使用重试过滤器时,主体将被缓存,并且网关将变得内存受限。正文缓存在由 定义的请求属性中ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR。对象的类型是org.springframework.core.io.buffer.DataBuffer。
|
可以使用单个status和添加简化的“快捷方式”符号method。
以下两个示例是等效的:
spring:
cloud:
gateway:
routes:
- id: retry_route
uri: https://example.org
filters:
- name: Retry
args:
retries: 3
statuses: INTERNAL_SERVER_ERROR
methods: GET
backoff:
firstBackoff: 10ms
maxBackoff: 50ms
factor: 2
basedOnPreviousValue: false
- id: retryshortcut_route
uri: https://example.org
filters:
- Retry=3,INTERNAL_SERVER_ERROR,GET,10ms,50ms,2,false
6.34。工厂RequestSize GatewayFilter_
当请求大小大于允许的限制时,工厂RequestSize GatewayFilter可以限制请求到达下游服务。过滤器采用一个maxSize参数。这maxSize是一种DataSize类型,因此值可以定义为数字后跟可选后缀,DataUnit例如“KB”或“MB”。默认值为“B”(字节)。它是以字节为单位定义的请求的允许大小限制。以下清单配置了RequestSize GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: request_size_route
uri: http://localhost:8080/upload
predicates:
- Path=/upload
filters:
- name: RequestSize
args:
maxSize: 5000000
当请求由于大小而被拒绝时,工厂RequestSize GatewayFilter将响应状态设置为413 Payload Too Large附加标头。errorMessage以下示例显示了这样的errorMessage:
errorMessage : Request size is larger than permissible limit. Request size is 6.0 MB where permissible limit is 5.0 MB
| 如果未在路由定义中作为过滤器参数提供,则默认请求大小将设置为 5 MB。 |
6.35。工厂SetRequestHostHeader GatewayFilter_
在某些情况下,可能需要覆盖主机标头。在这种情况下,SetRequestHostHeader GatewayFilter工厂可以将现有的主机头替换为指定值。过滤器采用一个host参数。以下清单配置了SetRequestHostHeader GatewayFilter:
spring:
cloud:
gateway:
routes:
- id: set_request_host_header_route
uri: http://localhost:8080/headers
predicates:
- Path=/headers
filters:
- name: SetRequestHostHeader
args:
host: example.org
工厂SetRequestHostHeader GatewayFilter将主机标头的值替换为example.org。
6.36。工厂TokenRelay GatewayFilter_
令牌中继是 OAuth2 使用者充当客户端并将传入令牌转发到传出资源请求的地方。使用者可以是纯粹的客户端(如 SSO 应用程序)或资源服务器。
Spring Cloud Gateway 可以将 OAuth2 访问令牌下游转发到它所代理的服务。要将此功能添加到网关,您需要添加TokenRelayGatewayFilterFactory如下内容:
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("resource", r -> r.path("/resource")
.filters(f -> f.tokenRelay())
.uri("http://localhost:9000"))
.build();
}
或这个
spring:
cloud:
gateway:
routes:
- id: resource
uri: http://localhost:9000
predicates:
- Path=/resource
filters:
- TokenRelay=
并且它(除了让用户登录并获取令牌之外)还将身份验证令牌传递给下游服务(在本例中
/resource)。
要为 Spring Cloud Gateway 启用此功能,请添加以下依赖项
-
org.springframework.boot:spring-boot-starter-oauth2-client
它是如何工作的?{githubmaster}/src/main/java/org/springframework/cloud/gateway/security/TokenRelayGatewayFilterFactory.java[filter] 从当前经过身份验证的用户中提取访问令牌,并将其放入下游请求的请求标头中。
有关完整的工作示例,请参阅此项目。
仅当设置了TokenRelayGatewayFilterFactory正确的属性(这将触发 Bean 的创建)时,才会创建
Bean 。
spring.security.oauth2.client.*ReactiveClientRegistrationRepository |
ReactiveOAuth2AuthorizedClientServiceby 使用的
默认实现TokenRelayGatewayFilterFactory
使用内存中的数据存储。ReactiveOAuth2AuthorizedClientService
如果您需要更强大的解决方案,
您将需要提供自己的实现。 |
6.37。默认过滤器
要添加过滤器并将其应用于所有路由,您可以使用spring.cloud.gateway.default-filters。该属性采用一个过滤器列表。以下清单定义了一组默认过滤器:
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Response-Default-Red, Default-Blue
- PrefixPath=/httpbin
7. 全局过滤器
该GlobalFilter接口具有与 相同的签名GatewayFilter。这些是有条件地应用于所有路由的特殊过滤器。
| 此接口及其用法可能会在未来的里程碑版本中发生变化。 |
7.1. 组合全局过滤器和GatewayFilter排序
当请求与路由匹配时,过滤 Web 处理程序会将 的所有实例GlobalFilter以及所有特定于路由的实例添加GatewayFilter到过滤器链中。这个组合的过滤器链是按org.springframework.core.Ordered接口排序的,您可以通过实现方法来设置getOrder()。
由于 Spring Cloud Gateway 区分过滤器逻辑执行的“前”和“后”阶段(请参阅工作原理),具有最高优先级的过滤器是“前”阶段的第一个和“后”阶段的最后一个 -阶段。
以下清单配置了过滤器链:
@Bean
public GlobalFilter customFilter() {
return new CustomGlobalFilter();
}
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("custom global filter");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1;
}
}
7.2. 网关指标过滤器
要启用网关指标,请添加spring-boot-starter-actuator为项目依赖项。然后,默认情况下,只要该spring.cloud.gateway.metrics.enabled属性未设置为 ,网关指标过滤器就会运行false。spring.cloud.gateway.requests此过滤器添加一个使用以下标签命名的计时器指标:
-
routeId:路线ID。 -
routeUri:API 路由到的 URI。 -
outcome:结果,按HttpStatus.Series分类。 -
status:返回给客户端的请求的HTTP状态。 -
httpStatusCode:返回给客户端的请求的 HTTP 状态。 -
httpMethod:请求所使用的 HTTP 方法。
此外,通过spring.cloud.gateway.metrics.tags.path.enabled属性(默认情况下为false),您可以使用路径标签激活额外的指标:
-
path:请求的路径。
要启用 prometheus 端点,请添加micrometer-registry-prometheus为项目依赖项。
|
7.3. 本地响应缓存过滤器
LocalResponseCache如果启用关联属性,则运行:
-
spring.cloud.gateway.global-filter.local-response-cache.enabled:激活所有路由的全局缓存 -
spring.cloud.gateway.filter.local-response-cache.enabled:激活关联的过滤器以在路由级别使用
此功能为满足以下条件的所有响应启用使用 Caffeine 的本地缓存:
-
该请求是无实体的 GET。
-
响应具有以下状态代码之一:HTTP 200(正常)、HTTP 206(部分内容)或 HTTP 301(永久移动)。
-
HTTP
Cache-Control标头允许缓存(这意味着它不具有以下任何值:no-store存在于请求中和/no-store或private存在于响应中)。
它接受两个配置参数:
-
spring.cloud.gateway.filter.local-response-cache.size:设置缓存的最大大小以逐出该路由的条目(以 KB、MB 和 GB 为单位)。 -
spring.cloud.gateway.filter.local-response-cache.time-to-live设置缓存条目的过期时间(以 s 表示秒、m 表示分钟、h 表示小时)表示。
如果未配置这些参数,但启用了全局过滤器,则默认情况下,它会为缓存的响应配置 5 分钟的生存时间。
max-age该过滤器还实现了HTTP标头中的值的自动计算Cache-Control。如果max-age原始响应中存在,则使用配置参数中设置的秒数重写该值timeToLive。在后续调用中,将使用响应到期之前剩余的秒数重新计算该值。
设置spring.cloud.gateway.global-filter.local-response-cache.enabled为false禁用所有路由的本地响应缓存,LocalResponseCache 过滤器允许在路由级别使用此功能。
要启用此功能,请添加com.github.ben-manes.caffeine:caffeine和spring-boot-starter-cache作为项目依赖项。
|
如果您的项目创建自定义CacheManagerbean,则需要@Primary使用 进行标记或注入@Qualifier。
|
7.4. 正向路由过滤器
在交换属性中查找ForwardRoutingFilterURI ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR。如果 URL 有一个forward方案(例如forward:///localendpoint),它将使用 SpringDispatcherHandler来处理请求。请求 URL 的路径部分将被转发 URL 中的路径覆盖。未修改的原始 URL 将附加到属性中的列表中ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR。
7.5。Netty 路由过滤器
ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR如果交换属性中的 URL具有httporhttps方案,则 Netty 路由过滤器将运行。它使用 NettyHttpClient发出下游代理请求。响应被放入ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR交换属性中以供稍后的过滤器使用。(还有一个实验WebClientHttpRoutingFilter可以实现相同的功能,但不需要Netty。)
7.6。Netty 写响应过滤器
如果交换属性中NettyWriteResponseFilter有 Netty,则运行。它在所有其他过滤器完成后运行,并将代理响应写回网关客户端响应。(还有一个实验可以实现相同的功能,但不需要Netty。)HttpClientResponseServerWebExchangeUtils.CLIENT_RESPONSE_ATTRWebClientWriteResponseFilter
7.7. 这ReactiveLoadBalancerClientFilter
在名为 的交换属性中查找ReactiveLoadBalancerClientFilterURI ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR。如果 URL 有一个lb方案(例如lb://myservice),它会使用 Spring CloudReactorLoadBalancer将名称(myservice在本示例中)解析为实际的主机和端口,并替换同一属性中的 URI。未修改的原始 URL 将附加到属性中的列表中ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR。过滤器还会查看ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR属性以查看它是否等于lb。如果是这样,则适用相同的规则。以下清单配置了ReactiveLoadBalancerClientFilter:
spring:
cloud:
gateway:
routes:
- id: myRoute
uri: lb://service
predicates:
- Path=/service/**
默认情况下,当找不到服务实例时ReactorLoadBalancer,503返回 a。404您可以通过设置配置网关返回a spring.cloud.gateway.loadbalancer.use404=true。
|
返回isSecure的值
会覆盖向网关发出的请求中指定的方案。例如,如果请求通过 进入网关,但指示它不安全,则下游请求将通过 发出。相反的情况也可以适用。但是,如果在网关配置中为路由指定了 ,则前缀将被删除,并且路由 URL 生成的方案将覆盖配置。
ServiceInstanceReactiveLoadBalancerClientFilterHTTPSServiceInstanceHTTPGATEWAY_SCHEME_PREFIX_ATTRServiceInstance |
| 网关支持所有 LoadBalancer 功能。您可以在Spring Cloud Commons 文档中阅读有关它们的更多信息。 |
7.8。过滤RouteToRequestUrl器
Route如果交换属性中有对象ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR,则RouteToRequestUrlFilter运行。它基于请求 URI 创建一个新的 URI,但使用对象的 URI 属性进行更新Route。新的 URI 被放置在ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR交换属性中。
如果 URI 具有方案前缀,例如lb:ws://serviceid,则该lb方案将从 URI 中剥离并放置在 中,ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR以便稍后在过滤器链中使用。
7.9。Websocket 路由过滤器
如果位于交换属性中的 URLServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR具有wsorwss方案,则 websocket 路由过滤器将运行。它使用 Spring WebSocket 基础设施向下游转发 websocket 请求。
您可以通过在 URI 前添加 前缀来对 Websocket 进行负载平衡lb,例如lb:ws://serviceid。
| 如果您使用SockJS作为普通 HTTP 的后备,您应该配置普通 HTTP 路由以及 websocket 路由。 |
以下清单配置了 websocket 路由过滤器:
spring:
cloud:
gateway:
routes:
# SockJS route
- id: websocket_sockjs_route
uri: http://localhost:3001
predicates:
- Path=/websocket/info/**
# Normal Websocket route
- id: websocket_route
uri: ws://localhost:3001
predicates:
- Path=/websocket/**
7.10。将交换标记为已路由
网关路由 后,它会通过添加
交换属性ServerWebExchange来将该交换标记为“已路由” 。gatewayAlreadyRouted一旦请求被标记为已路由,其他路由过滤器将不会再次路由该请求,实质上会跳过该过滤器。您可以使用一些方便的方法将交换标记为已路由或检查交换是否已被路由。
-
ServerWebExchangeUtils.isAlreadyRouted获取一个ServerWebExchange对象并检查它是否已被“路由”。 -
ServerWebExchangeUtils.setAlreadyRouted获取一个ServerWebExchange对象并将其标记为“已路由”。
8.HttpHeaders过滤器
HttpHeadersFilters在将请求发送到下游之前应用于请求,例如在NettyRoutingFilter.
8.1. 转发标头过滤器
标Forwarded头过滤器创建一个Forwarded标头以发送到下游服务。它将Host当前请求的标头、方案和端口添加到任何现有Forwarded标头中。
8.2. 删除HopByHop标头过滤器
标RemoveHopByHop头过滤器从转发的请求中删除标头。删除的默认标头列表来自IETF。
-
联系
-
活着
-
代理认证
-
代理授权
-
TE
-
预告片
-
传输编码
-
升级
要更改此设置,请将该spring.cloud.gateway.filter.remove-hop-by-hop.headers属性设置为要删除的标头名称列表。
8.3. XForwarded 标头过滤器
标XForwarded头过滤器创建各种X-Forwarded-*标头以发送到下游服务。它使用Host当前请求的标头、方案、端口和路径来创建各种标头。
可以通过以下布尔属性控制单个标头的创建(默认为 true):
-
spring.cloud.gateway.x-forwarded.for-enabled -
spring.cloud.gateway.x-forwarded.host-enabled -
spring.cloud.gateway.x-forwarded.port-enabled -
spring.cloud.gateway.x-forwarded.proto-enabled -
spring.cloud.gateway.x-forwarded.prefix-enabled
附加多个标头可以通过以下布尔属性控制(默认为 true):
-
spring.cloud.gateway.x-forwarded.for-append -
spring.cloud.gateway.x-forwarded.host-append -
spring.cloud.gateway.x-forwarded.port-append -
spring.cloud.gateway.x-forwarded.proto-append -
spring.cloud.gateway.x-forwarded.prefix-append
9. TLS 和 SSL
网关可以按照通常的 Spring 服务器配置监听 HTTPS 上的请求。以下示例展示了如何执行此操作:
server:
ssl:
enabled: true
key-alias: scg
key-store-password: scg1234
key-store: classpath:scg-keystore.p12
key-store-type: PKCS12
您可以将网关路由路由到 HTTP 和 HTTPS 后端。如果您要路由到 HTTPS 后端,则可以使用以下配置将网关配置为信任所有下游证书:
spring:
cloud:
gateway:
httpclient:
ssl:
useInsecureTrustManager: true
使用不安全的信任管理器不适合生产。对于生产部署,您可以使用一组可通过以下配置信任的已知证书来配置网关:
spring:
cloud:
gateway:
httpclient:
ssl:
trustedX509Certificates:
- cert1.pem
- cert2.pem
如果 Spring Cloud Gateway 未配置受信任的证书,则使用默认的信任存储(您可以通过设置系统javax.net.ssl.trustStore属性来覆盖它)。
9.1. TLS 握手
网关维护一个客户端池,用于路由到后端。通过 HTTPS 进行通信时,客户端会发起 TLS 握手。许多超时与此握手相关。您可以配置这些超时(显示默认值),如下所示:
spring:
cloud:
gateway:
httpclient:
ssl:
handshake-timeout-millis: 10000
close-notify-flush-timeout-millis: 3000
close-notify-read-timeout-millis: 0
10. 配置
Spring Cloud Gateway 的配置由实例集合驱动RouteDefinitionLocator。下面的清单显示了接口的定义RouteDefinitionLocator:
public interface RouteDefinitionLocator {
Flux<RouteDefinition> getRouteDefinitions();
}
默认情况下,aPropertiesRouteDefinitionLocator使用 Spring Boot 的@ConfigurationProperties机制加载属性。
早期的配置示例都使用快捷表示法,该表示法使用位置参数而不是命名参数。以下两个示例是等效的:
spring:
cloud:
gateway:
routes:
- id: setstatus_route
uri: https://example.org
filters:
- name: SetStatus
args:
status: 401
- id: setstatusshortcut_route
uri: https://example.org
filters:
- SetStatus=401
对于网关的某些用途,属性就足够了,但某些生产用例受益于从外部源(例如数据库)加载配置。未来的里程碑版本将具有RouteDefinitionLocator基于 Spring Data Repositories 的实现,例如 Redis、MongoDB 和 Cassandra。
10.1. 路由定义指标
要启用RouteDefinition指标,请将 spring-boot-starter-actuator 添加为项目依赖项。然后,默认情况下,只要该属性spring.cloud.gateway.metrics.enabled设置为,指标就可用true。将添加一个名为 的计量指标spring.cloud.gateway.routes.count,其值为 的数量RouteDefinitions。该指标可从 获得/actuator/metrics/spring.cloud.gateway.routes.count。
11. 路由元数据配置
您可以使用元数据为每个路由配置附加参数,如下所示:
spring:
cloud:
gateway:
routes:
- id: route_with_metadata
uri: https://example.org
metadata:
optionName: "OptionValue"
compositeObject:
name: "value"
iAmNumber: 1
您可以从交换中获取所有元数据属性,如下所示:
Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
// get all metadata properties
route.getMetadata();
// get a single metadata property
route.getMetadata(someKey);
12.Http超时配置
可以为所有路由配置 HTTP 超时(响应和连接),并为每个特定路由覆盖。
12.1。全局超时
配置全局 http 超时:
connect-timeout必须以毫秒为单位指定。
response-timeout必须指定为 java.time.Duration
spring:
cloud:
gateway:
httpclient:
connect-timeout: 1000
response-timeout: 5s
12.2. 每个路由超时
配置每个路由的超时:
connect-timeout必须以毫秒为单位指定。
response-timeout必须以毫秒为单位指定。
- id: per_route_timeouts
uri: https://example.org
predicates:
- name: Path
args:
pattern: /delay/{timeout}
metadata:
response-timeout: 200
connect-timeout: 200
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeBuilder){
return routeBuilder.routes()
.route("test1", r -> {
return r.host("*.somehost.org").and().path("/somepath")
.filters(f -> f.addRequestHeader("header1", "header-value-1"))
.uri("http://someuri")
.metadata(RESPONSE_TIMEOUT_ATTR, 200)
.metadata(CONNECT_TIMEOUT_ATTR, 200);
})
.build();
}
response-timeout具有负值的每条路由将禁用全局response-timeout值。
- id: per_route_timeouts
uri: https://example.org
predicates:
- name: Path
args:
pattern: /delay/{timeout}
metadata:
response-timeout: -1
13. 流畅的 Java 路由 API
为了在 Java 中进行简单的配置,该RouteLocatorBuilderbean 包含一个流畅的 API。下面的清单显示了它的工作原理:
// static imports from GatewayFilters and RoutePredicates
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder, ThrottleGatewayFilterFactory throttle) {
return builder.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")
.metadata("key", "value")
)
.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")
.metadata("key", "value")
)
.build();
}
这种风格还允许更多自定义谓词断言。bean定义的谓词RouteDefinitionLocator使用逻辑组合and。通过使用流畅的 Java API,您可以在类上使用and()、or()和运算符。negate()Predicate
14.DiscoveryClient路由定义定位器
您可以配置网关以根据在DiscoveryClient兼容服务注册表中注册的服务创建路由。
要启用此功能,请设置spring.cloud.gateway.discovery.locator.enabled=true并确保DiscoveryClient实现(例如 Netflix Eureka、Consul 或 Zookeeper)位于类路径上并启用。
14.1. 为DiscoveryClient路由配置谓词和过滤器
默认情况下,网关为使用DiscoveryClient.
默认谓词是使用模式定义的路径谓词/serviceId/**,其中serviceId是来自 的服务的 ID DiscoveryClient。
默认过滤器是带有正则表达式/serviceId/?(?<remaining>.*)和替换的重写路径过滤器/${remaining}。这会在请求发送到下游之前从路径中剥离服务 ID。
如果要自定义路由使用的谓词或过滤器DiscoveryClient,请设置spring.cloud.gateway.discovery.locator.predicates[x]和spring.cloud.gateway.discovery.locator.filters[y]。执行此操作时,如果您想保留该功能,则需要确保包含前面显示的默认谓词和过滤器。以下示例显示了它的样子:
spring.cloud.gateway.discovery.locator.predicates[0].name: Path
spring.cloud.gateway.discovery.locator.predicates[0].args[pattern]: "'/'+serviceId+'/**'"
spring.cloud.gateway.discovery.locator.predicates[1].name: Host
spring.cloud.gateway.discovery.locator.predicates[1].args[pattern]: "'**.foo.com'"
spring.cloud.gateway.discovery.locator.filters[0].name: CircuitBreaker
spring.cloud.gateway.discovery.locator.filters[0].args[name]: serviceId
spring.cloud.gateway.discovery.locator.filters[1].name: RewritePath
spring.cloud.gateway.discovery.locator.filters[1].args[regexp]: "'/' + serviceId + '/?(?<remaining>.*)'"
spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'"
15. Reactor Netty访问日志
要启用 Reactor Netty 访问日志,请设置-Dreactor.netty.http.server.accessLogEnabled=true。
| 它必须是 Java 系统属性,而不是 Spring Boot 属性。 |
您可以将日志记录系统配置为具有单独的访问日志文件。以下示例创建 Logback 配置:
<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>
16.CORS配置
您可以配置网关以全局或按路由控制 CORS 行为。两者都提供相同的可能性。
16.1. 全局 CORS 配置
“全局”CORS 配置是 URL 模式到Spring FrameworkCorsConfiguration的映射。以下示例配置 CORS:
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: ""
allowedMethods:
- GET
在前面的示例中,允许来自docs.spring.io所有 GET 请求路径的请求发出 CORS 请求。
要为某些网关路由谓词未处理的请求提供相同的 CORS 配置,请将该spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping属性设置为true。true当您尝试支持 CORS 预检请求并且您的路由谓词由于 HTTP 方法为 而无法计算为 时,这非常有用options。
16.2. 路由CORS配置
“route”配置允许将 CORS 直接应用到路由作为带有 key 的元数据cors。与全局配置的情况一样,属性属于Spring FrameworkCorsConfiguration。
如果Path路由中不存在谓词,则将应用“/**”。
|
spring:
cloud:
gateway:
routes:
- id: cors_route
uri: https://example.org
predicates:
- Path=/service/**
metadata:
cors
allowedOrigins: '*'
allowedMethods:
- GET
- POST
allowedHeaders: '*'
maxAge: 30
17.执行器API
执行/gateway器端点允许您监视 Spring Cloud Gateway 应用程序并与之交互。要进行远程访问,必须在应用程序属性中通过 HTTP 或 JMX启用并公开端点。以下清单显示了如何执行此操作:
management.endpoint.gateway.enabled=true # default value
management.endpoints.web.exposure.include=gateway
17.1。详细执行器格式
Spring Cloud Gateway 中添加了一种新的、更详细的格式。它为每个路由添加了更多详细信息,使您可以查看与每个路由关联的谓词和过滤器以及任何可用的配置。以下示例配置/actuator/gateway/routes:
[
{
"predicate": "(Hosts: [**.addrequestheader.org] && Paths: [/headers], match trailing slash: true)",
"route_id": "add_request_header_test",
"filters": [
"[[AddResponseHeader X-Response-Default-Foo = 'Default-Bar'], order = 1]",
"[[AddRequestHeader X-Request-Foo = 'Bar'], order = 1]",
"[[PrefixPath prefix = '/httpbin'], order = 2]"
],
"uri": "lb://testservice",
"order": 0
}
]
该功能默认启用。要禁用它,请设置以下属性:
spring.cloud.gateway.actuator.verbose.enabled=false
这将true在未来版本中默认设置。
17.2. 检索路由过滤器
本节详细介绍如何检索路由过滤器,包括:
17.2.1。全局过滤器
要检索应用于所有路由的全局过滤器GET,请向 发出请求/actuator/gateway/globalfilters。生成的响应类似于以下内容:
{
"org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter@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
}
响应包含现有全局过滤器的详细信息。对于每个全局过滤器,都有过滤器对象的字符串表示形式(例如,org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter@77856cc5)以及过滤器链中相应的顺序。
17.2.2. 路由过滤器
要检索应用于路由的GatewayFilter工厂GET,请向 发出请求/actuator/gateway/routefilters。生成的响应类似于以下内容:
{
"[AddRequestHeaderGatewayFilterFactory@570ed9c configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,
"[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]": null,
"[SaveSessionGatewayFilterFactory@4449b273 configClass = Object]": null
}
响应包含GatewayFilter应用于任何特定路由的工厂的详细信息。对于每个工厂,都有相应对象的字符串表示形式(例如,[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object])。请注意,该null值是由于端点控制器的不完整实现造成的,因为它尝试设置过滤器链中对象的顺序,这不适用于工厂对象GatewayFilter。
17.3。刷新路由缓存
要清除路由缓存,请POST向 发出请求/actuator/gateway/refresh。该请求返回 200,但没有响应正文。
要清除具有特定元数据值的路由,请添加 Query 参数,metadata指定key:value要清除的路由应匹配的对。如果异步刷新过程中出现错误,则刷新不会修改现有路由。
发送POST请求到/actuator/gateway/refresh?metadata=group:group-1只会刷新group元数据为group-1:first_route和 的路由third_route。
[{
"route_id": "first_route",
"route_object": {
"predicate": "...",
},
"metadata": { "group": "group-1" }
},
{
"route_id": "second_route",
"route_object": {
"predicate": "...",
},
"metadata": { "group": "group-2" }
},
{
"route_id": "third_route",
"route_object": {
"predicate": "...",
},
"metadata": { "group": "group-1" }
}]
17.4。检索网关中定义的路由
要检索网关中定义的路由,请GET向 发出请求/actuator/gateway/routes。生成的响应类似于以下内容:
[{
"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
}]
响应包含网关中定义的所有路由的详细信息。下表描述了响应的每个元素(每个元素是一个路由)的结构:
| 小路 | 类型 | 描述 |
|---|---|---|
|
细绳 |
路线 ID。 |
|
目的 |
路由谓词。 |
|
大批 |
工厂申请了该 |
|
数字 |
路线顺序。 |
17.5。检索有关特定路线的信息
要检索有关单个路由的信息,请GET向/actuator/gateway/routes/{id}(例如,/actuator/gateway/routes/first_route)发出请求。生成的响应类似于以下内容:
{
"id": "first_route",
"predicates": [{
"name": "Path",
"args": {"_genkey_0":"/first"}
}],
"filters": [],
"uri": "https://www.uri-destination.org",
"order": 0
}
下表描述了响应的结构:
| 小路 | 类型 | 描述 |
|---|---|---|
|
细绳 |
路线 ID。 |
|
大批 |
路由谓词的集合。每个项目定义给定谓词的名称和参数。 |
|
大批 |
应用于路由的过滤器的集合。 |
|
细绳 |
路由的目标 URI。 |
|
数字 |
路线顺序。 |
17.6。创建和删除特定路径定义
要创建路由定义,请使用指定路由字段的 JSON 正文发出POST请求(请参阅检索有关特定路由的信息)。/gateway/routes/{id_route_to_create}
要删除路由定义,请DELETE向 发出请求/gateway/routes/{id_route_to_delete}。
17.7。创建多个路由定义
要在单个请求中创建多个路由定义,请使用指定路由字段(包括路由 ID)的 JSON 正文发出POST请求(请参阅检索有关特定路由的信息)。/gateway/routes
如果任何路由在创建路由期间引发错误,则路由定义将被丢弃。
17.8。回顾:所有端点的列表
下表总结了 Spring Cloud Gateway 执行器端点(请注意,每个端点都有/actuator/gateway基本路径):
| ID | HTTP方法 | 描述 |
|---|---|---|
|
得到 |
显示应用于路由的全局过滤器列表。 |
|
得到 |
|
|
邮政 |
清除路由缓存。 |
|
得到 |
显示网关中定义的路由列表。 |
|
得到 |
显示有关特定路线的信息。 |
|
邮政 |
添加到网关的新路由。 |
|
删除 |
从网关中删除现有路由。 |
17.9。在多个网关实例之间共享路由
Spring Cloud Gateway 提供两种RouteDefinitionRepository实现。第一个是
InMemoryRouteDefinitionRepository仅存在于一个网关实例的内存中的。这种类型的存储库不适合跨多个网关实例填充路由。
为了在 Spring Cloud Gateway 实例集群之间共享路由,RedisRouteDefinitionRepository可以使用。要启用这种类型的存储库,以下属性必须设置为 true:spring.cloud.gateway.redis-route-definition-repository.enabled
与 RedisRateLimiter Filter Factory 类似,它需要使用 spring-boot-starter-data-redis-reactive Spring Boot 启动器。
18. 故障排除
本节介绍您在使用 Spring Cloud Gateway 时可能出现的常见问题。
18.1. 日志级别
以下记录器可能包含 和DEBUG级别的有价值的故障排除信息TRACE:
-
org.springframework.cloud.gateway -
org.springframework.http.server.reactive -
org.springframework.web.reactive -
org.springframework.boot.autoconfigure.web -
reactor.netty -
redisratelimiter
18.2. 窃听
Reactor NettyHttpClient可以HttpServer启用窃听功能。当与将reactor.netty日志级别设置为DEBUG或结合TRACE使用时,它可以记录信息,例如通过线路发送和接收的标头和正文。要启用窃听,请分别设置和spring.cloud.gateway.httpserver.wiretap=true的或。spring.cloud.gateway.httpclient.wiretap=trueHttpServerHttpClient
19. 开发者指南
这些是编写网关的一些自定义组件的基本指南。
19.1。编写自定义路由谓词工厂
为了编写 Route Predicate,您需要将其实现RoutePredicateFactory为 bean。有一个名为AbstractRoutePredicateFactory您可以扩展的抽象类。
@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {
public MyRoutePredicateFactory() {
super(Config.class);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
// grab configuration from Config object
return exchange -> {
//grab the request
ServerHttpRequest request = exchange.getRequest();
//take information from the request to see if it
//matches configuration.
return matches(config, request);
};
}
public static class Config {
//Put the configuration properties for your filter here
}
}
19.2。编写自定义 GatewayFilter 工厂
要编写GatewayFilter,您必须将其实现GatewayFilterFactory为 bean。您可以扩展一个名为 的抽象类AbstractGatewayFilterFactory。以下示例展示了如何执行此操作:
@Component
public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory<PreGatewayFilterFactory.Config> {
public PreGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
// grab configuration from Config object
return (exchange, chain) -> {
//If you want to build a "pre" filter you need to manipulate the
//request before calling chain.filter
ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
//use builder to manipulate the request
return chain.filter(exchange.mutate().request(builder.build()).build());
};
}
public static class Config {
//Put the configuration properties for your filter here
}
}
@Component
public class PostGatewayFilterFactory extends AbstractGatewayFilterFactory<PostGatewayFilterFactory.Config> {
public PostGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
// grab configuration from Config object
return (exchange, chain) -> {
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
ServerHttpResponse response = exchange.getResponse();
//Manipulate the response in some way
}));
};
}
public static class Config {
//Put the configuration properties for your filter here
}
}
19.2.1。在配置中命名自定义过滤器和引用
自定义过滤器类名称应以GatewayFilterFactory.
例如,要引用Something配置文件中命名的过滤器,该过滤器必须位于名为 的类中SomethingGatewayFilterFactory。
可以创建不带后缀的网关过滤器
GatewayFilterFactory,例如class AnotherThing. 该过滤器可以在配置文件中引用AnotherThing。这不是受支持的命名约定,并且此语法可能会在未来版本中删除。请更新过滤器名称以使其符合要求。
|
19.3。编写自定义全局过滤器
要编写自定义全局过滤器,您必须将GlobalFilter接口实现为 bean。这会将过滤器应用于所有请求。
以下示例分别展示了如何设置全局前置过滤器和后置过滤器:
@Bean
public GlobalFilter customGlobalFilter() {
return (exchange, chain) -> exchange.getPrincipal()
.map(Principal::getName)
.defaultIfEmpty("Default User")
.map(userName -> {
//adds header to proxied request
exchange.getRequest().mutate().header("CUSTOM-REQUEST-HEADER", userName).build();
return exchange;
})
.flatMap(chain::filter);
}
@Bean
public GlobalFilter customGlobalPostFilter() {
return (exchange, chain) -> chain.filter(exchange)
.then(Mono.just(exchange))
.map(serverWebExchange -> {
//adds header to response
serverWebExchange.getResponse().getHeaders().set("CUSTOM-RESPONSE-HEADER",
HttpStatus.OK.equals(serverWebExchange.getResponse().getStatusCode()) ? "It worked": "It did not work");
return serverWebExchange;
})
.then();
}
20. 使用 Spring MVC 或 Webflux 构建简单网关
| 下面描述另一种风格的网关。先前的文档均不适用于以下内容。 |
Spring Cloud Gateway 提供了一个名为 的实用程序对象ProxyExchange。您可以在常规 Spring Web 处理程序中将其用作方法参数。它通过镜像 HTTP 动词的方法支持基本的下游 HTTP 交换。使用MVC,它还支持通过forward()方法转发到本地处理程序。要使用ProxyExchange,请在类路径中包含正确的模块( 或spring-cloud-gateway-mvc)spring-cloud-gateway-webflux。
以下 MVC 示例将/test下游请求代理到远程服务器:
@RestController
@SpringBootApplication
public class GatewaySampleApplication {
@Value("${remote.home}")
private URI home;
@GetMapping("/test")
public ResponseEntity<?> proxy(ProxyExchange<byte[]> proxy) throws Exception {
return proxy.uri(home.toString() + "/image/png").get();
}
}
以下示例使用 Webflux 执行相同的操作:
@RestController
@SpringBootApplication
public class GatewaySampleApplication {
@Value("${remote.home}")
private URI home;
@GetMapping("/test")
public Mono<ResponseEntity<?>> proxy(ProxyExchange<byte[]> proxy) throws Exception {
return proxy.uri(home.toString() + "/image/png").get();
}
}
方便的方法使ProxyExchange处理程序方法能够发现并增强传入请求的 URI 路径。例如,您可能想要提取路径的尾部元素以将它们传递到下游:
@GetMapping("/proxy/path/**")
public ResponseEntity<?> proxyPath(ProxyExchange<byte[]> proxy) throws Exception {
String path = proxy.path("/proxy/path/");
return proxy.uri(home.toString() + "/foos/" + path).get();
}
Spring MVC 和 Webflux 的所有功能均可用于网关处理程序方法。因此,例如,您可以注入请求标头和查询参数,并且可以使用映射注释中的声明来约束传入请求。@RequestMapping有关这些功能的更多详细信息,请参阅 Spring MVC 中的文档。
header()您可以使用上的方法向下游响应添加标头ProxyExchange。
您还可以通过向方法(和其他方法)添加映射器来操作响应标头(以及响应中您喜欢的任何其他内容)get()。映射器是一种Function接收传入ResponseEntity并将其转换为传出的映射器。
为不向下游传递的“敏感”标头(默认情况下cookie为 和)以及“代理”( ) 标头提供一流的支持。authorizationx-forwarded-*
21. AOT 和本机映像支持
自 以来4.0.0,Spring Cloud Gateway 支持 Spring AOT 转换和本机映像。
如果您使用负载平衡路由,则需要显式定义LoadBalancerClient服务 ID。您可以通过使用注释的value或属性或作为属性的值来执行此操作。
name@LoadBalancerClientspring.cloud.loadbalancer.eager-load.clients |