【Spring Cloud】Spring Cloud Gateway操作手册(中文版)

1. 如何包含 Spring Cloud Gateway

要将 Spring Cloud Gateway 包含在您的项目中,请使用带有 org.springframework.cloud group ID 和 spring-cloud-starter-gateway artifact ID 的启动器。有关如何使用当前 Spring Cloud Release Train 设置构建系统的详细信息,请参见 Spring Cloud 项目页面。

如果您包含了启动器但不希望启用网关,可以设置 spring.cloud.gateway.enabled=false

2. 术语表

  • 路由 (Route): 网关的基本构建块。它由 ID、目标 URI、断言集合和过滤器集合定义。如果聚合断言为真,则匹配该路由。

  • 断言 (Predicate): 这是一个 Java 8 函数式断言。输入类型是 Spring Framework 的 ServerWebExchange。它允许您匹配来自 HTTP 请求的任何内容,如头或参数。

  • 过滤器 (Filter): 这些是使用特定工厂构建的 GatewayFilter 实例。在这里,您可以在发送下游请求之前或之后修改请求和响应。

3. 如何工作

以下图表提供了 Spring Cloud Gateway 工作方式的高级概述:

img

客户端向 Spring Cloud Gateway 发送请求。如果 Gateway Handler Mapping 确定请求匹配某个路由,则将其发送到 Gateway Web Handler。这个处理器会将请求运行通过特定于请求的过滤器链。

过滤器由虚线分隔的原因是因为过滤器可以在发送代理请求之前和之后运行逻辑。首先执行所有“预”过滤器逻辑。然后发起代理请求。代理请求完成后,运行“后”过滤器逻辑。

在路由中定义的 URIs,如果没有指定端口,则 HTTP 和 HTTPS URIs 分别默认使用端口 80 和 443。

4. 配置路由断言工厂和网关过滤器工厂

有两种配置断言和过滤器的方法:快捷方式和完全展开的参数。下面的大多数示例使用快捷方式。

名称和参数名称在每个部分的前两句话中以 代码 形式列出。参数通常按快捷配置所需的顺序列出。

4.1. 快捷配置

快捷配置由过滤器名称、等号 (=) 和由逗号 (,) 分隔的参数值组成。

application.yml 示例:

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - Cookie=mycookie,mycookievalue

前面的示例定义了 Cookie 路由断言工厂,它有两个参数,cookie 名称 mycookie 和要匹配的值 mycookievalue

4.2. 完全展开的参数

完全展开的参数看起来更像是标准 yaml 配置,具有名称/值对。通常,会有一个 name 键和一个 args 键。args 键是一个键值对映射,用于配置断言或过滤器。

application.yml 示例:

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 WebFlux HandlerMapping 基础设施的一部分匹配路由。Spring Cloud Gateway 包括许多内置的路由断言工厂。所有这些断言都匹配 HTTP 请求的不同属性。您可以使用逻辑 and 语句组合多个路由断言工厂。

5.1. After 路由断言工厂

After 路由断言工厂接受一个参数,datetime(这是一个 Java ZonedDateTime)。这个断言匹配指定 datetime 之后发生的请求。

以下示例配置了一个 after 路由断言:

application.yml 示例:

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 Mountain Time (Denver) 之后发起的请求。

5.2. Before 路由断言工厂

Before 路由断言工厂接受一个参数,datetime(这是一个 Java ZonedDateTime)。这个断言匹配指定 datetime 之前发生的请求。

以下示例配置了一个 before 路由断言:

application.yml 示例:

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 Mountain Time (Denver) 之前发起的请求。

5.3. Between 路由断言工厂

Between 路由断言工厂接受两个参数,datetime1datetime2,它们是 Java ZonedDateTime 对象。这个断言匹配 datetime1 之后和 datetime2 之前发生的请求。datetime2 参数必须在 datetime1 之后。

以下示例配置了一个 between 路由断言:

application.yml 示例:

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 Mountain Time (Denver) 之后和 2017 年 1 月 21 日 17:42 Mountain Time (Denver) 之前发起的请求。这可以用于维护窗口。

5.4. Cookie 路由断言工厂

Cookie 路由断言工厂接受两个参数,cookie 的 name 和一个 regexp(这是一个 Java 正则表达式)。这个断言匹配具有给定名称且其值与正则表达式匹配的 cookie。

以下示例配置了一个 cookie 路由断言工厂:

application.yml 示例:

spring:
  cloud:
    gateway:
      routes:
      - id: cookie_route
        uri: https://example.org
        predicates:
        - Cookie=chocolate, ch.p

这个路由匹配请求中有一个名为 chocolate 的 cookie,其值匹配 ch.p 正则表达式。

5.5 Header路由断言工厂

Header 路由断言工厂接受两个参数,header 和一个 regexp(这是一个 Java 正则表达式)。这个断言匹配具有给定名称且其值与正则表达式匹配的 header。

以下示例配置了一个 header 路由断言:

application.yml 示例:

spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: https://example.org
        predicates:
        - Header=X-Request-Id, \d+

这个路由匹配如果请求具有一个名为 X-Request-Id 的 header,其值匹配 \d+ 正则表达式(即,它有一个或多个数字的值)。

5.6. Host 路由断言工厂

Host 路由断言工厂接受一个参数:一个主机名 patterns 列表。模式是使用 . 作为分隔符的 Ant 风格模式。

这个断言匹配匹配模式的 Host 头。

以下示例配置了一个 host 路由断言:

application.yml 示例:

spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: https://example.org
        predicates:
        - Host=**.somehost.org,**.anotherhost.org

URI 模板变量(例如 {sub}.myhost.org)也受到支持。

这个路由匹配如果请求具有 Host 头的值为 www.somehost.orgbeta.somehost.orgwww.anotherhost.org

这个断言还提取 URI 模板变量(如前面的示例中定义的 sub)作为名称和值的映射,并将其放置在 ServerWebExchange.getAttributes() 中,使用 ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE 中定义的键。然后,这些值可供 GatewayFilter 工厂使用。

5.7. Method 路由断言工厂

Method 路由断言工厂接受一个 methods 参数,这是一或多个参数:要匹配的 HTTP 方法。

以下示例配置了一个方法路由断言:

application.yml 示例:

spring:
  cloud:
    gateway:
      routes:
      - id: method_route
        uri: https://example.org
        predicates:
        - Method=GET,POST

这个路由匹配如果请求方法是 GETPOST

5.8. Path 路由断言工厂

Path 路由断言工厂接受两个参数:Spring PathMatcher patterns 的列表和可选的标志 matchTrailingSlash(默认为 true)。

以下示例配置了一个路径路由断言:

application.yml 示例:

spring:
  cloud:
    gateway:
      routes:
      - id: path_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment},/blue/{segment}

如果请求路径是 /red/1/red/1//red/blue/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 路由断言工厂

Query 路由断言工厂接受两个参数:一个必需的 param 和一个可选的 regexp(这是一个 Java 正则表达式)。

以下示例配置了一个查询路由断言:

application.yml 示例:

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=green

如果请求包含一个 green 查询参数,则前面的路由匹配。

application.yml 示例:

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=red, gree.

如果请求包含一个 red 查询参数,其值匹配 gree. 正则表达式,那么前面的路由匹配,因此 greengreet 将匹配。

5.10. RemoteAddr 路由断言工厂

RemoteAddr 路由断言工厂接受一个列表(最小大小为 1)的 sources,这些是 CIDR 表示法(IPv4 或 IPv6)字符串,例如 192.168.0.1/16(其中 192.168.0.1 是 IP 地址,16 是子网掩码)。

以下示例配置了一个 RemoteAddr 路由断言:

application.yml 示例:

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::trustAll 返回一个 RemoteAddressResolver,它总是采用 X-Forwarded-For 头中的第一个 IP 地址。这种方法容易受到欺骗,因为恶意客户端可以为 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结果
[Integer.MIN_VALUE, 0](无效,在初始化期间抛出 IllegalArgumentException
10.0.0.3
20.0.0.2
30.0.0.1
[4, Integer.MAX_VALUE]0.0.0.1

以下示例展示了如何使用 Java 实现相同的配置:

示例 11. GatewayConfig.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();
}

5.11. Weight 路由断言工厂

Weight 路由断言工厂接受两个参数:groupweight(一个整数)。权重是按组计算的。

以下示例配置了一个权重路由断言:

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

5.12. XForwarded Remote Addr 路由断言工厂

XForwarded Remote Addr 路由断言工厂接受一个列表(最小大小为 1)的 sources,这些是 CIDR 表示法(IPv4 或 IPv6)字符串,例如 192.168.0.1/16(其中 192.168.0.1 是 IP 地址,16 是子网掩码)。

这个路由断言允许基于 X-Forwarded-For HTTP 头过滤请求。

这可以与反向代理如负载均衡器或 Web 应用程序防火墙一起使用,其中请求只有在来自这些反向代理使用的受信任 IP 地址列表时才被允许。

以下示例配置了一个 XForwardedRemoteAddr 路由断言:

application.yml 示例:

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 工厂。

6.1. AddRequestHeader

AddRequestHeader GatewayFilter 工厂接受 namevalue 参数。

以下示例配置了一个 AddRequestHeader GatewayFilter:

示例 14. application.yml

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:

示例 15. application.yml

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

AddRequestHeadersIfNotPresent GatewayFilter 工厂接受由冒号分隔的 namevalue 对集合。

以下示例配置了一个 AddRequestHeadersIfNotPresent GatewayFilter:

示例 16. application.yml

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

这个配置为所有匹配的请求向下游请求的头中添加了两个头 X-Request-Color-1:blueX-Request-Color-2:green。这类似于 AddRequestHeader 的工作方式,但与 AddRequestHeader 不同的是,只有在头不已经存在的情况下才会添加它们。否则,将发送客户端请求中的原始值。

此外,要设置多值头,可以使用头名称多次,如 AddRequestHeadersIfNotPresent=X-Request-Color-1:blue,X-Request-Color-1:green

AddRequestHeadersIfNotPresent 还支持 URI 变量,这些变量用于匹配路径或主机。URI 变量可以在值中使用,并在运行时展开。以下示例配置了一个使用变量的 AddRequestHeadersIfNotPresent GatewayFilter:

示例 17. application.yml

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

AddRequestParameter GatewayFilter 工厂接受 namevalue 参数。

以下示例配置了一个 AddRequestParameter GatewayFilter:

示例 18. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_parameter_route
        uri: https://example.org
        filters:
        - AddRequestParameter=red, blue

这个配置将为所有匹配的请求向下游请求的查询字符串中添加 red=blue

AddRequestParameter 能够识别用于匹配路径或主机的 URI 变量。URI 变量可以在值中使用,并在运行时展开。以下示例配置了一个使用变量的 AddRequestParameter GatewayFilter:

示例 19. application.yml

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

AddResponseHeader GatewayFilter 工厂接受 namevalue 参数。

以下示例配置了一个 AddResponseHeader GatewayFilter:

示例 20. application.yml

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:

示例 21. application.yml

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

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

示例 22. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: circuitbreaker_route
        uri: https://example.org
        filters:
        - CircuitBreaker=myCircuitBreaker

要配置断路器,请参见您使用的底层断路器实现的配置。

  • Resilience4J 文档

Spring Cloud CircuitBreaker 过滤器还可以接受一个可选的 fallbackUri 参数。目前,仅支持 forward: 方案的 URI。

如果调用了回退,请求将转发到与 URI 匹配的控制器。

以下示例配置了这样的回退:

示例 23. application.yml

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 形式完成了相同的操作:

示例 24. Application.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 负载均衡(由目的 URI 上的 lb 前缀定义)。

断路器还支持 fallbackUri 中的 URI 变量。这允许更复杂的路由选项,例如使用 PathPattern 表达式转发原始主机或 URL 路径的部分。

在下面的示例中,调用 consumingServiceEndpoint/users/1 将被重定向到 inCaseOfFailureUseThis/users/1

示例 25. application.yml

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 来定义网关应用程序内的内部控制器或处理器。然而,您也可以将请求重新路由到外部应用程序中的控制器或处理器,如下所示:

示例 26. application.yml

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 枚举的字符串表示。

示例 27. application.yml

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"

示例 28. Application.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").addStatusCode("INTERNAL_SERVER_ERROR")))
                .rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088"))
        .build();
}

6.6. CacheRequestBody

在某些情况下,需要读取请求体。由于请求体只能读取一次,因此需要缓存请求体。您可以使用 CacheRequestBody 过滤器在将其发送下游之前缓存请求体,并从 exchange 属性中获取体。

以下列表展示了如何缓存请求体 GatewayFilter

示例 29. application.yml

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)。然后,它将体放置在 ServerWebExchange.getAttributes() 可用的属性中,使用 ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR 中定义的键。

注意:此过滤器仅适用于 HTTP(包括 HTTPS)请求。

6.7. DedupeResponseHeader

DedupeResponseHeader GatewayFilter 工厂接受 name 参数和可选的 strategy 参数。name 可以包含一个由空格分隔的头名称列表。

以下示例配置了一个 DedupeResponseHeader GatewayFilter:

示例 30. application.yml

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-CredentialsAccess-Control-Allow-Origin 响应头的重复值。

DedupeResponseHeader 过滤器还接受一个可选的 strategy 参数。接受的值为 RETAIN_FIRST(默认)、RETAIN_LASTRETAIN_UNIQUE

6.8. FallbackHeaders

FallbackHeaders 工厂允许您在请求被转发到外部应用程序的 fallbackUri 时,在请求头中添加 Spring Cloud CircuitBreaker 执行异常的详细信息,如下所示:

示例 31. application.yml

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

在此示例中,当在运行断路器时发生执行异常,请求将被转发到 localhost:9994 上运行的应用程序的 fallback 端点或处理器。FallbackHeaders 过滤器通过添加异常类型、消息(如果可用的话)以及根原因异常类型和消息的头,来修改该请求。

您可以通过在配置中设置以下参数的值来覆盖头的名称(显示了默认值):

  • executionExceptionTypeHeaderName (“Execution-Exception-Type”)
  • executionExceptionMessageHeaderName (“Execution-Exception-Message”)
  • rootCauseExceptionTypeHeaderName (“Root-Cause-Exception-Type”)
  • rootCauseExceptionMessageHeaderName (“Root-Cause-Exception-Message”)

有关断路器和网关的更多信息,请参阅 Spring Cloud CircuitBreaker 工厂部分。

6.9. JsonToGrpc

JSONToGRPCFilter GatewayFilter 工厂将 JSON 负载转换为 gRPC 请求。

该过滤器接受以下参数:

  • protoDescriptor: Proto 描述文件。

    该文件可以使用 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: Proto 定义文件。

  • service: 处理请求的服务的短名称。

  • method: 处理请求的服务中的方法名称。

    注意:不支持流式传输。

application.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))
            .build();
}
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。

默认情况下,它通过使用默认的 TrustManagerFactory 创建一个 NettyChannel。但是,您可以通过创建一个 GrpcSslConfigurer 类型的 bean 来自定义此 TrustManager

@Configuration
public class GRPCLocalConfiguration {
    @Bean
    public GRPCSSLContext sslContext() {
        TrustManager trustManager = trustAllCerts();
        return new GRPCSSLContext(trustManager);
    }
}

6.10. LocalResponseCache 网关过滤器工厂

此过滤器允许缓存响应体和头,遵循以下规则:

  • 它只能缓存无体的 GET 请求。
  • 它仅在以下状态码之一的情况下缓存响应:HTTP 200 (OK)、HTTP 206 (Partial Content) 或 HTTP 301 (Moved Permanently)。
  • 如果 Cache-Control 头不允许(请求中存在 no-store 或响应中存在 no-storeprivate),则不缓存响应数据。
  • 如果响应已经被缓存,并且新请求在 Cache-Control 头中使用了 no-cache 值,它将返回一个无体的响应,状态码为 304 (Not Modified)。

此过滤器按路由配置本地响应缓存,并且只有在启用了 spring.cloud.gateway.filter.local-response-cache.enabled 属性时才可用。还有一个全局配置的本地响应缓存作为特性提供。

它接受第一个参数以覆盖缓存项过期的时间(以 s 表示秒,m 表示分钟,h 表示小时),第二个参数设置为此路由的缓存最大大小以逐出条目(使用 KBMBGB)。

以下列表显示了如何添加本地响应缓存 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();
}

或者这样

application.yaml

spring:
  cloud:
    gateway:
      routes:
      - id: resource
        uri: http://localhost:9000
        predicates:
        - Path=/resource
        filters:
        - LocalResponseCache=30m,500MB
注意
此过滤器还自动计算 HTTP Cache-Control 头中的 max-age 值。仅当原始响应中存在 max-age 时,才使用 timeToLive 配置参数中设置的秒数重写该值。在连续调用中,该值将根据响应到期前剩余的秒数重新计算。
要启用此特性,请将 com.github.ben-manes.caffeine:caffeinespring-boot-starter-cache 添加为项目依赖。
如果您的项目创建了自定义 CacheManager beans,它将需要使用 @Primary 标记或使用 @Qualifier 注入。

MapRequestHeader 网关过滤器工厂接受 fromHeadertoHeader 参数。它创建一个新的命名头 (toHeader),值从传入的 HTTP 请求的现有命名头 (fromHeader) 中提取。如果输入头不存在,则过滤器无影响。如果新命名头已经存在,则其值与新值合并。

以下示例配置了一个 MapRequestHeader

示例 32. application.yml

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 网关过滤器工厂

您可以使用 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 网关过滤器工厂

您可以使用 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 网关过滤器工厂

PrefixPath 网关过滤器工厂接受一个单一的 prefix 参数。

以下示例配置了一个 PrefixPath 网关过滤器:

示例 33. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
        filters:
        - PrefixPath=/mypath

这将为所有匹配请求的路径添加前缀 /mypath。因此,对 /hello 的请求将被发送到 /mypath/hello

6.15 PreserveHostHeader网关过滤器工厂

PreserveHostHeader 网关过滤器工厂没有参数。此过滤器设置了一个请求属性,路由过滤器检查该属性以确定是否应发送原始主机头,而不是由 HTTP 客户端确定的主机头。

以下示例配置了一个 PreserveHostHeader 网关过滤器:

示例 34. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: preserve_host_route
        uri: https://example.org
        filters:
        - PreserveHostHeader

6.16. RedirectTo 网关过滤器工厂

RedirectTo 网关过滤器工厂接受三个参数:statusurl 和可选的 includeRequestParams

status 参数应该是一个 300 系列的重定向 HTTP 状态码,例如 301。

url 参数应该是一个有效的 URL。这是 Location 头的值。

includeRequestParams 参数指示是否应在 url 上包含请求查询参数。如果未设置,则视为 false

对于相对重定向,您应该使用 uri: no://op 作为您的路由定义的 uri。

以下列表配置了一个 RedirectTo 网关过滤器:

示例 35. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
        filters:
        - RedirectTo=302, https://acme.org

这将发送状态 302 和一个 Location:https://acme.org 头来执行重定向。

以下示例配置了一个 RedirectTo 网关过滤器,并将 includeRequestParams 设置为 true

application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
        filters:
        - RedirectTo=302, https://acme.org, true

当向网关发出带有查询 ?skip=10 的请求时,网关将发送状态 302 和一个 Location:https://acme.org?skip=10 头来执行重定向。

6.17. RemoveJsonAttributesResponseBody 网关过滤器工厂

RemoveJsonAttributesResponseBody 网关过滤器工厂接受一组要搜索的 attribute names,列表中的最后一个可选参数可以是一个布尔值,指示是否仅在根级别(如果参数配置的末尾没有出现,则为默认值 false)或递归地(true)删除这些属性。

它提供了一种方便的方法,通过对 JSON 体内容应用转换来删除其中的属性。

以下示例配置了一个 RemoveJsonAttributesResponseBody 网关过滤器:

示例 36. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: removejsonattributes_route
        uri: https://example.org
        filters:
        - RemoveJsonAttributesResponseBody=id,color

这将在根级别从 JSON 内容体中删除 “id” 和 “color” 属性。

以下示例配置了一个使用可选最后一个参数的 RemoveJsonAttributesResponseBody 网关过滤器:

示例 37. application.yml

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 网关过滤器工厂接受一个 name 参数。它是要删除的头的名称。

以下列表配置了一个 RemoveRequestHeader 网关过滤器:

示例 38. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: removerequestheader_route
        uri: https://example.org
        filters:
        - RemoveRequestHeader=X-Request-Foo

这将在将其发送下游之前删除 X-Request-Foo 头。

6.19. RemoveRequestParameter 网关过滤器工厂

RemoveRequestParameter 网关过滤器工厂接受一个 name 参数。它是要删除的查询参数的名称。

以下示例配置了一个 RemoveRequestParameter 网关过滤器:

示例 39. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: removerequestparameter_route
        uri: https://example.org
        filters:
        - RemoveRequestParameter=red

这将在将其发送下游之前删除 red 参数。

6.20 RemoveResponseHeader 网关过滤器工厂

RemoveResponseHeader 网关过滤器工厂接受一个 name 参数。它是要删除的头的名称。

以下列表配置了一个 RemoveResponseHeader 网关过滤器:

示例 40. application.yml

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 网关过滤器工厂

RequestHeaderSize 网关过滤器工厂接受 maxSizeerrorHeaderName 参数。

maxSize 参数是请求头允许的最大数据大小(包括键和值)。errorHeaderName 参数设置了包含错误消息的响应头的名称,默认为 “errorMessage”。

以下列表配置了一个 RequestHeaderSize 网关过滤器:

示例 41. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: requestheadersize_route
        uri: https://example.org
        filters:
        - RequestHeaderSize=1000B

如果任何请求头的大小超过 1000 字节,这将发送状态 431。

6.22. RequestRateLimiter 网关过滤器工厂

RequestRateLimiter 网关过滤器工厂使用 RateLimiter 实现来确定当前请求是否被允许继续。如果不是,将返回默认状态 HTTP 429 - Too Many Requests

此过滤器接受一个可选的 keyResolver 参数和特定于速率限制器的参数(稍后在本节中描述)。

keyResolver 是实现 KeyResolver 接口的一个 bean。在配置中,使用 SpEL 引用 bean 的名称。#{@myKeyResolver} 是一个 SpEL 表达式,引用了一个名为 myKeyResolver 的 bean。

以下列表显示了 KeyResolver 接口:

示例 42. KeyResolver.java

public interface KeyResolver {
    Mono<String> resolve(ServerWebExchange exchange);
}

KeyResolver 接口允许插入式策略派生限制请求的键。在未来的里程碑版本中,将有一些 KeyResolver 实现。

默认的 KeyResolver 实现是 PrincipalNameKeyResolver,它从 ServerWebExchange 中检索 Principal 并调用 Principal.getName()

默认情况下,如果 KeyResolver 找不到键,将拒绝请求。您可以通过设置 spring.cloud.gateway.filter.request-rate-limiter.deny-empty-keytruefalse)和 spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code 属性来调整这种行为。

RequestRateLimiter 不能用“快捷”符号进行配置。以下示例是无效的:

示例 43. application.properties

# INVALID SHORTCUT CONFIGURATION
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}
6.22.1. Redis RateLimiter

Redis 实现基于 Stripe 的工作。它需要使用 spring-boot-starter-data-redis-reactive Spring Boot 启动器。

redis-rate-limiter.replenishRate 属性定义了每秒允许的请求数(没有任何丢弃的请求)。这是令牌桶填充的速率。

redis-rate-limiter.burstCapacity 属性是用户在一秒钟内允许的最大请求数(没有任何丢弃的请求)。这是令牌桶可以容纳的令牌数。将此值设置为零将阻止所有请求。

redis-rate-limiter.requestedTokens 属性是每个请求的成本。这是每个请求从桶中取出的令牌数,默认为 1

通过设置相同的 replenishRateburstCapacity 值,可以实现稳定速率。通过将 burstCapacity 设置为高于 replenishRate,可以允许临时突发。在这种情况下,由于 replenishRate,速率限制器需要在突发之间允许一些时间,因为连续两个突发会导致丢弃请求(HTTP 429 - Too Many Requests)。

以下列表配置了一个 redis-rate-limiter

低于 1 request/s 的速率限制可以通过将 replenishRate 设置为所需的请求数,requestedTokens 设置为秒数的时间跨度,burstCapacity 设置为 replenishRaterequestedTokens 的乘积来实现。例如,设置 replenishRate=1requestedTokens=60burstCapacity=60 将限制为 1 request/min

.application.yml

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

以下示例在 Java 中配置了一个 KeyResolver

示例 44. Config.java

@Bean
KeyResolver userKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}

这定义了每个用户的请求速率限制为 10。允许 20 的突发,但接下来一秒钟只有 10 个请求可用。KeyResolver 是一个简单的实现,它获取 user 请求参数。注意:这不是生产推荐的做法。

您还可以定义一个实现 RateLimiter 接口的 bean 作为速率限制器。在配置中,您可以使用 SpEL 引用 bean 的名称。#{@myRateLimiter} 是一个 SpEL 表达式,引用了一个名为 myRateLimiter 的 bean。以下列表定义了一个使用前面定义的 KeyResolver 的速率限制器:

示例 45. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: https://example.org
        filters:
        - name: RequestRateLimiter
          args:
            rate-limiter: "#{@myRateLimiter}"
            key-resolver: "#{@userKeyResolver}"

6.23 RewriteLocationResponseHeader网关过滤器工厂

RewriteLocationResponseHeader 网关过滤器工厂修改 Location 响应头的值,通常是为了去掉后端特定的详细信息。它接受 stripVersionModelocationHeaderNamehostValueprotocolsRegex 参数。

以下列表配置了一个 RewriteLocationResponseHeader 网关过滤器:

示例 46. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: rewritelocationresponseheader_route
        uri: http://example.org
        filters:        - RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,

stripVersionMode 参数有以下可能的值:NEVER_STRIPAS_IN_REQUEST(默认)和 ALWAYS_STRIP

  • NEVER_STRIP:即使原始请求路径不包含版本,也不会剥离版本。
  • AS_IN_REQUEST:仅当原始请求路径不包含版本时,才剥离版本。
  • ALWAYS_STRIP:即使原始请求路径包含版本,也总是剥离版本。

如果提供了 hostValue 参数,则用于替换响应 Location 头中的 host:port 部分。如果没有提供,将使用 Host 请求头的值。

protocolsRegex 参数必须是有效的 regex String,用于匹配协议名称。如果没有匹配,过滤器将不执行任何操作。默认值为 http|https|ftp|ftps

6.24. RewritePath 网关过滤器工厂

RewritePath 网关过滤器工厂接受一个路径 regexp 参数和一个 replacement 参数。它使用 Java 正则表达式灵活地重写请求路径。

以下列表配置了一个 RewritePath 网关过滤器:

示例 47. application.yml

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. RewriteRequestParameter 网关过滤器工厂

RewriteRequestParameter 网关过滤器工厂接受一个 name 参数和一个 replacement 参数。它将重写给定 name 的请求参数的值。如果设置了多个具有相同 name 的请求参数,它们将被替换为单个值。如果没有找到请求参数,则不进行任何更改。

以下列表配置了一个 RewriteRequestParameter 网关过滤器:

示例 48. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: rewriterequestparameter_route
        uri: https://example.org
        predicates:
        - Path=/products
        filters:
        - RewriteRequestParameter=campaign,fall2023

对于 /products?campaign=old 的请求,这将请求参数设置为 campaign=fall2023

6.26 RewriteResponseHeader 网关过滤器工厂

RewriteResponseHeader 网关过滤器工厂接受 nameregexpreplacement 参数。它使用 Java 正则表达式灵活地重写响应头的值。

以下示例配置了一个 RewriteResponseHeader 网关过滤器:

示例 49. application.yml

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 的头值,在发出下游请求后,它将被设置为 /42?user=ford&password=***&flag=true。由于 YAML 规范,您必须使用 $\ 来表示 $

6.27. SaveSession 网关过滤器工厂

SaveSession 网关过滤器工厂在将调用转发到下游之前,强制执行 WebSession::save 操作。当使用像 Spring Session 这样的惰性数据存储时,这特别有用,您需要确保在发出转发调用之前会话状态已被保存。

以下示例配置了一个 SaveSession 网关过滤器:

示例 50. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: save_session
        uri: https://example.org
        predicates:
        - Path=/foo/**
        filters:
        - SaveSession

如果您将 Spring Security 与 Spring Session 集成,并希望确保安全细节已转发到远程进程,这很关键。

6.28 SecureHeaders网关过滤器工厂

SecureHeaders 网关过滤器工厂根据本博客文章中的建议,向响应添加多个头。

添加了以下头(显示了默认值):

  • 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.29. SetPath 网关过滤器工厂

SetPath 网关过滤器工厂接受一个路径 template 参数。它提供了一种简单的方法来通过允许路径的模板化段来操作请求路径。它使用了 Spring Framework 的 URI 模板。允许多个匹配段。

以下示例配置了一个 SetPath 网关过滤器:

示例 51. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: setpath_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment}
        filters:
        - SetPath=/{segment}

对于 /red/blue 的请求路径,这在发出下游请求之前将路径设置为 /blue

6.30. SetRequestHeader网关过滤器工厂

SetRequestHeader 网关过滤器工厂接受 namevalue 参数。

以下列表配置了一个 SetRequestHeader 网关过滤器:

示例 52. application.yml

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 网关过滤器:

示例 53. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: setrequestheader_route
        uri: https://example.org
        predicates:
        - Host: {segment}.myhost.org
        filters:
        - SetRequestHeader=foo, bar-{segment}

6.31. SetResponseHeader网关过滤器工厂

SetResponseHeader 网关过滤器工厂接受 namevalue 参数。

以下列表配置了一个 SetResponseHeader 网关过滤器:

示例 54. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: setresponseheader_route
        uri: https://example.org
        filters:
        - SetResponseHeader=X-Response-Red, Blue

这个网关过滤器替换(而不是添加)给定名称的所有头。因此,如果下游服务器响应了 X-Response-Red:1234,它将被替换为 X-Response-Red:Blue,这就是网关客户端将接收到的。

SetResponseHeader 知道用于匹配路径或主机的 URI 变量。URI 变量可以在值中使用,并在运行时展开。

以下示例配置了一个使用变量的 SetResponseHeader 网关过滤器:

示例 55. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: setresponseheader_route
        uri: https://example.org
        predicates:
        - Host: {segment}.myhost.org
        filters:
        - SetResponseHeader=foo, bar-{segment}

6.32. SetStatus 网关过滤器工厂

SetStatus 网关过滤器工厂接受一个单一的 status 参数。它必须是有效的 Spring HttpStatus。它可以是整数值 404 或枚举的字符串表示:NOT_FOUND

以下列表配置了一个 SetStatus 网关过滤器:

示例 56. application.yml

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 网关过滤器,以在响应头中返回代理请求的原始 HTTP 状态码。如果使用以下属性进行配置,则将头添加到响应中:

示例 57. application.yml

spring:
  cloud:
    gateway:
      set-status:
        original-status-header-name: original-http-status

6.33. StripPrefix 网关过滤器工厂

StripPrefix 网关过滤器工厂接受一个 parts 参数。parts 参数指示在将请求发送到下游之前,要从请求中剥离的路径部分数。

以下列表配置了一个 StripPrefix 网关过滤器:

示例 58. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: nameRoot
        uri: https://nameservice
        predicates:
        - Path=/name/**
        filters:
        - StripPrefix=2

当通过网关向 /name/blue/red 发出请求时,向 nameservice 发出的请求看起来像 nameservice/red

6.34. Retry 网关过滤器工厂

Retry 网关过滤器工厂支持以下参数:

  • 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:GET 方法
  • exceptionsIOExceptionTimeoutException
  • backoff:禁用

以下列表配置了一个 Retry 网关过滤器:

示例 59. 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
            methods: GET,POST
            backoff:
              firstBackoff: 10ms
              maxBackoff: 50ms
              factor: 2
              basedOnPreviousValue: false
注意
使用带有 forward: 前缀 URL 的重试过滤器时,目标端点应小心编写,以便在发生错误时,它不执行任何可能导致向客户端发送并提交响应的操作。
例如,如果目标端点是注解控制器,则目标控制器方法不应返回带有错误状态代码的 ResponseEntity
相反,它应该抛出一个 Exception 或者通过 Mono.error(ex) 返回值发出错误信号,这样重试过滤器就可以配置为通过重试来处理。
使用带有任何 HTTP 方法和正文的重试过滤器时,正文将被缓存,网关将受到内存限制。正文被缓存在由 ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR 定义的请求属性中。该对象的类型是 org.springframework.core.io.buffer.DataBuffer

可以使用单个 statusmethod 添加简化的“快捷”符号。

以下两个示例是等效的:

示例 60. application.yml

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.35. RequestSize 网关过滤器工厂

当请求大小大于允许的限制时,RequestSize 网关过滤器工厂可以阻止请求到达下游服务。该过滤器接受一个 maxSize 参数。

maxSizeDataSize 类型,因此值可以定义为数字,后面是可选的 DataUnit 后缀,如 ‘KB’ 或 ‘MB’。默认值为 ‘B’,表示字节。它是以字节定义的请求的允许大小限制。

以下列表配置了一个 RequestSize 网关过滤器:

示例 61. 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 网关过滤器工厂将响应状态设置为 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
注意
如果在路由定义中未作为过滤器参数提供,则默认请求大小设置为五 MB。

6.36. SetRequestHostHeader` 网关过滤器工厂

当需要覆盖主机头时,可以使用 SetRequestHostHeader 网关过滤器工厂将现有主机头替换为指定的值。该过滤器接受一个 host 参数。

以下列表配置了一个 SetRequestHostHeader 网关过滤器:

示例 62. application.yml

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 网关过滤器工厂将主机头的值替换为 example.org

6.37. TokenRelay 网关过滤器工厂

Token Relay 是指 OAuth2 消费者充当客户端,并将传入的令牌转发到传出的资源请求。消费者可以是纯客户端(如 SSO 应用程序)或资源服务器。

Spring Cloud Gateway 可以将 OAuth2 访问令牌下游转发到它所代理的服务。要将此功能添加到网关,您需要添加 TokenRelayGatewayFilterFactory,如下所示:

App.java

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
    return builder.routes()
            .route("resource", r -> r.path("/resource")
                    .filters(f -> f.tokenRelay())
                    .uri("http://localhost:9000"))
            .build();
}

或者这样

application.yaml

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] 从当前认证的用户中提取访问令牌,并将其放入下游请求的请求头中。

注意
如果正确设置了 spring.security.oauth2.client.* 属性,将触发创建 ReactiveClientRegistrationRepository bean,并且仅会创建 TokenRelayGatewayFilterFactory bean 。
TokenRelayGatewayFilterFactory 使用的默认实现 ReactiveOAuth2AuthorizedClientService 使用内存数据存储。如果您需要更健壮的解决方案,您需要提供自己的实现 ReactiveOAuth2AuthorizedClientService

6.38. 默认过滤器

要添加一个过滤器并将其应用于所有路由,您可以使用 spring.cloud.gateway.default-filters。此属性接受过滤器列表。

以下列表定义了一组默认过滤器:

示例 63. application.yml

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 在过滤器逻辑执行中区分了“预”和“后”阶段(见工作原理),因此具有最高优先级的过滤器是“预”阶段的第一个和“后”阶段的最后一个。

以下列表配置了过滤器链:

示例 64. ExampleConfiguration.java

@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:请求的路径。

然后,这些指标可以从 /actuator/metrics/spring.cloud.gateway.requests 抓取,并可以轻松地与 Prometheus 集成以创建 Grafana 仪表板。

注意注意注意
要启用 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 (OK)、HTTP 206 (Partial Content) 或 HTTP 301 (Moved Permanently)。
  • HTTP Cache-Control 头允许缓存(即请求中没有 no-store,响应中也没有 no-storeprivate)。

它接受两个配置参数:

  • 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 分钟的生存时间。

此过滤器还实现了 HTTP Cache-Control 头中 max-age 值的自动计算。如果在原始响应中存在 max-age,则该值将使用 timeToLive 配置参数中设置的秒数重写。在后续调用中,该值将根据响应到期前剩余的秒数重新计算。

spring.cloud.gateway.global-filter.local-response-cache.enabled 设置为 false 将为所有路由停用本地响应缓存,LocalResponseCache 过滤器允许在路由级别使用此功能。

注意注意注意
要启用此特性,请将 com.github.ben-manes.caffeine:caffeinespring-boot-starter-cache 添加为项目依赖。
如果您的项目创建了自定义 CacheManager beans,它将需要使用 @Primary 标记或使用 @Qualifier 注入。

7.4. 转发路由过滤器

ForwardRoutingFilter 查找 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 交换属性中的 URI。如果 URL 具有 forward 方案(例如 forward:///localendpoint),它使用 Spring DispatcherHandler 来处理请求。请求 URL 的路径部分被覆盖为转发 URL 中的路径。原始未修改的 URL 被追加到 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR 属性中的列表。

7.5. Netty 路由过滤器

如果位于 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 交换属性中的 URL 具有 httphttps 方案,则 Netty 路由过滤器运行。它使用 Netty HttpClient 发出下游代理请求。响应被放入 ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR 交换属性中,供后续过滤器使用。(还有一个实验性的 WebClientHttpRoutingFilter,执行相同的功能,但不需要 Netty。)

7.6. Netty 写响应过滤器

如果 ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR 交换属性中存在 Netty HttpClientResponse,则 NettyWriteResponseFilter 运行。它在所有其他过滤器完成后运行,并将代理响应写回到网关客户端响应。(还有一个实验性的 WebClientWriteResponseFilter,执行相同的功能,但不需要 Netty。)

7.7. ReactiveLoadBalancerClientFilter

ReactiveLoadBalancerClientFilter 查找名为 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 的交换属性中的 URI。如果 URL 具有 lb 方案(例如 lb://myservice),它使用 Spring Cloud ReactorLoadBalancer 将名称(本例中的 myservice)解析为实际的主机和端口,并替换同一属性中的 URI。原始未修改的 URL 被追加到 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR 属性中的列表。过滤器还在 ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR 属性中查看它是否等于 lb。如果是,则应用相同的规则。

以下列表配置了一个 ReactiveLoadBalancerClientFilter

示例 65. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: myRoute
        uri: lb://service
        predicates:
        - Path=/service/**
注意注意注意
默认情况下,当 ReactorLoadBalancer 找不到服务实例时,返回 503。您可以通过设置 spring.cloud.gateway.loadbalancer.use404=true 来配置网关返回 404
ReactiveLoadBalancerClientFilter 返回的 ServiceInstanceisSecure 值覆盖了向 Gateway 发出的请求中指定的方案。
例如,如果请求通过 HTTPS 进入 Gateway,但 ServiceInstance 指示它不安全,则下游请求将通过 HTTP 发出。
相反的情况也可以应用。
然而,如果网关配置中的路由指定了 GATEWAY_SCHEME_PREFIX_ATTR,则前缀被剥离,路由 URL 中的结果方案覆盖了 ServiceInstance 配置。

7.8. RouteToRequestUrl 过滤器

如果在 ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR 交换属性中存在 Route 对象,则 RouteToRequestUrlFilter 运行。它创建一个新的 URI,基于请求 URI 但更新了 Route 对象的 URI 属性。新的 URI 被放置在 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 交换属性中。

如果 URI 有一个方案前缀,例如 lb:ws://serviceid,则 lb 方案从 URI 中剥离并放置在 ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR 中,以便在过滤器链中后续使用。

7.9. Websocket 路由过滤器

如果位于 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 交换属性中的 URL 有一个 wswss 方案,则 Websocket 路由过滤器运行。它使用 Spring Websocket 基础设施将 Websocket 请求转发到下游。

您可以通过在 URI 前缀 lb 来对 Websockets 进行负载均衡,例如 lb:ws://serviceid

注意注意注意
如果您使用 SockJS 作为正常 HTTP 的回退,您还应该配置一个正常的 HTTP 路由以及 Websocket 路由。

以下列表配置了一个 Websocket 路由过滤器:

示例 66. application.yml

spring:
  cloud:
    gateway:
      routes:
      # SockJS 路由
      - id: websocket_sockjs_route
        uri: http://localhost:3001
        predicates:
        - Path=/websocket/info/**
      # 正常 Websocket 路由
      - id: websocket_route
        uri: ws://localhost:3001
        predicates:
        - Path=/websocket/**

7.10. 标记交换为已路由

在网关路由了 ServerWebExchange 之后,它通过向交换属性添加 gatewayAlreadyRouted 来将该交换标记为“已路由”。一旦请求被标记为已路由,其他路由过滤器将不再路由请求,基本上跳过该过滤器。您可以使用方便的方法来标记交换为已路由或检查交换是否已经被路由。

  • ServerWebExchangeUtils.isAlreadyRouted 接受一个 ServerWebExchange 对象并检查它是否已经被“路由”。
  • ServerWebExchangeUtils.setAlreadyRouted 接受一个 ServerWebExchange 对象并将其标记为“已路由”。

HttpHeadersFilters 在将请求发送到下游之前应用于请求,例如在 NettyRoutingFilter 中。

Forwarded 头过滤器创建一个 Forwarded 头以发送到下游服务。它将当前请求的 Host 头、方案和端口添加到任何现有的 Forwarded 头中。

RemoveHopByHop 头过滤器从转发请求中删除头。默认删除的头列表来自 IETF。

默认删除的头有:

  • Connection
  • Keep-Alive
  • Proxy-Authenticate
  • Proxy-Authorization
  • TE
  • Trailer
  • Transfer-Encoding
  • Upgrade

要更改此设置,将 spring.cloud.gateway.filter.remove-hop-by-hop.headers 属性设置为要删除的头名称列表。

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 请求。以下示例展示了如何操作:

示例 67. application.yml

server:
  ssl:
    enabled: true
    key-alias: scg
    key-store-password: scg1234
    key-store: classpath:scg-keystore.p12
    key-store-type: PKCS12

您可以将网关路由到 HTTP 和 HTTPS 后端。如果您正在路由到 HTTPS 后端,您可以配置网关信任所有下游证书,如下所示:

示例 68. application.yml

spring:
  cloud:
    gateway:
      httpclient:
        ssl:
          useInsecureTrustManager: true

使用不安全的 Trust Manager 不适合生产环境。对于生产部署,您可以使用以下配置,配置网关信任一组已知的证书:

示例 69. application.yml

spring:
  cloud:
    gateway:
      httpclient:
        ssl:
          trustedX509Certificates:
          - cert1.pem
          - cert2.pem

如果 Spring Cloud Gateway 没有提供信任的证书,将使用默认的信任存储(您可以通过设置 javax.net.ssl.trustStore 系统属性来覆盖它)。

9.1. TLS 握手

网关维护了一个客户端池,它用于路由到后端。当通过 HTTPS 通信时,客户端启动 TLS 握手。与此握手相关联的有多个超时。您可以配置这些超时(默认值如下):

示例 70. application.yml

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 接口的定义:

示例 71. RouteDefinitionLocator.java

public interface RouteDefinitionLocator {
    Flux<RouteDefinition> getRouteDefinitions();
}

默认情况下,PropertiesRouteDefinitionLocator 使用 Spring Boot 的 @ConfigurationProperties 机制加载属性。

前面配置示例都使用了使用位置参数而不是命名参数的快捷符号。以下两个示例是等效的:

示例 72. application.yml

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

对于网关的一些使用情况,属性是足够的,但是一些生产用例从从外部源(如数据库)加载配置中受益。未来的里程碑版本将有基于 Spring Data Repositories 的 RouteDefinitionLocator 实现,如 Redis、MongoDB 和 Cassandra。

10.1. RouteDefinition 指标

要启用 RouteDefinition 指标,请将 spring-boot-starter-actuator 添加为项目依赖。然后,默认情况下,只要 spring.cloud.gateway.metrics.enabled 属性设置为 true,指标将可用。将添加一个名为 spring.cloud.gateway.routes.count 的计量器指标,其值为 RouteDefinitions 的数量。此指标将从 /actuator/metrics/spring.cloud.gateway.routes.count 可用。

您可以使用元数据为每个路由配置额外的参数,如下所示:

示例 73. application.yml

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);
// 获取所有元数据属性
route.getMetadata();
// 获取单个元数据属性
route.getMetadata(someKey);

12. HTTP 超时配置

可以为所有路由配置 HTTP 超时(响应和连接),并为每个特定路由覆盖。

12.1. 全局超时

要配置全局 HTTP 超时:

connect-timeout 必须以毫秒为单位指定。

response-timeout 必须指定为 java.time.Duration。

全局 HTTP 超时示例

spring:
  cloud:
    gateway:
      httpclient:
        connect-timeout: 1000
        response-timeout: 5s

12.2. 每路由超时

要配置每路由超时:

connect-timeout 必须以毫秒为单位指定。

response-timeout 必须以毫秒为单位指定。

通过配置配置每路由 HTTP 超时

      - id: per_route_timeouts
        uri: https://example.org
        predicates:
          - name: Path
            args:
              pattern: /delay/{timeout}
        metadata:
          response-timeout: 200
          connect-timeout: 200

使用 Java DSL 配置每路由超时

import static org.springframework.cloud.gateway.support.RouteMetadataUtils.CONNECT_TIMEOUT_ATTR;
import static org.springframework.cloud.gateway.support.RouteMetadataUtils.RESPONSE_TIMEOUT_ATTR;

      @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 中允许简单的配置,RouteLocatorBuilder bean 包括一个流畅的 API。以下列表展示了它的工作原理:

示例 74. GatewaySampleApplication.java

// 从 GatewayFilters 和 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();
}

这种风格还允许更多的自定义断言断言。由 RouteDefinitionLocator beans 定义的断言使用逻辑 and 组合。通过使用流畅的 Java API,您可以在 Predicate 类上使用 and()or()negate() 操作符。

14. DiscoveryClient 路由定义定位器

您可以配置网关,根据在 DiscoveryClient 兼容的服务注册表中注册的服务来创建路由。

要启用此功能,请设置 spring.cloud.gateway.discovery.locator.enabled=true 并确保 DiscoveryClient 实现(例如 Netflix Eureka、Consul 或 Zookeeper)在类路径上并启用。

14.1. 为 DiscoveryClient 路由配置断言和过滤器

默认情况下,网关为使用 DiscoveryClient 创建的路由定义了一个单一的断言和一个过滤器。

默认断言是使用模式 /serviceId/** 定义的路径断言,其中 serviceId 是来自 DiscoveryClient 的服务 ID。

默认过滤器是带有正则表达式 /serviceId/?(?<remaining>.*) 和替换 /${remaining} 的重写路径过滤器。这在将请求发送到下游之前从路径中剥离了服务 ID。

如果您想自定义 DiscoveryClient 路由使用的断言或过滤器,设置 spring.cloud.gateway.discovery.locator.predicates[x]spring.cloud.gateway.discovery.locator.filters[y]。这样做时,您需要确保包括前面显示的默认断言和过滤器,如果您想保留该功能。以下示例展示了这是什么样子:

示例 75. application.properties

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 配置:

示例 76. logback.xml

    <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 配置

示例 77. application.yml

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "https://docs.spring.io"
            allowedMethods:
            - GET

前面的示例允许来自 docs.spring.io 的请求,对于所有 GET 请求的路径,允许 CORS 请求。

要为不受某些网关路由断言处理的请求提供相同的 CORS 配置,将 spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping 属性设置为 true。当您尝试支持 CORS 预请求,并且您的路由断言由于 HTTP 方法是 options 而没有评估为 true 时,这很有用。

16.2. 路由 CORS 配置

“route” 配置允许将 CORS 直接作为元数据应用到路由上,使用 cors 作为键。像全局配置一样,属性属于 Spring Framework CorsConfiguration

注意注意注意
如果路由中没有 Path 断言,'/***' 将被应用。

示例 78. application.yml

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。

以下列表展示了如何这样做:

示例 79. application.properties

management.endpoint.gateway.enabled=true # 默认值
management.endpoints.web.exposure.include=gateway

这个端点提供了对子执行器端点上可用内容的概述,以及每个引用的可用方法。结果响应类似于以下内容:

[
   {
      "href":"/actuator/gateway/",
      "methods":["GET"]
   },
   {
      "href":"/actuator/gateway/routedefinitions",
      "methods":["GET"]
   },
   {
      "href":"/actuator/gateway/globalfilters",
      "methods":["GET"]
   },
   {
      "href":"/actuator/gateway/routefilters",
      "methods":["GET"]
   },
   {
      "href":"/actuator/gateway/routes",
      "methods":["POST","GET"]
   },
   {
      "href":"/actuator/gateway/routepredicates",
      "methods":["GET"]
   },
   {
      "href":"/actuator/gateway/refresh",
      "methods":["POST"]
   },
   {
      "href":"/actuator/gateway/routes/route-id-1/combinedfilters",
      "methods":["GET"]
   },
   {
      "href":"/actuator/gateway/routes/route-id-1",
      "methods":["POST","DELETE","GET"]
   }
]

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
  }
]

此功能默认启用。要禁用它,请设置以下属性:

示例 80. application.properties

spring.cloud.gateway.actuator.verbose.enabled=false

这将在未来的版本中默认为 true

17.2. 检索路由过滤器

本节详细介绍了如何检索路由过滤器,包括:

  • 全局过滤器

  • [gateway-route-filters]

17.2.1. 全局过滤器

要检索应用于所有路由的全局过滤器,请向 /actuator/gateway/globalfilters 发送 GET 请求。结果响应类似于以下内容:

{
  "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 工厂,请向 /actuator/gateway/routefilters 发送 GET 请求。结果响应类似于以下内容:

{
  "[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. 刷新路由缓存

要清除路由缓存,请向 /actuator/gateway/refresh 发送 POST 请求。请求返回 200,没有响应正文。

要清除与特定元数据值匹配的路由,请添加查询参数 metadata,指定要清除的路由应匹配的 key:value 对。如果在异步刷新期间出现错误,刷新将不会修改现有路由。

发送 POST 请求到 /actuator/gateway/refresh?metadata=group:group-1 将仅刷新其 group 元数据为 group-1 的路由:first_routethird_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. 检索网关中定义的路由

要检索网关中定义的路由,请向 /actuator/gateway/routes 发送 GET 请求。结果响应类似于以下内容:

[
  {
    "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
  }
]

响应包含了网关中定义的所有路由的详细信息。下面的表格描述了响应中每个元素(每个是一个路由)的结构:

路径类型描述
route_idString路由 ID。
route_object.predicateObject路由断言。
route_object.filtersArray应用于路由的 GatewayFilter 工厂。
orderNumber路由顺序。

17.5. 检索特定路由的信息

要检索有关单个路由的信息,请向 /actuator/gateway/routes/{id} 发送 GET 请求(例如,/actuator/gateway/routes/first_route)。结果响应类似于以下内容:

{
  "id": "first_route",
  "predicates": [
    {
      "name": "Path",
      "args": {
        "_genkey_0":"/first"
      }
    }
  ],
  "filters": [],
  "uri": "https://www.uri-destination.org",
  "order": 0
}

下面的表格描述了响应的结构:

路径类型描述
idString路由 ID。
predicatesArray路由断言的集合。每个项目定义了给定断言的名称和参数。
filtersArray应用于路由的过滤器集合。
uriString路由的目标 URI。
orderNumber路由顺序。

17.6. 创建和删除特定路由定义

要创建路由定义,请向 /gateway/routes/{id_route_to_create} 发送带有指定路由字段的 JSON 正文的 POST 请求(见检索有关特定路由的信息)。

要删除路由定义,请向 /gateway/routes/{id_route_to_delete} 发送 DELETE 请求。

17.7. 创建多个路由定义

要在单个请求中创建多个路由定义,请向 /gateway/routes 发送带有指定路由字段的 JSON 正文的 POST 请求,包括路由 ID(见检索有关特定路由的信息)。如果在创建路由期间任何路由引发错误,将丢弃路由定义。

17.8. 所有端点的总结

下面的表格总结了 Spring Cloud Gateway 执行器端点(请注意,每个端点的基本路径为 /actuator/gateway):

IDHTTP 方法描述
globalfiltersGET显示应用于路由的全局过滤器列表。
routefiltersGET显示应用于特定路由的 GatewayFilter 工厂列表。
refreshPOST清除路由缓存。
routesGET显示网关中定义的路由列表。
routes/{id}GET显示有关特定路由的信息。
routes/{id}POST向网关添加新路由。
routes/{id}DELETE从网关中移除现有路由。

17.9. 在多个 Gateway 实例之间共享路由

Spring Cloud Gateway 提供了两种 RouteDefinitionRepository 实现。第一种是 InMemoryRouteDefinitionRepository,它只存在于一个 Gateway 实例的内存中。这种类型的存储库不适合在多个 Gateway 实例之间填充路由。

为了在 Spring Cloud Gateway 实例的集群中共享路由,可以使用 RedisRouteDefinitionRepository。要启用这种类型的存储库,必须将以下属性设置为 true:spring.cloud.gateway.redis-route-definition-repository.enabled。与 RedisRateLimiter 过滤器工厂一样,它需要使用 spring-boot-starter-data-redis-reactive Spring Boot 启动器。

18. 故障排除

本节涵盖了使用 Spring Cloud Gateway 时可能出现的常见问题。

18.1. 日志级别

以下记录器在 DEBUGTRACE 级别可能包含有价值的故障排除信息:

  • org.springframework.cloud.gateway
  • org.springframework.http.server.reactive
  • org.springframework.web.reactive
  • org.springframework.boot.autoconfigure.web
  • reactor.netty
  • redisratelimiter

18.2. 监听

Reactor Netty HttpClientHttpServer 可以启用监听。当与将 reactor.netty 日志级别设置为 DEBUGTRACE 结合使用时,它启用了记录信息,例如发送和接收的头和正文。

要启用监听,请设置 spring.cloud.gateway.httpserver.wiretap=truespring.cloud.gateway.httpclient.wiretap=true,分别用于 HttpServerHttpClient

19. 开发者指南

这些是编写网关的一些自定义组件的基本指南。

19.1. 编写自定义路由断言工厂

为了编写路由断言,您需要实现 RoutePredicateFactory 作为 bean。有一个名为 AbstractRoutePredicateFactory 的抽象类,您可以扩展它。

MyRoutePredicateFactory.java

@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {

    public MyRoutePredicateFactory() {
        super(Config.class);
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        // 从 Config 对象中获取配置
        return exchange -> {
            // 获取请求
            ServerHttpRequest request = exchange.getRequest();
            // 从请求中获取信息以查看它是否匹配配置。
            return matches(config, request);
        };
    }

    public static class Config {
        // 在此处放置您的过滤器的配置属性
    }

}

19.2. 编写自定义网关过滤器工厂

要编写 GatewayFilter,您必须实现 GatewayFilterFactory 作为 bean。您可以扩展一个名为 AbstractGatewayFilterFactory 的抽象类。以下示例展示了如何操作:

示例 81. PreGatewayFilterFactory.java

@Component
public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory<PreGatewayFilterFactory.Config> {

    public PreGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        // 从 Config 对象中获取配置
        return (exchange, chain) -> {
            // 如果您想构建一个“预”过滤器,您需要在调用 chain.filter 之前操作请求
            ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
            // 使用构建器操作请求
            return chain.filter(exchange.mutate().request(builder.build()).build());
        };
    }

    public static class Config {
        // 在此处放置您的过滤器的配置属性
    }

}

PostGatewayFilterFactory.java

@Component
public class PostGatewayFilterFactory extends AbstractGatewayFilterFactory<PostGatewayFilterFactory.Config> {

    public PostGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        // 从 Config 对象中获取配置
        return (exchange, chain) -> {
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                ServerHttpResponse response = exchange.getResponse();
                // 以某种方式操作响应
            }));
        };
    }

    public static class Config {
        // 在此处放置您的过滤器的配置属性
    }

}
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 -> {
            // 向代理请求添加头
            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 -> {
            // 向响应添加头
            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-mvcspring-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 的所有特性。因此,您可以注入请求头和查询参数,并且您可以在映射注解的声明中约束传入的请求。有关这些特性的更多详细信息,请参阅 Spring MVC 中的 @RequestMapping 文档。

您可以通过在 ProxyExchange 上使用 header() 方法向下游响应添加头。

您也可以通过向 get() 方法(和其他方法)添加一个映射器来操作响应头(和响应中的任何其他内容)。映射器是一个函数,它接受传入的 ResponseEntity 并将其转换为传出的 ResponseEntity

默认情况下,为“敏感”头(cookieauthorization)提供了一流的支持,这些头不会传递给下游,以及“代理”(x-forwarded-*)头。

21. AOT 和原生镜像支持

4.0.0 起,Spring Cloud Gateway 支持 Spring AOT 转换和原生镜像。

如果您使用负载均衡路由,您需要显式定义您的 LoadBalancerClient 服务 ID。您可以通过使用 @LoadBalancerClient 注解的 valuename 属性或作为 spring.cloud.loadbalancer.eager-load.clients 属性的值来实现。 |

22. 配置属性

要查看所有与 Spring Cloud Gateway 相关的配置属性列表,请参见附录。

以下是 Spring Cloud Gateway 常见应用程序属性的翻译,这些属性可以在您的 application.properties 文件、application.yml 文件中指定,或作为命令行开关使用。

这个附录提供了 Spring Cloud Gateway 的常见属性列表,以及使用它们的底层类的引用。

名称默认值描述
spring.cloud.gateway.default-filters应用于每条路由的过滤器定义列表。
spring.cloud.gateway.discovery.locator.enabledfalse启用 DiscoveryClient 网关集成的标志。
spring.cloud.gateway.discovery.locator.filters
spring.cloud.gateway.discovery.locator.include-expressiontrue用于评估是否将服务包含在网关集成中的 SpEL 表达式,默认为 true。
spring.cloud.gateway.discovery.locator.lower-case-service-idfalse在谓词和过滤器中将 serviceId 小写化的选项,默认为 false。在使用 Eureka 时很有用,因为 Eureka 会自动将 serviceId 大写,所以 MYSERVICE 将匹配 /myservice/**
spring.cloud.gateway.discovery.locator.predicates
spring.cloud.gateway.discovery.locator.route-id-prefix路由 ID 的前缀,默认为 discoveryClient.getClass().getSimpleName() + “_”。将附加服务 ID 以创建 routeId。
spring.cloud.gateway.discovery.locator.url-expression'lb://'+serviceId创建每条路由 URI 的 SpEL 表达式,默认为:‘lb://’+serviceId。
spring.cloud.gateway.enabledtrue启用网关功能。
spring.cloud.gateway.fail-on-route-definition-errortrue路由定义错误时失败的选项,默认为 true。否则,会记录警告。
spring.cloud.gateway.filter.add-request-header.enabledtrue启用 add-request-header 过滤器。
spring.cloud.gateway.filter.add-request-parameter.enabledtrue启用 add-request-parameter 过滤器。
spring.cloud.gateway.filter.add-response-header.enabledtrue启用 add-response-header 过滤器。
spring.cloud.gateway.filter.circuit-breaker.enabledtrue启用 circuit-breaker 过滤器。
spring.cloud.gateway.filter.dedupe-response-header.enabledtrue启用 dedupe-response-header 过滤器。
spring.cloud.gateway.filter.fallback-headers.enabledtrue启用 fallback-headers 过滤器。
spring.cloud.gateway.filter.hystrix.enabledtrue启用 hystrix 过滤器。
spring.cloud.gateway.filter.json-to-grpc.enabledtrue启用 JSON 到 gRPC 过滤器。
spring.cloud.gateway.filter.local-response-cache.enabledfalse启用 local-response-cache 过滤器。
spring.cloud.gateway.filter.local-response-cache.request.no-cache-strategy
spring.cloud.gateway.filter.local-response-cache.size为此路由逐出条目的最大缓存大小(以 KB、MB 和 GB 为单位)。
spring.cloud.gateway.filter.local-response-cache.time-to-live5m缓存项过期的时间(以 s 表示秒,m 表示分钟,h 表示小时)。
spring.cloud.gateway.filter.map-request-header.enabledtrue启用 map-request-header 过滤器。
spring.cloud.gateway.filter.modify-request-body.enabledtrue启用 modify-request-body 过滤器。
spring.cloud.gateway.filter.modify-response-body.enabledtrue启用 modify-response-body 过滤器。
spring.cloud.gateway.filter.prefix-path.enabledtrue启用 prefix-path 过滤器。
spring.cloud.gateway.filter.preserve-host-header.enabledtrue启用 preserve-host-header 过滤器。
spring.cloud.gateway.filter.redirect-to.enabledtrue启用 redirect-to 过滤器。
spring.cloud.gateway.filter.remove-hop-by-hop.headers
spring.cloud.gateway.filter.remove-hop-by-hop.order0
spring.cloud.gateway.filter.remove-request-header.enabledtrue启用 remove-request-header 过滤器。
spring.cloud.gateway.filter.remove-request-parameter.enabledtrue启用 remove-request-parameter 过滤器。
spring.cloud.gateway.filter.remove-response-header.enabledtrue启用 remove-response-header 过滤器。
spring.cloud.gateway.filter.request-header-size.enabledtrue启用 request-header-size 过滤器。
spring.cloud.gateway.filter.request-header-to-request-uri.enabledtrue启用 request-header-to-request-uri 过滤器。
spring.cloud.gateway.filter.request-rate-limiter.default-key-resolver
spring.cloud.gateway.filter.request-rate-limiter.default-rate-limiter
spring.cloud.gateway.filter.request-rate-limiter.enabledtrue启用 request-rate-limiter 过滤器。
spring.cloud.gateway.filter.request-size.enabledtrue启用 request-size 过滤器。
spring.cloud.gateway.filter.retry.enabledtrue启用 retry 过滤器。
spring.cloud.gateway.filter.rewrite-location-response-header.enabledtrue启用 rewrite-location-response-header 过滤器。
spring.cloud.gateway.filter.rewrite-location.enabledtrue启用 rewrite-location 过滤器。
spring.cloud.gateway.filter.rewrite-path.enabledtrue启用 rewrite-path 过滤器。
spring.cloud.gateway.filter.rewrite-request-parameter.enabledtrue启用 rewrite-request-parameter 过滤器。
spring.cloud.gateway.filter.rewrite-response-header.enabledtrue启用 rewrite-response-header 过滤器。
spring.cloud.gateway.filter.save-session.enabledtrue启用 save-session 过滤器。
spring.cloud.gateway.filter.secure-headers.content-security-policydefault-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'
spring.cloud.gateway.filter.secure-headers.content-type-optionsnosniff
spring.cloud.gateway.filter.secure-headers.disable
spring.cloud.gateway.filter.secure-headers.download-optionsnoopen
spring.cloud.gateway.filter.secure-headers.enabledtrue启用 secure-headers 过滤器。
spring.cloud.gateway.filter.secure-headers.frame-optionsDENY
spring.cloud.gateway.filter.secure-headers.permitted-cross-domain-policiesnone
spring.cloud.gateway.filter.secure-headers.referrer-policyno-referrer
spring.cloud.gateway.filter.secure-headers.strict-transport-securitymax-age=631138519
spring.cloud.gateway.filter.secure-headers.xss-protection-header1 ; mode=block
spring.cloud.gateway.filter.set-path.enabledtrue启用 set-path 过滤器。
spring.cloud.gateway.filter.set-request-header.enabledtrue启用 set-request-header 过滤器。
spring.cloud.gateway.filter.set-request-host-header.enabledtrue

RoutePredicateHandlerMapping 的顺序。

名称默认值描述
spring.cloud.gateway.httpclient.compressionfalse为 Netty HttpClient 启用压缩。
spring.cloud.gateway.httpclient.connect-timeout连接超时(毫秒),默认为 30 秒。
spring.cloud.gateway.httpclient.max-header-size最大响应头大小。
spring.cloud.gateway.httpclient.max-initial-line-length最大初始行长度。
spring.cloud.gateway.httpclient.pool.acquire-timeout仅适用于类型 FIXED,获取时等待的最长时间(毫秒)。
spring.cloud.gateway.httpclient.pool.eviction-interval0在指定的时间间隔内定期执行后台驱逐检查。默认禁用(Duration.ZERO)。
spring.cloud.gateway.httpclient.pool.max-connections仅适用于类型 FIXED,开始对现有连接进行挂起获取之前的最大连接数。
spring.cloud.gateway.httpclient.pool.max-idle-time通道将被关闭的时间(毫秒)。如果为 NULL,则没有最大空闲时间。
spring.cloud.gateway.httpclient.pool.max-life-time通道将被关闭的持续时间。如果为 NULL,则没有最大生命周期。
spring.cloud.gateway.httpclient.pool.metricsfalse启用通道池指标的收集,并在 Micrometer 中注册。默认禁用。
spring.cloud.gateway.httpclient.pool.nameproxy通道池映射的名称,默认为 proxy。
spring.cloud.gateway.httpclient.pool.typeHttpClient 使用的池类型,默认为 ELASTIC。
spring.cloud.gateway.httpclient.proxy.hostNetty HttpClient 代理配置的主机名。
spring.cloud.gateway.httpclient.proxy.non-proxy-hosts-pattern应直接到达、绕过代理的配置主机列表的正则表达式(Java)。
spring.cloud.gateway.httpclient.proxy.passwordNetty HttpClient 代理配置的密码。
spring.cloud.gateway.httpclient.proxy.portNetty HttpClient 代理配置的端口。
spring.cloud.gateway.httpclient.proxy.typeNetty HttpClient 代理配置的代理类型。
spring.cloud.gateway.httpclient.proxy.usernameNetty HttpClient 代理配置的用户名。
spring.cloud.gateway.httpclient.response-timeout响应超时。
spring.cloud.gateway.httpclient.ssl.close-notify-flush-timeout3000msSSL close_notify 刷新超时。默认为 3000 毫秒。
spring.cloud.gateway.httpclient.ssl.close-notify-read-timeout0SSL close_notify 读取超时。默认为 0 毫秒。
spring.cloud.gateway.httpclient.ssl.handshake-timeout10000msSSL 握手超时。默认为 10000 毫秒。
spring.cloud.gateway.httpclient.ssl.key-password密钥密码,默认与 keyStorePassword 相同。
spring.cloud.gateway.httpclient.ssl.key-storeNetty HttpClient 的密钥库路径。
spring.cloud.gateway.httpclient.ssl.key-store-password密钥库密码。
spring.cloud.gateway.httpclient.ssl.key-store-providerNetty HttpClient 的密钥库提供者,可选字段。
spring.cloud.gateway.httpclient.ssl.key-store-typeJKSNetty HttpClient 的密钥库类型,默认为 JKS。
spring.cloud.gateway.httpclient.ssl.trusted-x509-certificates用于验证远程端点证书的受信任证书。
spring.cloud.gateway.httpclient.ssl.use-insecure-trust-managerfalse安装 netty InsecureTrustManagerFactory。这是不安全的,不适合生产环境。
spring.cloud.gateway.httpclient.websocket.max-frame-payload-length最大帧负载长度。
spring.cloud.gateway.httpclient.websocket.proxy-pingtrue将 ping 帧代理到下游服务,默认为 true。
spring.cloud.gateway.httpclient.wiretapfalse为 Netty HttpClient 启用 wiretap 调试。
spring.cloud.gateway.httpserver.wiretapfalse为 Netty HttpServer 启用 wiretap 调试。
spring.cloud.gateway.loadbalancer.use404false
spring.cloud.gateway.metrics.enabledfalse启用指标数据的收集。
spring.cloud.gateway.metrics.prefixspring.cloud.gateway由网关发出的所有指标的前缀。
spring.cloud.gateway.metrics.tags添加到指标的标签映射。
spring.cloud.gateway.observability.enabledtrue是否应该打开 Micrometer 可观测性支持。
spring.cloud.gateway.predicate.after.enabledtrue启用 after 谓词。
spring.cloud.gateway.predicate.before.enabledtrue启用 before 谓词。
spring.cloud.gateway.predicate.between.enabledtrue启用 between 谓词。
spring.cloud.gateway.predicate.cloud-foundry-route-service.enabledtrue启用 cloud-foundry-route-service 谓词。
spring.cloud.gateway.predicate.cookie.enabledtrue启用 cookie 谓词。
spring.cloud.gateway.predicate.header.enabledtrue启用 header 谓词。
spring.cloud.gateway.predicate.host.enabledtrue启用 host 谓词。
spring.cloud.gateway.predicate.method.enabledtrue启用 method 谓词。
spring.cloud.gateway.predicate.path.enabledtrue启用 path 谓词。
spring.cloud.gateway.predicate.query.enabledtrue启用 query 谓词。
spring.cloud.gateway.predicate.read-body.enabledtrue启用 read-body 谓词。
spring.cloud.gateway.predicate.remote-addr.enabledtrue启用 remote-addr 谓词。
spring.cloud.gateway.predicate.weight.enabledtrue启用 weight 谓词。
spring.cloud.gateway.predicate.xforwarded-remote-addr.enabledtrue启用 xforwarded-remote-addr 谓词。
spring.cloud.gateway.redis-rate-limiter.burst-capacity-headerX-RateLimit-Burst-Capacity返回突发容量配置的头名称。
spring.cloud.gateway.redis-rate-limiter.config
spring.cloud.gateway.redis-rate-limiter.include-headerstrue是否包含包含速率限制器信息的头,默认为 true。
spring.cloud.gateway.redis-rate-limiter.remaining-headerX-RateLimit-Remaining返回当前秒内剩余请求数的头名称。
spring.cloud.gateway.redis-rate-limiter.replenish-rate-headerX-RateLimit-Replenish-Rate返回填充速率配置的头名称。
spring.cloud.gateway.redis-rate-limiter.requested-tokens-headerX-RateLimit-Requested-Tokens返回请求令牌配置的头名称。
spring.cloud.gateway.restrictive-property-accessor.enabledtrue限制 SpEL 中的方法和属性访问。
spring.cloud.gateway.routes路由列表。
spring.cloud.gateway.set-status.original-status-header-name包含代理请求 HTTP 代码的头名称。
spring.cloud.gateway.streaming-media-types
spring.cloud.gateway.x-forwarded.enabledtrue是否启用 XForwardedHeadersFilter。
spring.cloud.gateway.x-forwarded.for-appendtrue是否启用将 X-Forwarded-For 作为列表追加。
spring.cloud.gateway.x-forwarded.for-enabledtrue是否启用 X-Forwarded-For。
spring.cloud.gateway.x-forwarded.host-appendtrue是否启用将 X-Forwarded-Host 作为列表追加。
spring.cloud.gateway.x-forwarded.host-enabledtrue是否启用 X-Forwarded-Host。
spring.cloud.gateway.x-forwarded.order0XForwardedHeadersFilter 的顺序。
spring.cloud.gateway.x-forwarded.port-appendtrue是否启用将 X-Forwarded-Port 作为列表追加。
spring.cloud.gateway.x-forwarded.port-enabledtrue是否启用 X-Forwarded-Port。
spring.cloud.gateway.x-forwarded.prefix-appendtrue是否启用将 X-Forwarded-Prefix 作为列表追加。
spring.cloud.gateway.x-forwarded.prefix-enabledtrue是否启用 X-Forwarded-Prefix。
spring.cloud.gateway.x-forwarded.proto-appendtrue是否启用将 X-Forwarded-Proto 作为列表追加。
spring.cloud.gateway.x-forwarded.proto-enabledtrue是否启用 X-Forwarded-Proto。

A.1. 可观测性 - 指标

以下是此项目声明的所有指标的列表。

A.1.1. 网关 HttpClient 观测

通过网关发送请求时创建的观测。

指标名称 http.client.requests(由惯例类 org.springframework.cloud.gateway.filter.headers.observation.Default.active(由惯例类 org.springframework.cloud.gateway.filter.headers.observation.DefaultGatewayObservationConvention 定义)。类型 long task timer

关键值在开始观测后添加的可能不会出现在 *.active 指标中。
Micrometer 内部使用 nanoseconds 作为基础单位。但是,每个后端确定实际的基础单位。(即 Prometheus 使用秒)

完整限定名的封闭类 org.springframework.cloud.gateway.filter.headers.observation.GatewayDocumentedObservation

名称描述
http.method (必需)HTTP 方法。
http.status_code (必需)HTTP 状态。
spring.cloud.gateway.route.id (必需)路由 ID。
spring.cloud.gateway.route.uri (必需)从路由中获取的 HTTP URI。

表 1. 低基数键

名称描述
http.uri (必需)完整的 HTTP URI。

表 2. 高基数键

A.2. 可观测性 - Spans

以下是此项目声明的所有 spans 的列表。

A.2.1. 网关 HttpClient 观测 Span

通过网关发送请求时创建的观测。

Span 名称 http.client.requests(由惯例类 org.springframework.cloud.gateway.filter.headers.observation.DefaultGatewayObservationConvention 定义)。

完整限定名的封闭类 org.springframework.cloud.gateway.filter.headers.observation.GatewayDocumentedObservation

名称描述
http.method (必需)HTTP 方法。
http.status_code (必需)HTTP 状态。
http.uri (必需)完整的 HTTP URI。
spring.cloud.gateway.route.id (必需)路由 ID。
spring.cloud.gateway.route.uri (必需)从路由中获取的 HTTP URI。

表 3. 标签键

A.3. 可观测性 - 惯例

以下是此项目声明的所有 GlobalObservabilityConventionsObservabilityConventions 的列表。

适用的观测上下文类名称观测惯例类名称
GatewayContextorg.springframework.cloud.gateway.filter.headers.observation.DefaultGatewayObservationConvention

表 4. 观测惯例实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值