springcloud-gateway 网关组件中文文档

Spring Cloud网关

Greenwich SR5

该项目提供了一个基于Spring生态系统的API网关,其中包括:Spring 5,Spring Boot 2和项目Reactor。Spring Cloud网关的目的是提供一种简单而有效的方法来路由到API,并向它们提供跨领域的关注,例如:安全性,监视/度量和弹性。

如何包括Spring Cloud网关

要将Spring Cloud网关包含在项目中,请将该启动器与组org.springframework.cloud和工件ID spring-cloud-starter-gateway一起使用。有关 使用当前Spring Cloud版本Train设置构建系统的详细信息,请参见Spring Cloud项目页面

如果包括启动器,但由于某种原因,您不希望启用网关,请设置spring.cloud.gateway.enabled=false

|-----------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| | 重要 |
| | Spring Cloud网关基于Spring Boot 2.xSpring WebFlux项目Reactor构建。因此,使用Spring Cloud网关时,许多熟悉的同步库(例如,Spring Data和Spring Security)和模式可能不适用。如果您不熟悉这些项目,建议您在使用Spring Cloud Gateway之前,先阅读它们的文档以熟悉一些新概念。 |

|-----------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|
| | 重要 |
| | Spring Cloud网关需要Spring Boot和Spring Webflux提供的Netty运行时。它不能在传统的Servlet容器中或作为WAR构建。 |

111.词汇表

  • 路由:路由网关的基本构建块。它由ID,目标URI,谓词集合和过滤器集合定义。如果聚合谓词为true,则匹配路由。
  • 谓词 :这是Java 8 Function谓词。输入类型为Spring Framework ServerWebExchange。这使开发人员可以匹配HTTP请求中的任何内容,例如标头或参数。
  • 过滤器 :这些是使用特定工厂构造的实例Spring Framework GatewayFilter。在此,可以在发送下游请求之前或之后修改请求和响应。

112.工作原理

客户端向Spring Cloud网关发出请求。如果网关处理程序映射确定请求与路由匹配,则将其发送到网关Web处理程序。该处理程序运行通过特定于请求的筛选器链发送请求。筛选器由虚线分隔的原因是,筛选器可以在发送代理请求之前或之后执行逻辑。执行所有"前置"过滤器逻辑,然后发出代理请求。发出代理请求后,将执行"后"过滤器逻辑。

|-----------------------------------------------------------------------------------------|----------------------------------------------------|
| |
| | 在没有端口的路由中定义的URI将分别将HTTP和HTTPS URI的默认端口分别设置为80和443。 |

113.配置路由谓词工厂和网关过滤工厂

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

名称和自变量名称将在第一部分或每部分的两个部分中以code的形式列出。参数通常按快捷方式配置所需的顺序列出。

113.1快捷方式配置

快捷方式配置由过滤器名称识别,后跟等号(=),后跟由逗号分隔的参数值(,)。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: after_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Cookie</span>=mycookie,mycookievalue</span></span></span>

先前的示例使用两个参数定义了Cookie Route Predicate Factory,即cookie名称mycookie和与mycookievalue相匹配的值。

113.2完全展开的参数

完全扩展的参数看起来更像带有名称/值对的标准Yaml配置。通常,将有一个name键和一个args键。args键是用于配置谓词或过滤器的键值对的映射。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: after_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - name</span>: Cookie
<span style="color:#7f007f">          args</span>:
<span style="color:#7f007f">            name</span>: mycookie
<span style="color:#7f007f">            regexp</span>: mycookievalue</span></span></span>

这是上面显示的Cookie谓词的快捷方式配置的完整配置。

114.路由谓词工厂

Spring Cloud网关将路由匹配为Spring WebFlux HandlerMapping基础结构的一部分。Spring Cloud网关包括许多内置的Route Predicate工厂。所有这些谓词都与HTTP请求的不同属性匹配。多个路由谓词工厂可以合并,也可以通过逻辑and合并。

114.1路由谓词工厂之后

After路由谓词工厂采用一个参数,即datetime(这是Java ZonedDateTime)。该谓词匹配在当前日期时间之后发生的请求。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: after_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - After</span>=2017-01-20T17:42:47.789-07:00[America/Denver<span style="color:#7f0055"><strong>]</strong></span></span></span></span>

该路线与2017年1月20日17:42山区时间(丹佛)之后的所有请求匹配。

114.2路线谓词工厂之前

Before路由谓词工厂采用一个参数datetime(它是Java ZonedDateTime)。该谓词匹配当前日期时间之前发生的请求。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: before_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Before</span>=2017-01-20T17:42:47.789-07:00[America/Denver<span style="color:#7f0055"><strong>]</strong></span></span></span></span>

该路线与2017年1月20日17:42山区时间(丹佛)之前的所有请求匹配。

114.3路由谓词工厂之间

Between路由谓词工厂采用两个参数datetime1datetime2,它们是Java ZonedDateTime对象。该谓词匹配在datetime1之后和datetime2之前发生的请求。datetime2参数必须在datetime1之后。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: between_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Between</span>=2017-01-20T17:42:47.789-07:00[America/Denver]<span style="color:#7f0055"><strong>,</strong></span> 2017-01-21T17:42:47.789-07:00[America/Denver<span style="color:#7f0055"><strong>]</strong></span></span></span></span>

该路线与2017年1月20日山区时间(丹佛)之后和2017年1月21日17:42山区时间(丹佛)之后的所有请求匹配。这对于维护时段可能很有用。

114.4 Cookie路线谓词工厂

Cookie Route Predicate Factory采用两个参数,即cookie nameregexp(这是Java正则表达式)。该谓词匹配具有给定名称的cookie,并且值匹配正则表达式。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: cookie_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Cookie</span>=chocolate<span style="color:#7f0055"><strong>,</strong></span> ch.p</span></span></span>

此路由与请求匹配,具有一个名为chocolate的cookie,该cookie的值与ch.p正则表达式匹配。

114.5标头路由谓词工厂

Header Route Predicate Factory具有两个参数,标头nameregexp(这是Java正则表达式)。该谓词与具有给定名称的标头匹配,并且值与正则表达式匹配。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: header_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Header</span>=X-Request-Id<span style="color:#7f0055"><strong>,</strong></span> \d+</span></span></span>

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

114.6主机路由谓词工厂

Host Route Predicate Factory采用一个参数:主机名patterns的列表。模式是Ant样式的模式,以.作为分隔符。该谓词与匹配模式的Host头匹配。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: host_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Host</span>=**.somehost.org,**.anotherhost.org</span></span></span>

还支持URI模板变量,例如{sub}.myhost.org

如果请求的Host标头的值为www.somehost.orgbeta.somehost.orgwww.anotherhost.org,则此路由将匹配。

该谓词提取URI模板变量(如上例中定义的sub)作为名称和值的映射,并使用在ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE中定义的键将其放置在ServerWebExchange.getAttributes()中。这些值可供GatewayFilter工厂使用。

114.7方法路线谓词工厂

Method路由谓词工厂采用一个methods参数,该参数是一个或多个要匹配的HTTP方法。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: method_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Method</span>=GET,POST</span></span></span>

如果请求方法是GETPOST,则此路由将匹配。

114.8路径路线谓词工厂

Path路由谓词工厂采用两个参数:Spring PathMatcher patterns的列表和matchOptionalTrailingSeparator的可选标志。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: host_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Path</span>=/foo/{segment},/bar/{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>

如果请求路径为例如/foo/1/foo/bar/bar/baz,则此路由将匹配。

该谓词提取URI模板变量(如以上示例中定义的segment)作为名称和值的映射,并使用在ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE中定义的键将其放置在ServerWebExchange.getAttributes()中。这些值可供GatewayFilter工厂使用。

可以使用实用程序方法来简化对这些变量的访问。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);

String segment = uriVariables.get(<span style="color:#2a00ff">"segment"</span>);</span></span></span>

114.9查询路由谓词工厂

Query Route Predicate Factory采用两个参数:必需的param和可选的regexp(这是Java正则表达式)。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: query_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Query</span>=baz</span></span></span>

如果请求包含baz查询参数,则此路由将匹配。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: query_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Query</span>=foo<span style="color:#7f0055"><strong>,</strong></span> ba.</span></span></span>

如果请求包含一个foo查询参数,其值与ba.正则表达式匹配,则此路由将匹配,因此barbaz将匹配。

114.10 RemoteAddr路由谓词工厂

RemoteAddr路由谓词工厂采用sources的列表(最小大小1),它是CIDR表示法(IPv4或IPv6)字符串,例如192.168.0.1/16(其中192.168.0.1是IP地址, 16是子网掩码)。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: remoteaddr_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - RemoteAddr</span>=192.168.1.1/24</span></span></span>

如果请求的远程地址为192.168.1.10,则此路由将匹配。

114.11重量路线谓词工厂

Weight Route Predicate Factory接受两个参数groupweight(一个int)。权重是按组计算的。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: weight_high
<span style="color:#7f007f">        uri</span>: https://weighthigh.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Weight</span>=group1<span style="color:#7f0055"><strong>,</strong></span> 8
<span style="color:#7f007f">      - id</span>: weight_low
<span style="color:#7f007f">        uri</span>: https://weightlow.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Weight</span>=group1<span style="color:#7f0055"><strong>,</strong></span> 2</span></span></span>

此路由会将约80%的流量转发到https://weighthigh.org,并将约20%的流量转发到https://weighlow.org

114.11.1修改解析远程地址的方式

默认情况下,RemoteAddr路由谓词工厂使用传入请求中的远程地址。如果Spring Cloud网关位于代理层后面,则此地址可能与实际的客户端IP地址不匹配。

您可以通过设置自定义RemoteAddressResolver来自定义解析远程地址的方式。Spring Cloud网关带有一个基于X-Forwarded-For标头 XForwardedRemoteAddressResolver的非默认远程地址解析器。

XForwardedRemoteAddressResolver有两个静态构造方法,它们采用不同的安全性方法:

XForwardedRemoteAddressResolver::trustAll返回一个RemoteAddressResolver,该地址始终使用在X-Forwarded-For标头中找到的第一个IP地址。这种方法容易受到欺骗,因为恶意客户端可能会为X-Forwarded-For设置一个初始值,该初始值将被解析程序接受。

XForwardedRemoteAddressResolver::maxTrustedIndex获取一个索引,该索引与在Spring Cloud网关前面运行的受信任基础结构的数量相关。例如,如果Spring Cloud网关只能通过HAProxy访问,则应使用值1。如果在访问Spring Cloud网关之前需要两跳可信基础结构,则应使用值2。

给定以下标头值:

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3</span></span></span>

下面的maxTrustedIndex值将产生以下远程地址。

maxTrustedIndex 结果
[Integer.MIN_VALUE,0] (invalid, IllegalArgumentException during initialization)
1 0.0.0.3
2 0.0.0.2
3 0.0.0.1
[4, Integer.MAX_VALUE] 0.0.0.1

使用Java配置:

GatewayConfig.java

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">RemoteAddressResolver resolver = XForwardedRemoteAddressResolver
    .maxTrustedIndex(1);

...

.route(<span style="color:#2a00ff">"direct-route"</span>,
    r -> r.remoteAddr(<span style="color:#2a00ff">"10.1.1.1"</span>, <span style="color:#2a00ff">"10.10.1.1/24"</span>)
        .uri(<span style="color:#2a00ff">"https://downstream1"</span>)
.route(<span style="color:#2a00ff">"proxied-route"</span>,
    r -> r.remoteAddr(resolver,  <span style="color:#2a00ff">"10.10.1.1"</span>, <span style="color:#2a00ff">"10.10.1.1/24"</span>)
        .uri(<span style="color:#2a00ff">"https://downstream2"</span>)
)</span></span></span>

115.网关过滤器工厂

路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。路由过滤器适用于特定路由。Spring Cloud网关包括许多内置的GatewayFilter工厂。

注意有关如何使用以下任何过滤器的更多详细示例,请查看单元测试

115.1 AddRequestHeader GatewayFilter工厂

AddRequestHeader GatewayFilter工厂采用namevalue参数。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: add_request_header_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - AddRequestHeader</span>=X-Request-Foo<span style="color:#7f0055"><strong>,</strong></span> Bar</span></span></span>

这会将X-Request-Foo:Bar标头添加到所有匹配请求的下游请求标头中。

AddRequestHeader知道用于匹配路径或主机的URI变量。URI变量可用于该值,并将在运行时扩展。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: add_request_header_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Path</span>=/foo/{segment<span style="color:#7f0055"><strong>}</strong></span>
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - AddRequestHeader</span>=X-Request-Foo<span style="color:#7f0055"><strong>,</strong></span> Bar-{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>

115.2 AddRequestParameter GatewayFilter工厂

AddRequestParameter GatewayFilter工厂采用namevalue参数。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: add_request_parameter_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - AddRequestParameter</span>=foo<span style="color:#7f0055"><strong>,</strong></span> bar</span></span></span>

这会将foo=bar添加到所有匹配请求的下游请求的查询字符串中。

AddRequestParameter知道用于匹配路径或主机的URI变量。URI变量可用于该值,并将在运行时扩展。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: add_request_parameter_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Host</span>: {segment}.myhost.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - AddRequestParameter</span>=foo<span style="color:#7f0055"><strong>,</strong></span> bar-{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>

115.3 AddResponseHeader GatewayFilter工厂

AddResponseHeader GatewayFilter工厂采用namevalue参数。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: add_response_header_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - AddResponseHeader</span>=X-Response-Foo<span style="color:#7f0055"><strong>,</strong></span> Bar</span></span></span>

这会将X-Response-Foo:Bar标头添加到所有匹配请求的下游响应的标头中。

AddResponseHeader知道用于匹配路径或主机的URI变量。URI变量可用于该值,并将在运行时扩展。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: add_response_header_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Host</span>: {segment}.myhost.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - AddResponseHeader</span>=foo<span style="color:#7f0055"><strong>,</strong></span> bar-{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>

115.4 DedupeResponseHeader GatewayFilter工厂

DedupeResponseHeader GatewayFilter工厂采用name参数和可选的strategy参数。name可以包含标题名称列表,以空格分隔。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: dedupe_response_header_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - DedupeResponseHeader</span>=Access-Control-Allow-Credentials Access-Control-Allow-Origin</span></span></span>

在网关CORS逻辑和下游逻辑都将它们添加的情况下,这将删除Access-Control-Allow-CredentialsAccess-Control-Allow-Origin响应头的重复值。

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

115.5 Hystrix GatewayFilter工厂

Hystrix是Netflix的一个库,它实现了断路器模式Hystrix GatewayFilter允许您将断路器引入网关路由,保护服务免受级联故障的影响,并允许您在下游故障的情况下提供后备响应。

要在您的项目中启用Hystrix GatewayFilters,请添加对Spring Cloud Netflix中的 spring-cloud-starter-netflix-hystrix的依赖。

Hystrix GatewayFilter工厂需要一个name参数,它是HystrixCommand的名称。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: hystrix_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - Hystrix</span>=myCommandName</span></span></span>

这会将其余过滤器包装在命令名称为myCommandNameHystrixCommand中。

Hystrix过滤器还可以接受可选的fallbackUri参数。当前,仅支持forward:计划的URI。如果调用了后备,则请求将被转发到与URI相匹配的控制器。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: hystrix_route
<span style="color:#7f007f">        uri</span>: lb://backing-service:8088
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Path</span>=/consumingserviceendpoint
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - name</span>: Hystrix
<span style="color:#7f007f">          args</span>:
<span style="color:#7f007f">            name</span>: fallbackcmd
<span style="color:#7f007f">            fallbackUri</span>: forward:/incaseoffailureusethis
<span style="color:#7f007f">        - RewritePath</span>=/consumingserviceendpoint<span style="color:#7f0055"><strong>,</strong></span> /backingserviceendpoint</span></span></span>

调用Hystrix后备广告时,它将转发到/incaseoffailureusethis URI。请注意,此示例还通过目标URI上的lb前缀演示了(可选)Spring Cloud Netflix Ribbon负载均衡。

主要方案是将fallbackUri用于网关应用程序中的内部控制器或处理程序。但是,也可以将请求重新路由到外部应用程序中的控制器或处理程序,如下所示:

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: ingredients
<span style="color:#7f007f">        uri</span>: lb://ingredients
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Path</span>=//ingredients/**
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - name</span>: Hystrix
<span style="color:#7f007f">          args</span>:
<span style="color:#7f007f">            name</span>: fetchIngredients
<span style="color:#7f007f">            fallbackUri</span>: forward:/fallback
<span style="color:#7f007f">      - id</span>: ingredients-fallback
<span style="color:#7f007f">        uri</span>: http://localhost:9994
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Path</span>=/fallback</span></span></span>

在此示例中,网关应用程序中没有fallback端点或处理程序,但是,另一个应用程序中没有fallback端点或处理程序,已在http://localhost:9994下注册。

如果将请求转发到后备,则Hystrix网关过滤器还会提供引起请求的Throwable。它作为ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR属性添加到ServerWebExchange中,可以在网关应用程序中处理后备时使用。

对于外部控制器/处理程序方案,可以添加带有异常详细信息的标头。您可以在FallbackHeaders GatewayFilter Factory部分中找到有关它的更多信息。

Hystrix设置(例如超时)可以使用全局默认值进行配置,也可以使用Hystrix Wiki中所述的应用程序属性在逐条路由的基础上进行配置。

要为上述示例路由设置5秒超时,将使用以下配置:

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds</span>: 5000</span></span></span>

115.6 FallbackHeaders GatewayFilter工厂

FallbackHeaders工厂允许您在转发到外部应用程序中的fallbackUri的请求的标头中添加Hystrix执行异常详细信息,例如以下情况:

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: ingredients
<span style="color:#7f007f">        uri</span>: lb://ingredients
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Path</span>=//ingredients/**
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - name</span>: Hystrix
<span style="color:#7f007f">          args</span>:
<span style="color:#7f007f">            name</span>: fetchIngredients
<span style="color:#7f007f">            fallbackUri</span>: forward:/fallback
<span style="color:#7f007f">      - id</span>: ingredients-fallback
<span style="color:#7f007f">        uri</span>: http://localhost:9994
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Path</span>=/fallback
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - name</span>: FallbackHeaders
<span style="color:#7f007f">          args</span>:
<span style="color:#7f007f">            executionExceptionTypeHeaderName</span>: Test-Header</span></span></span>

在此示例中,在运行HystrixCommand时发生执行异常之后,该请求将转发到fallback端点或运行在localhost:9994上的应用程序中的处理程序。具有异常类型,消息和-if available-根本原因异常类型和消息的标头将由FallbackHeaders过滤器添加到该请求。

通过设置下面列出的参数的值及其默认值,可以在配置中覆盖标头的名称:

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

您可以在Hystrix GatewayFilter工厂部分中找到有关Hystrix与Gateway一起工作的更多信息。

115.7 MapRequestHeader GatewayFilter工厂

MapRequestHeader GatewayFilter要素采用'fromHeader'和'toHeader'参数。它创建一个新的命名标头(toHeader),并从传入的HTTP请求中从现有的命名标头(fromHeader)中提取值。如果输入标头不存在,则过滤器不起作用。如果新的命名标头已经存在,则将使用新值扩充其值。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: map_request_header_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - MapRequestHeader</span>=Bar<span style="color:#7f0055"><strong>,</strong></span> X-Request-Foo</span></span></span>

这会将X-Request-Foo:<values>标头添加到下游请求中,并带有来自传入的HTTP请求Bar标头的更新值。

115.8 PrefixPath GatewayFilter工厂

PrefixPath GatewayFilter工厂采用单个prefix参数。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: prefixpath_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - PrefixPath</span>=/mypath</span></span></span>

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

115.9 PreserveHostHeader GatewayFilter工厂

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

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: preserve_host_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
        - PreserveHostHeader</span></span></span>

115.10 RequestRateLimiter GatewayFilter工厂

RequestRateLimiter GatewayFilter工厂使用RateLimiter实现来确定是否允许继续当前请求。如果不是,则返回状态HTTP 429 - Too Many Requests(默认)。

该过滤器采用一个可选的keyResolver参数和特定于速率限制器的参数(请参见下文)。

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

KeyResolver.java。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>interface</strong></span> KeyResolver {
	Mono<String> resolve(ServerWebExchange exchange);
}</span></span></span>

KeyResolver接口允许可插拔策略派生用于限制请求的密钥。在未来的里程碑中,将有一些KeyResolver实现。

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

默认情况下,如果KeyResolver未找到密钥,则请求将被拒绝。可以使用spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key(对或错)和spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code属性来调整此行为。

|-----------------------------------------------------------------------------------------|-------------------------------------------|
| |
| | 无法通过"快捷方式"符号配置RequestRateLimiter。以下示例无效 |

application.properties。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"># INVALID SHORTCUT CONFIGURATION
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}</span></span></span>

115.10.1 Redis RateLimiter

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

使用的算法是令牌桶算法

redis-rate-limiter.replenishRate是您希望用户每秒允许多少个请求,而没有任何丢弃的请求。这是令牌桶被填充的速率。

redis-rate-limiter.burstCapacity是允许用户在一秒钟内执行的最大请求数。这是令牌桶可以容纳的令牌数。将此值设置为零将阻止所有请求。

通过在replenishRateburstCapacity中设置相同的值可以达到稳定的速率。通过将burstCapacity设置为高于replenishRate,可以允许临时突发。在这种情况下,速率限制器需要在突发之间间隔一段时间(根据replenishRate),因为2个连续的突发将导致请求丢失(HTTP 429 - Too Many Requests)。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: requestratelimiter_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - name</span>: RequestRateLimiter
<span style="color:#7f007f">          args</span>:
<span style="color:#7f007f">            redis-rate-limiter.replenishRate</span>: 10
<span style="color:#7f007f">            redis-rate-limiter.burstCapacity</span>: 20</span></span></span>

Config.java。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@Bean</span></em>
KeyResolver userKeyResolver() {
    <span style="color:#7f0055"><strong>return</strong></span> exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst(<span style="color:#2a00ff">"user"</span>));
}</span></span></span>

这定义了每个用户10的请求速率限制。允许20个突发,但是下一秒只有10个请求可用。KeyResolver是一个简单的参数,它获取user请求参数(注意:不建议在生产中使用)。

速率限制器也可以定义为实现RateLimiter接口的bean。在配置中,使用SpEL通过名称引用bean。#{@myRateLimiter}是一个SpEL表达式,引用名称为myRateLimiter的bean。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: requestratelimiter_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - name</span>: RequestRateLimiter
<span style="color:#7f007f">          args</span>:
<span style="color:#7f007f">            rate-limiter</span>: <span style="color:#2a00ff">"#{@myRateLimiter}"</span>
<span style="color:#7f007f">            key-resolver</span>: <span style="color:#2a00ff">"#{@userKeyResolver}"</span></span></span></span>

115.11重定向到GatewayFilter工厂

RedirectTo GatewayFilter工厂采用一个status和一个url参数。状态应该是300系列重定向http代码,例如301。URL应该是有效的URL。这将是Location标头的值。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: prefixpath_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - RedirectTo</span>=302<span style="color:#7f0055"><strong>,</strong></span> https://acme.org</span></span></span>

这将发送带有Location:https://acme.org标头的状态302以执行重定向。

115.12 RemoveRequestHeader GatewayFilter工厂

RemoveRequestHeader GatewayFilter工厂采用一个name参数。它是要删除的标题的名称。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: removerequestheader_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - RemoveRequestHeader</span>=X-Request-Foo</span></span></span>

这将删除X-Request-Foo标头,然后将其发送到下游。

115.13 RemoveResponseHeader GatewayFilter工厂

RemoveResponseHeader GatewayFilter工厂采用一个name参数。它是要删除的标题的名称。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: removeresponseheader_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - RemoveResponseHeader</span>=X-Response-Foo</span></span></span>

这会将X-Response-Foo标头从响应中删除,然后将其返回到网关客户端。

要删除任何类型的敏感标头,应为可能需要的任何路由配置此过滤器。此外,您可以使用spring.cloud.gateway.default-filters一次配置此过滤器,并将其应用于所有路由。

115.14 RewritePath GatewayFilter工厂

RewritePath GatewayFilter工厂采用路径regexp参数和replacement参数。这使用Java正则表达式提供了一种灵活的方式来重写请求路径。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: rewritepath_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Path</span>=/foo/**
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - RewritePath</span>=/foo(?<segment>/?.*)<span style="color:#7f0055"><strong>,</strong></span> $\{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>

对于/foo/bar的请求路径,这将在发出下游请求之前将路径设置为/bar。请注意,由于YAML规范,$\$所取代。

115.15 RewriteLocationResponseHeader GatewayFilter工厂

RewriteLocationResponseHeader GatewayFilter工厂通常会修改Location响应标头的值,以摆脱后端特定的详细信息。它需要stripVersionModelocationHeaderNamehostValueprotocolsRegex参数。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: rewritelocationresponseheader_route
<span style="color:#7f007f">        uri</span>: http://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - RewriteLocationResponseHeader</span>=AS_IN_REQUEST<span style="color:#7f0055"><strong>,</strong></span> Location<span style="color:#7f0055"><strong>,</strong></span> <span style="color:#7f0055"><strong>,</strong></span></span></span></span>

例如,对于请求POST https://api.example.com/some/object/nameLocation响应标头值https://object-service.prod.example.net/v2/some/object/id将被重写为https://api.example.com/some/object/id

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

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

参数hostValue(如果提供)将用于替换响应Location标头中的host:port部分。如果未提供,将使用Host请求标头的值。

参数protocolsRegex必须是有效的正则表达式String,协议名称将与之匹配。如果不匹配,过滤器将不执行任何操作。默认值为http|https|ftp|ftps

115.16 RewriteResponseHeader GatewayFilter工厂

RewriteResponseHeader GatewayFilter工厂采用nameregexpreplacement参数。它使用Java正则表达式以灵活的方式重写响应标头值。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: rewriteresponseheader_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - RewriteResponseHeader</span>=X-Response-Foo<span style="color:#7f0055"><strong>,</strong></span> <span style="color:#7f0055"><strong>,</strong></span> password=[^&]+<span style="color:#7f0055"><strong>,</strong></span> password=***</span></span></span>

对于标头值为/42?user=ford&password=omg!what&flag=true,在发出下游请求后它将被设置为/42?user=ford&password=***&flag=true。由于YAML规范,请使用$\来表示$

115.17 SaveSession GatewayFilter工厂

向下游转发呼叫之前 ,SaveSession GatewayFilter工厂强制执行WebSession::save操作。这在将Spring Session之类的内容用于惰性数据存储并且需要确保在进行转接呼叫之前已保存会话状态时特别有用。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: save_session
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Path</span>=/foo/**
<span style="color:#7f007f">        filters</span>:
        - SaveSession</span></span></span>

如果您将Spring Security与Spring Session 集成在一起,并且想要确保安全性详细信息已转发到远程进程,则至关重要。

115.18 SecureHeaders GatewayFilter工厂

SecureHeaders GatewayFilter Factory根据此博客文章的建议向响应中添加了许多标头。
添加了以下标头(以及默认值):

  • X-Xss-Protection:1; mode=block
  • Strict-Transport-Security:max-age=631138519
  • X-Frame-Options:DENY
  • X-Content-Type-Options:nosniff
  • Referrer-Policy:no-referrer
  • Content-Security-Policy:default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'
  • X-Download-Options:noopen
  • X-Permitted-Cross-Domain-Policies:none

要更改默认值,请在spring.cloud.gateway.filter.secure-headers名称空间中设置适当的属性:
Property进行更改:

  • 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

|-----------------------------------------------------------------------------------------|-----------------|
| |
| | 需要使用小写和安全标头的全名。 |

可以使用以下值:

  • x-xss-protection
  • strict-transport-security
  • x-frame-options
  • x-content-type-options
  • referrer-policy
  • content-security-policy
  • x-download-options
  • x-permitted-cross-domain-policies

例: spring.cloud.gateway.filter.secure-headers.disable=x-frame-options,strict-transport-security

115.19 SetPath GatewayFilter工厂

SetPath GatewayFilter工厂采用路径template参数。通过允许路径的模板段,它提供了一种操作请求路径的简单方法。这将使用Spring Framework中的uri模板。允许多个匹配段。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: setpath_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Path</span>=/foo/{segment<span style="color:#7f0055"><strong>}</strong></span>
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - SetPath</span>=/{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>

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

115.20 SetRequestHeader GatewayFilter工厂

SetRequestHeader GatewayFilter工厂采用namevalue参数。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: setrequestheader_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - SetRequestHeader</span>=X-Request-Foo<span style="color:#7f0055"><strong>,</strong></span> Bar</span></span></span>

该GatewayFilter用给定的名称替换所有标头,而不是添加。因此,如果下游服务器响应X-Request-Foo:1234,则将其替换为X-Request-Foo:Bar,下游服务将收到此信息。

SetRequestHeader知道用于匹配路径或主机的URI变量。URI变量可用于该值,并将在运行时扩展。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: setrequestheader_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Host</span>: {segment}.myhost.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - SetRequestHeader</span>=foo<span style="color:#7f0055"><strong>,</strong></span> bar-{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>

115.21 SetResponseHeader GatewayFilter工厂

SetResponseHeader GatewayFilter工厂采用namevalue参数。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: setresponseheader_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - SetResponseHeader</span>=X-Response-Foo<span style="color:#7f0055"><strong>,</strong></span> Bar</span></span></span>

该GatewayFilter用给定的名称替换所有标头,而不是添加。因此,如果下游服务器以X-Response-Foo:1234响应,则将其替换为X-Response-Foo:Bar,这是网关客户端将收到的内容。

SetResponseHeader知道用于匹配路径或主机的URI变量。URI变量可用于该值,并将在运行时扩展。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: setresponseheader_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Host</span>: {segment}.myhost.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - SetResponseHeader</span>=foo<span style="color:#7f0055"><strong>,</strong></span> bar-{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>

115.22 SetStatus GatewayFilter工厂

SetStatus GatewayFilter工厂采用单个status参数。它必须是有效的Spring HttpStatus。它可以是整数值404,也可以是枚举NOT_FOUND的字符串表示形式。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: setstatusstring_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - SetStatus</span>=BAD_REQUEST
<span style="color:#7f007f">      - id</span>: setstatusint_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - SetStatus</span>=401</span></span></span>

无论哪种情况,响应的HTTP状态都将设置为401。

115.23 StripPrefix GatewayFilter工厂

StripPrefix GatewayFilter工厂采用一个参数partsparts参数指示在向下游发送请求之前,要从请求中剥离的路径中的零件数。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: nameRoot
<span style="color:#7f007f">        uri</span>: http://nameservice
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Path</span>=/name/**
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - StripPrefix</span>=2</span></span></span>

通过网关发送到/name/bar/foo的请求时,对nameservice的请求将类似于http://nameservice/foo

115.24重试GatewayFilter工厂

Retry GatewayFilter Factory支持以下参数集:

  • 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-3次
  • series --- 5XX系列
  • methods --- GET方法
  • exceptions-IOExceptionTimeoutException
  • backoff-已禁用

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: retry_test
<span style="color:#7f007f">        uri</span>: http://localhost:8080/flakey
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Host</span>=*.retry.com
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - name</span>: Retry
<span style="color:#7f007f">          args</span>:
<span style="color:#7f007f">            retries</span>: 3
<span style="color:#7f007f">            statuses</span>: BAD_GATEWAY
<span style="color:#7f007f">            methods</span>: GET,POST
<span style="color:#7f007f">            backoff</span>:
<span style="color:#7f007f">              firstBackoff</span>: 10ms
<span style="color:#7f007f">              maxBackoff</span>: 50ms
<span style="color:#7f007f">              factor</span>: 2
<span style="color:#7f007f">              basedOnPreviousValue</span>: <span style="color:#7f0055"><strong>false</strong></span></span></span></span>

|-----------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| |
| | 当使用带有forward:前缀URL的重试过滤器时,应仔细编写目标端点,以便在发生错误的情况下不会执行任何可能导致响应发送到客户端并提交的操作。例如,如果目标端点是带注释的控制器,则目标控制器方法不应返回带有错误状态代码的ResponseEntity。相反,它应该抛出一个Exception,或者例如通过一个Mono.error(ex)返回值来发出错误信号,可以将重试过滤器配置为通过重试来处理。 |

|-----------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| |
| | 当将重试过滤器与任何具有主体的HTTP方法一起使用时,主体将被缓存,并且网关将受到内存的限制。正文被缓存在ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR定义的请求属性中。对象的类型是org.springframework.core.io.buffer.DataBuffer。 |

115.25 RequestSize GatewayFilter工厂

当请求大小大于允许的限制时,RequestSize GatewayFilter工厂可以限制请求到达下游服务。过滤器采用maxSize参数,该参数是请求的允许大小限制。maxSize is a `DataSize类型,因此值可以定义为数字,后跟可选的DataUnit后缀,例如'KB'或'MB'。字节的默认值为" B"。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: request_size_route
<span style="color:#7f007f">      uri</span>: http://localhost:8080/upload
<span style="color:#7f007f">      predicates</span>:
<span style="color:#7f007f">      - Path</span>=/upload
<span style="color:#7f007f">      filters</span>:
<span style="color:#7f007f">      - name</span>: RequestSize
<span style="color:#7f007f">        args</span>:
<span style="color:#7f007f">          maxSize</span>: 5000000</span></span></span>

当请求因大小而被拒绝时,RequestSize GatewayFilter Factory将响应状态设置为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。 |

115.26修改请求正文GatewayFilter工厂

该过滤器被认为是BETA,API将来可能会更改

ModifyRequestBody过滤器可用于在网关向下游发送请求主体之前修改请求主体。

|-----------------------------------------------------------------------------------------|--------------------|
| |
| | 只能使用Java DSL配置此过滤器 |

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> RouteLocator routes(RouteLocatorBuilder builder) {
    <span style="color:#7f0055"><strong>return</strong></span> builder.routes()
        .route(<span style="color:#2a00ff">"rewrite_request_obj"</span>, r -> r.host(<span style="color:#2a00ff">"*.rewriterequestobj.org"</span>)
            .filters(f -> f.prefixPath(<span style="color:#2a00ff">"/httpbin"</span>)
                .modifyRequestBody(String.<span style="color:#7f0055"><strong>class</strong></span>, Hello.<span style="color:#7f0055"><strong>class</strong></span>, MediaType.APPLICATION_JSON_VALUE,
                    (exchange, s) -> <span style="color:#7f0055"><strong>return</strong></span> Mono.just(<span style="color:#7f0055"><strong>new</strong></span> Hello(s.toUpperCase())))).uri(uri))
        .build();
}

<span style="color:#7f0055"><strong>static</strong></span> <span style="color:#7f0055"><strong>class</strong></span> Hello {
    String message;

    <span style="color:#7f0055"><strong>public</strong></span> Hello() { }

    <span style="color:#7f0055"><strong>public</strong></span> Hello(String message) {
        <span style="color:#7f0055"><strong>this</strong></span>.message = message;
    }

    <span style="color:#7f0055"><strong>public</strong></span> String getMessage() {
        <span style="color:#7f0055"><strong>return</strong></span> message;
    }

    <span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>void</strong></span> setMessage(String message) {
        <span style="color:#7f0055"><strong>this</strong></span>.message = message;
    }
}</span></span></span>

115.27修改响应主体GatewayFilter工厂

该过滤器被认为是BETA,API将来可能会更改

ModifyResponseBody过滤器可用于在将响应正文发送回客户端之前对其进行修改。

|-----------------------------------------------------------------------------------------|--------------------|
| |
| | 只能使用Java DSL配置此过滤器 |

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> RouteLocator routes(RouteLocatorBuilder builder) {
    <span style="color:#7f0055"><strong>return</strong></span> builder.routes()
        .route(<span style="color:#2a00ff">"rewrite_response_upper"</span>, r -> r.host(<span style="color:#2a00ff">"*.rewriteresponseupper.org"</span>)
            .filters(f -> f.prefixPath(<span style="color:#2a00ff">"/httpbin"</span>)
        		.modifyResponseBody(String.<span style="color:#7f0055"><strong>class</strong></span>, String.<span style="color:#7f0055"><strong>class</strong></span>,
        		    (exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri)
        .build();
}</span></span></span>

115.28默认过滤器

如果您要添加过滤器并将其应用于所有路由,则可以使用spring.cloud.gateway.default-filters。该属性采用过滤器列表

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      default-filters</span>:
<span style="color:#7f007f">      - AddResponseHeader</span>=X-Response-Default-Foo<span style="color:#7f0055"><strong>,</strong></span> Default-Bar
<span style="color:#7f007f">      - PrefixPath</span>=/httpbin</span></span></span>

116.全局过滤器

GlobalFilter接口具有与GatewayFilter相同的签名。这些是特殊过滤器,有条件地应用于所有路由。(此接口和用法可能会在将来的里程碑中更改)。

116.1组合的全局过滤器和GatewayFilter排序

当有请求进入(并与路由匹配)时,过滤Web处理程序会将GlobalFilter的所有实例和GatewayFilter的所有特定于路由的实例添加到过滤器链中。该组合的过滤器链通过org.springframework.core.Ordered接口排序,可以通过实现getOrder()方法进行设置。

由于Spring Cloud网关区分执行过滤器逻辑的"前"阶段和"后"阶段(请参阅:工作原理),因此,具有最高优先级的过滤器将在"前"阶段中处于第一个阶段,在"阶段"中处于最后一个阶段。 "后期"阶段。

ExampleConfiguration.java。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> GlobalFilter customFilter() {
    <span style="color:#7f0055"><strong>return</strong></span> <span style="color:#7f0055"><strong>new</strong></span> CustomGlobalFilter();
}

<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> CustomGlobalFilter <span style="color:#7f0055"><strong>implements</strong></span> GlobalFilter, Ordered {

    <em><span style="color:gray">@Override</span></em>
    <span style="color:#7f0055"><strong>public</strong></span> Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info(<span style="color:#2a00ff">"custom global filter"</span>);
        <span style="color:#7f0055"><strong>return</strong></span> chain.filter(exchange);
    }

    <em><span style="color:gray">@Override</span></em>
    <span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>int</strong></span> getOrder() {
        <span style="color:#7f0055"><strong>return</strong></span> -1;
    }
}</span></span></span>

116.2转发路由过滤器

ForwardRoutingFilter在交换属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR中寻找URI。如果该网址具有forward方案(即forward:///localendpoint),它将使用Spring DispatcherHandler处理请求。请求URL的路径部分将被转发URL中的路径覆盖。未经修改的原始URL会附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。

116.3 LoadBalancerClient筛选器

LoadBalancerClientFilter在交换属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR中寻找URI。如果该网址具有lb方案(即lb://myservice),它将使用Spring Cloud LoadBalancerClient将名称(上例中为myservice)解析为实际的主机和端口并替换相同属性中的URI。未经修改的原始URL会附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。过滤器还将查看ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR属性,以查看其是否等于lb,然后应用相同的规则。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: myRoute
<span style="color:#7f007f">        uri</span>: lb://service
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Path</span>=/service/**</span></span></span>

|-----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|
| |
| | 默认情况下,当在LoadBalancer中找不到服务实例时,将返回503。您可以通过设置spring.cloud.gateway.loadbalancer.use404=true来配置网关以返回404。 |

|-----------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| |
| | 从LoadBalancer返回的ServiceInstanceisSecure值将覆盖对网关的请求中指定的方案。例如,如果请求通过HTTPS进入网关,但ServiceInstance表示它不安全,则下游请求将通过HTTP发出。相反的情况也可以适用。但是,如果在网关配置中为路由指定了GATEWAY_SCHEME_PREFIX_ATTR,则前缀将被删除,并且来自路由URL的结果方案将覆盖ServiceInstance配置。 |

|-----------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| |
| | LoadBalancerClientFilter在引擎盖下使用阻挡物Ribbon LoadBalancerClient。我们建议您改用ReactiveLoadBalancerClientFilter。您可以通过向项目添加org.springframework.cloud:spring-cloud-loadbalancer依赖项并将spring.cloud.loadbalancer.ribbon.enabled的值设置为false来切换为使用它。 |

116.4 ReactiveLoadBalancerClientFilter

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

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: myRoute
<span style="color:#7f007f">        uri</span>: lb://service
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Path</span>=/service/**</span></span></span>

|-----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|
| |
| | 默认情况下,当ReactorLoadBalancer无法找到服务实例时,将返回503。您可以通过设置spring.cloud.gateway.loadbalancer.use404=true将网关配置为返回404。 |

|-----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| |
| | 从ReactiveLoadBalancerClientFilter返回的ServiceInstanceisSecure值将覆盖对网关的请求中指定的方案。例如,如果请求通过HTTPS进入网关,但ServiceInstance表示它不安全,则下游请求将通过HTTP发出。相反的情况也可以适用。但是,如果在网关配置中为路由指定了GATEWAY_SCHEME_PREFIX_ATTR,则前缀将被删除,并且从路由URL生成的方案将覆盖ServiceInstance配置。 |

116.5网络路由过滤器

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

116.6 Netty写响应过滤器

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

116.7 RouteToRequestUrl过滤器

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

如果URI具有方案前缀(例如lb:ws://serviceid),则将从URI中剥离lb方案,并将其放在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR中,以供以后在过滤器链中使用。

116.8 Websocket路由过滤器

如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR交换属性中的URL具有wswss方案,则Websocket路由筛选器将运行。它使用Spring Web套接字基础结构向下游转发Websocket请求。

通过在URI前面加上lb,例如lb:ws://serviceid,可以实现Websocket的负载均衡。

|-----------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|
| |
| | 如果您将SockJS用作常规http的后备,则应配置常规HTTP路由以及Websocket路由。 |

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
      <span style="color:#3f5f5f"><em># SockJS route</em></span>
<span style="color:#7f007f">      - id</span>: websocket_sockjs_route
<span style="color:#7f007f">        uri</span>: http://localhost:3001
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Path</span>=/websocket/info/**
      <span style="color:#3f5f5f"><em># Normal Websocket route</em></span>
<span style="color:#7f007f">      - id</span>: websocket_route
<span style="color:#7f007f">        uri</span>: ws://localhost:3001
<span style="color:#7f007f">        predicates</span>:
<span style="color:#7f007f">        - Path</span>=/websocket/**</span></span></span>

116.9网关指标过滤器

要启用网关度量标准,请添加spring-boot-starter-actuator作为项目依赖项。然后,默认情况下,只要属性spring.cloud.gateway.metrics.enabled未设置为false,网关度量过滤器就会运行。该过滤器添加了一个带有以下标记的名为" gateway.requests"的计时器指标:

  • routeId:路线ID
  • routeUri:API将被路由到的URI
  • outcome:根据HttpStatus.Series分类的结果
  • status:返回给客户端的请求的Http状态
  • httpStatusCode:返回给客户端的请求的Http状态
  • httpMethod:用于请求的Http方法

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

|-----------------------------------------------------------------------------------------|-----------------------------------------------------------|
| |
| | 要启用Prometheus端点,请添加micrometer-registry-prometheus作为项目依赖项。 |

116.10将交换标记为已路由

网关路由ServerWebExchange后,它将通过在交换属性中添加gatewayAlreadyRouted将该交换标记为"已路由"。将请求标记为已路由后,其他路由筛选器将不会再次路由请求,实质上会跳过该筛选器。您可以使用多种便捷方法将交换标记为已路由,或者检查交换是否已路由。

  • ServerWebExchangeUtils.isAlreadyRouted接受ServerWebExchange对象,并检查其是否已"路由"
  • ServerWebExchangeUtils.setAlreadyRouted接受ServerWebExchange对象,并将其标记为"已路由"

117. HttpHeadersFilters

HttpHeadersFilters在向下游发送请求之前(例如,在NettyRoutingFilter中)已应用于请求。

117.1转发的标题过滤器

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

117.2 RemoveHopByHop标头过滤器

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

  • 连接
  • 活着
  • 代理验证
  • 代理授权
  • TE
  • 预告片
  • 传输编码
  • 升级

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

117.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

118. TLS / SSL

网关可以通过遵循常规的Spring服务器配置来侦听https上的请求。例:

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">server</span>:
<span style="color:#7f007f">  ssl</span>:
<span style="color:#7f007f">    enabled</span>: <span style="color:#7f0055"><strong>true</strong></span>
<span style="color:#7f007f">    key-alias</span>: scg
<span style="color:#7f007f">    key-store-password</span>: scg1234
<span style="color:#7f007f">    key-store</span>: classpath:scg-keystore.p12
<span style="color:#7f007f">    key-store-type</span>: PKCS12</span></span></span>

网关路由可以同时路由到http和https后端。如果路由到https后端,则可以使用以下配置将网关配置为信任所有下游证书:

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      httpclient</span>:
<span style="color:#7f007f">        ssl</span>:
<span style="color:#7f007f">          useInsecureTrustManager</span>: <span style="color:#7f0055"><strong>true</strong></span></span></span></span>

使用不安全的信任管理器不适用于生产。对于生产部署,可以为网关配置一组可以通过以下配置信任的已知证书:

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      httpclient</span>:
<span style="color:#7f007f">        ssl</span>:
<span style="color:#7f007f">          trustedX509Certificates</span>:
          - cert1.pem
          - cert2.pem</span></span></span>

如果Spring Cloud网关未配置受信任的证书,则使用默认的信任存储(可以使用系统属性javax.net.ssl.trustStore覆盖)。

118.1 TLS握手

网关维护一个客户端池,该客户端池用于路由到后端。通过https进行通信时,客户端会启动TLS握手。许多超时与此握手相关联。可以配置以下超时(显示默认值):

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      httpclient</span>:
<span style="color:#7f007f">        ssl</span>:
<span style="color:#7f007f">          handshake-timeout-millis</span>: 10000
<span style="color:#7f007f">          close-notify-flush-timeout-millis</span>: 3000
<span style="color:#7f007f">          close-notify-read-timeout-millis</span>: 0</span></span></span>

119.配置

Spring Cloud网关的配置由RouteDefinitionLocator的集合驱动。

RouteDefinitionLocator.java。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>interface</strong></span> RouteDefinitionLocator {
	Flux<RouteDefinition> getRouteDefinitions();
}</span></span></span>

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

上面的所有配置示例都使用一种快捷方式符号,该快捷方式符号使用位置参数而不是命名参数。以下两个示例是等效的:

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      routes</span>:
<span style="color:#7f007f">      - id</span>: setstatus_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - name</span>: SetStatus
<span style="color:#7f007f">          args</span>:
<span style="color:#7f007f">            status</span>: 401
<span style="color:#7f007f">      - id</span>: setstatusshortcut_route
<span style="color:#7f007f">        uri</span>: https://example.org
<span style="color:#7f007f">        filters</span>:
<span style="color:#7f007f">        - SetStatus</span>=401</span></span></span>

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

119.1 Fluent Java Routes API

为了在Java中进行简单的配置,在RouteLocatorBuilder bean中定义了一个流畅的API。

GatewaySampleApplication.java。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#3f5f5f"><em>// static imports from GatewayFilters and RoutePredicates</em></span>
<em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> RouteLocator customRouteLocator(RouteLocatorBuilder builder, ThrottleGatewayFilterFactory throttle) {
    <span style="color:#7f0055"><strong>return</strong></span> builder.routes()
            .route(r -> r.host(<span style="color:#2a00ff">"**.abc.org"</span>).and().path(<span style="color:#2a00ff">"/image/png"</span>)
                .filters(f ->
                        f.addResponseHeader(<span style="color:#2a00ff">"X-TestHeader"</span>, <span style="color:#2a00ff">"foobar"</span>))
                .uri(<span style="color:#2a00ff">"http://httpbin.org:80"</span>)
            )
            .route(r -> r.path(<span style="color:#2a00ff">"/image/webp"</span>)
                .filters(f ->
                        f.addResponseHeader(<span style="color:#2a00ff">"X-AnotherHeader"</span>, <span style="color:#2a00ff">"baz"</span>))
                .uri(<span style="color:#2a00ff">"http://httpbin.org:80"</span>)
            )
            .route(r -> r.order(-1)
                .host(<span style="color:#2a00ff">"**.throttle.org"</span>).and().path(<span style="color:#2a00ff">"/get"</span>)
                .filters(f -> f.filter(throttle.apply(1,
                        1,
                        10,
                        TimeUnit.SECONDS)))
                .uri(<span style="color:#2a00ff">"http://httpbin.org:80"</span>)
            )
            .build();
}</span></span></span>

此样式还允许更多自定义谓词断言。RouteDefinitionLocator beans定义的谓词使用逻辑and进行组合。通过使用流畅的Java API,您可以在Predicate类上使用and()or()negate()运算符。

119.2 DiscoveryClient路由定义定位器

可以将网关配置为基于在DiscoveryClient兼容服务注册表中注册的服务来创建路由。

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

119.2.1为DiscoveryClient路由配置谓词和过滤器

默认情况下,网关为通过DiscoveryClient创建的路由定义单个谓词和过滤器。

默认谓词是使用模式/serviceId/**定义的路径谓词,其中serviceIdDiscoveryClient中服务的ID。

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

如果要自定义DiscoveryClient路由使用的谓词和/或过滤器,可以通过设置spring.cloud.gateway.discovery.locator.predicates[x]spring.cloud.gateway.discovery.locator.filters[y]来实现。这样做时,如果要保留该功能,则需要确保在上面包含默认谓词和过滤器。以下是此示例的示例。

application.properties。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">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: Hystrix
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}'"</span></span></span>

120. Reactor Netty访问日志

要启用Reactor Netty访问日志,请设置-Dreactor.netty.http.server.accessLogEnabled=true。(它必须是Java系统Property,而不是Spring Boot属性)。

日志系统可以配置为具有单独的访问日志文件。以下是示例登录配置:

logback.xml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">    <span style="color:#3f7f7f"><appender</span> <span style="color:#7f007f">name</span>=<span style="color:#2a00ff">"accessLog"</span> <span style="color:#7f007f">class</span>=<span style="color:#2a00ff">"ch.qos.logback.core.FileAppender"</span><span style="color:#3f7f7f">></span>
        <span style="color:#3f7f7f"><file></span>access_log.log<span style="color:#3f7f7f"></file></span>
        <span style="color:#3f7f7f"><encoder></span>
            <span style="color:#3f7f7f"><pattern></span>%msg%n<span style="color:#3f7f7f"></pattern></span>
        <span style="color:#3f7f7f"></encoder></span>
    <span style="color:#3f7f7f"></appender></span>
    <span style="color:#3f7f7f"><appender</span> <span style="color:#7f007f">name</span>=<span style="color:#2a00ff">"async"</span> <span style="color:#7f007f">class</span>=<span style="color:#2a00ff">"ch.qos.logback.classic.AsyncAppender"</span><span style="color:#3f7f7f">></span>
        <span style="color:#3f7f7f"><appender-ref</span> <span style="color:#7f007f">ref</span>=<span style="color:#2a00ff">"accessLog"</span><span style="color:#3f7f7f"> /></span>
    <span style="color:#3f7f7f"></appender></span>

    <span style="color:#3f7f7f"><logger</span> <span style="color:#7f007f">name</span>=<span style="color:#2a00ff">"reactor.netty.http.server.AccessLog"</span> <span style="color:#7f007f">level</span>=<span style="color:#2a00ff">"INFO"</span> <span style="color:#7f007f">additivity</span>=<span style="color:#2a00ff">"false"</span><span style="color:#3f7f7f">></span>
        <span style="color:#3f7f7f"><appender-ref</span> <span style="color:#7f007f">ref</span>=<span style="color:#2a00ff">"async"</span><span style="color:#3f7f7f">/></span>
    <span style="color:#3f7f7f"></logger></span></span></span></span>

121. CORS配置

可以将网关配置为控制CORS行为。"全局" CORS配置是URL模式到Spring Framework CorsConfiguration的映射。

application.yml。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f">  cloud</span>:
<span style="color:#7f007f">    gateway</span>:
<span style="color:#7f007f">      globalcors</span>:
<span style="color:#7f007f">        corsConfigurations</span>:
<span style="color:#7f007f">          '[/**]'</span>:
<span style="color:#7f007f">            allowedOrigins</span>: <span style="color:#2a00ff">"https://docs.spring.io"</span>
<span style="color:#7f007f">            allowedMethods</span>:
            - GET</span></span></span>

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

要为未被某些网关路由谓词处理的请求提供相同的CORS配置,请将属性spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping设置为true。当尝试支持CORS预检请求并且您的路由谓词未评估为true时,这很有用,因为http方法为options

122.执行器API

/gateway执行器端点允许监视Spring Cloud Gateway应用程序并与之交互。为了可远程访问,必须在应用程序属性中通过HTTP或JMX启用公开端点。

application.properties。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">management.endpoint.gateway.enabled</span>=true <span style="color:#3f5f5f"><em># default value</em></span>
<span style="color:#7f007f">management.endpoints.web.exposure.include</span>=gateway</span></span></span>

122.1详细执行器格式

一种新的,更详细的格式已添加到网关。这为每个路由增加了更多细节,从而允许查看与每个路由关联的谓词和过滤器以及任何可用的配置。

/actuator/gateway/routes

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>[</strong></span>
  <span style="color:#7f0055"><strong>{</strong></span>
    <span style="color:#2a00ff">"predicate"</span>: <span style="color:#2a00ff">"(Hosts: [**.addrequestheader.org] && Paths: [/headers], match trailing slash: true)"</span><span style="color:#7f0055"><strong>,</strong></span>
    <span style="color:#2a00ff">"route_id"</span>: <span style="color:#2a00ff">"add_request_header_test"</span><span style="color:#7f0055"><strong>,</strong></span>
    <span style="color:#2a00ff">"filters"</span>: <span style="color:#7f0055"><strong>[</strong></span>
      <span style="color:#2a00ff">"[[AddResponseHeader X-Response-Default-Foo = 'Default-Bar'], order = 1]"</span><span style="color:#7f0055"><strong>,</strong></span>
      <span style="color:#2a00ff">"[[AddRequestHeader X-Request-Foo = 'Bar'], order = 1]"</span><span style="color:#7f0055"><strong>,</strong></span>
      <span style="color:#2a00ff">"[[PrefixPath prefix = '/httpbin'], order = 2]"</span>
    ]<span style="color:#7f0055"><strong>,</strong></span>
    <span style="color:#2a00ff">"uri"</span>: <span style="color:#2a00ff">"lb://testservice"</span><span style="color:#7f0055"><strong>,</strong></span>
    <span style="color:#2a00ff">"order"</span>: 0
  <span style="color:#7f0055"><strong>}</strong></span>
<span style="color:#7f0055"><strong>]</strong></span></span></span></span>

要启用此功能,请设置以下属性:

application.properties。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring.cloud.gateway.actuator.verbose.enabled</span>=true</span></span></span>

在将来的版本中,该默认值为true。

122.2检索路由过滤器

122.2.1全局过滤器

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

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">{
  "org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@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
}</span></span></span>

该响应包含适当的全局过滤器的详细信息。为每个全局过滤器提供过滤器对象的字符串表示形式(例如org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@77856cc5)和过滤器链中的相应顺序

122.2.2路由过滤器

要检索应用于路由的GatewayFilter工厂,请向/actuator/gateway/routefilters发出GET请求。产生的响应类似于以下内容:

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">{
  "[AddRequestHeaderGatewayFilterFactory@570ed9c configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,
  "[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]": null,
  "[SaveSessionGatewayFilterFactory@4449b273 configClass = Object]": null
}</span></span></span>

该响应包含应用于任何特定路由的GatewayFilter工厂的详细信息。为每个工厂提供相应对象的字符串表示形式(例如[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object])。请注意,null值是由于端点控制器的实现不完整而导致的,因为它试图设置对象在过滤器链中的顺序,该顺序不适用于GatewayFilter工厂对象。

122.3刷新路由缓存

要清除路由缓存,请向/actuator/gateway/refresh发出POST请求。该请求返回200,但没有响应主体。

122.4检索网关中定义的路由

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

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">[{
  "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
}]</span></span></span>

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

路径 类型 描述
route_id String The route id.
route_object.predicate Object The route predicate.
route_object.filters Array The GatewayFilter factories applied to the route.
order Number The route order.

122.5检索有关特定路线的信息

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

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">{
  "id": "first_route",
  "predicates": [{
    "name": "Path",
    "args": {"_genkey_0":"/first"}
  }],
  "filters": [],
  "uri": "https://www.uri-destination.org",
  "order": 0
}]</span></span></span>

下表描述了响应的结构。

路径 类型 描述
id String The route id.
predicates Array The collection of route predicates. Each item defines the name and the arguments of a given predicate.
filters Array The collection of filters applied to the route.
uri String The destination URI of the route.
order Number The route order.

122.6创建和删除特定路线

要创建路由,请使用指定路由字段的JSON正文向/gateway/routes/{id_route_to_create}发出POST请求(请参见上一小节)。

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

122.7概述:所有端点的列表

下表总结了Spring Cloud网关执行器端点。请注意,每个端点都有/actuator/gateway作为基本路径。

ID HTTP方法 描述
globalfilters GET Displays the list of global filters applied to the routes.
routefilters GET Displays the list of GatewayFilter factories applied to a particular route.
refresh POST Clears the routes cache.
routes GET Displays the list of routes defined in the gateway.
routes/{id} GET Displays information about a particular route.
routes/{id} POST Add a new route to the gateway.
routes/{id} DELETE Remove an existing route from the gateway.

123.故障排除

123.1日志级别

以下是一些有用的记录器,它们包含DEBUGTRACE级别的有价值的故障排除信息。

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

123.2窃听

Reactor Netty HttpClientHttpServer可以启用窃听功能。与将reactor.netty日志级别设置为DEBUGTRACE结合使用时,将允许记录信息,例如通过网络发送和接收的标头和正文。要启用此功能,请分别为HttpServerHttpClient设置spring.cloud.gateway.httpserver.wiretap=true和/或spring.cloud.gateway.httpclient.wiretap=true

124.开发人员指南

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

124.1编写自定义路由谓词工厂

为了编写路由谓词,您将需要实现RoutePredicateFactory。您可以扩展名为AbstractRoutePredicateFactory的抽象类。

MyRoutePredicateFactory.java。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> MyRoutePredicateFactory <span style="color:#7f0055"><strong>extends</strong></span> AbstractRoutePredicateFactory<HeaderRoutePredicateFactory.Config> {

    <span style="color:#7f0055"><strong>public</strong></span> MyRoutePredicateFactory() {
        <span style="color:#7f0055"><strong>super</strong></span>(Config.<span style="color:#7f0055"><strong>class</strong></span>);
    }

    <em><span style="color:gray">@Override</span></em>
    <span style="color:#7f0055"><strong>public</strong></span> Predicate<ServerWebExchange> apply(Config config) {
        <span style="color:#3f5f5f"><em>// grab configuration from Config object</em></span>
        <span style="color:#7f0055"><strong>return</strong></span> exchange -> {
            <span style="color:#3f5f5f"><em>//grab the request</em></span>
            ServerHttpRequest request = exchange.getRequest();
            <span style="color:#3f5f5f"><em>//take information from the request to see if it</em></span>
            <span style="color:#3f5f5f"><em>//matches configuration.</em></span>
            <span style="color:#7f0055"><strong>return</strong></span> matches(config, request);
        };
    }

    <span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>static</strong></span> <span style="color:#7f0055"><strong>class</strong></span> Config {
        <span style="color:#3f5f5f"><em>//Put the configuration properties for your filter here</em></span>
    }

}</span></span></span>

124.2编写自定义GatewayFilter工厂

为了编写GatewayFilter,您将需要实现GatewayFilterFactory。您可以扩展名为AbstractGatewayFilterFactory的抽象类。

PreGatewayFilterFactory.java。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> PreGatewayFilterFactory <span style="color:#7f0055"><strong>extends</strong></span> AbstractGatewayFilterFactory<PreGatewayFilterFactory.Config> {

	<span style="color:#7f0055"><strong>public</strong></span> PreGatewayFilterFactory() {
		<span style="color:#7f0055"><strong>super</strong></span>(Config.<span style="color:#7f0055"><strong>class</strong></span>);
	}

	<em><span style="color:gray">@Override</span></em>
	<span style="color:#7f0055"><strong>public</strong></span> GatewayFilter apply(Config config) {
		<span style="color:#3f5f5f"><em>// grab configuration from Config object</em></span>
		<span style="color:#7f0055"><strong>return</strong></span> (exchange, chain) -> {
			<span style="color:#3f5f5f"><em>//If you want to build a "pre" filter you need to manipulate the</em></span>
			<span style="color:#3f5f5f"><em>//request before calling chain.filter</em></span>
			ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
			<span style="color:#3f5f5f"><em>//use builder to manipulate the request</em></span>
			<span style="color:#7f0055"><strong>return</strong></span> chain.filter(exchange.mutate().request(request).build());
		};
	}

	<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>static</strong></span> <span style="color:#7f0055"><strong>class</strong></span> Config {
		<span style="color:#3f5f5f"><em>//Put the configuration properties for your filter here</em></span>
	}

}</span></span></span>

PostGatewayFilterFactory.java。

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> PostGatewayFilterFactory <span style="color:#7f0055"><strong>extends</strong></span> AbstractGatewayFilterFactory<PostGatewayFilterFactory.Config> {

	<span style="color:#7f0055"><strong>public</strong></span> PostGatewayFilterFactory() {
		<span style="color:#7f0055"><strong>super</strong></span>(Config.<span style="color:#7f0055"><strong>class</strong></span>);
	}

	<em><span style="color:gray">@Override</span></em>
	<span style="color:#7f0055"><strong>public</strong></span> GatewayFilter apply(Config config) {
		<span style="color:#3f5f5f"><em>// grab configuration from Config object</em></span>
		<span style="color:#7f0055"><strong>return</strong></span> (exchange, chain) -> {
			<span style="color:#7f0055"><strong>return</strong></span> chain.filter(exchange).then(Mono.fromRunnable(() -> {
				ServerHttpResponse response = exchange.getResponse();
				<span style="color:#3f5f5f"><em>//Manipulate the response in some way</em></span>
			}));
		};
	}

	<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>static</strong></span> <span style="color:#7f0055"><strong>class</strong></span> Config {
		<span style="color:#3f5f5f"><em>//Put the configuration properties for your filter here</em></span>
	}

}</span></span></span>

124.3编写自定义全局过滤器

为了编写自定义全局过滤器,您将需要实现GlobalFilter接口。这会将过滤器应用于所有请求。

如何分别设置全局前置和后置过滤器的示例

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> GlobalFilter customGlobalFilter() {
    <span style="color:#7f0055"><strong>return</strong></span> (exchange, chain) -> exchange.getPrincipal()
        .map(Principal::getName)
        .defaultIfEmpty(<span style="color:#2a00ff">"Default User"</span>)
        .map(userName -> {
          <span style="color:#3f5f5f"><em>//adds header to proxied request</em></span>
          exchange.getRequest().mutate().header(<span style="color:#2a00ff">"CUSTOM-REQUEST-HEADER"</span>, userName).build();
          <span style="color:#7f0055"><strong>return</strong></span> exchange;
        })
        .flatMap(chain::filter);
}

<em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> GlobalFilter customGlobalPostFilter() {
    <span style="color:#7f0055"><strong>return</strong></span> (exchange, chain) -> chain.filter(exchange)
        .then(Mono.just(exchange))
        .map(serverWebExchange -> {
          <span style="color:#3f5f5f"><em>//adds header to response</em></span>
          serverWebExchange.getResponse().getHeaders().set(<span style="color:#2a00ff">"CUSTOM-RESPONSE-HEADER"</span>,
              HttpStatus.OK.equals(serverWebExchange.getResponse().getStatusCode()) ? <span style="color:#2a00ff">"It worked"</span>: <span style="color:#2a00ff">"It did not work"</span>);
          <span style="color:#7f0055"><strong>return</strong></span> serverWebExchange;
        })
        .then();
}</span></span></span>

125.使用Spring MVC或Webflux构建一个简单的网关

|-----------------------------------------------------------------------------------------|--------------------------------|
| |
| | 以下描述了替代样式的网关。先前文档的None适用于以下内容。 |

Spring Cloud Gateway提供了一个名为ProxyExchange的实用程序对象,您可以在常规的Spring web处理程序中将其用作方法参数。它通过镜像HTTP动词的方法支持基本的下游HTTP交换。使用MVC,它还支持通过forward()方法转发到本地处理程序。要使用ProxyExchange,只需在类路径中包含正确的模块(spring-cloud-gateway-mvcspring-cloud-gateway-webflux)。

MVC示例(代理对远程服务器下游" /测试"的请求):

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@RestController</span></em>
<em><span style="color:gray">@SpringBootApplication</span></em>
<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> GatewaySampleApplication {

	<em><span style="color:gray">@Value("${remote.home}")</span></em>
	<span style="color:#7f0055"><strong>private</strong></span> URI home;

	<em><span style="color:gray">@GetMapping("/test")</span></em>
	<span style="color:#7f0055"><strong>public</strong></span> ResponseEntity<?> proxy(ProxyExchange<<span style="color:#7f0055"><strong>byte</strong></span>[]> proxy) <span style="color:#7f0055"><strong>throws</strong></span> Exception {
		<span style="color:#7f0055"><strong>return</strong></span> proxy.uri(home.toString() + <span style="color:#2a00ff">"/image/png"</span>).get();
	}

}</span></span></span>

与Webflux相同:

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@RestController</span></em>
<em><span style="color:gray">@SpringBootApplication</span></em>
<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> GatewaySampleApplication {

	<em><span style="color:gray">@Value("${remote.home}")</span></em>
	<span style="color:#7f0055"><strong>private</strong></span> URI home;

	<em><span style="color:gray">@GetMapping("/test")</span></em>
	<span style="color:#7f0055"><strong>public</strong></span> Mono<ResponseEntity<?>> proxy(ProxyExchange<<span style="color:#7f0055"><strong>byte</strong></span>[]> proxy) <span style="color:#7f0055"><strong>throws</strong></span> Exception {
		<span style="color:#7f0055"><strong>return</strong></span> proxy.uri(home.toString() + <span style="color:#2a00ff">"/image/png"</span>).get();
	}

}</span></span></span>

ProxyExchange上有一些便利的方法可以使处理程序方法发现并增强传入请求的URI路径。例如,您可能希望提取路径的尾随元素以将它们传递到下游:

notranslate 复制代码
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@GetMapping("/proxy/path/**")</span></em>
<span style="color:#7f0055"><strong>public</strong></span> ResponseEntity<?> proxyPath(ProxyExchange<<span style="color:#7f0055"><strong>byte</strong></span>[]> proxy) <span style="color:#7f0055"><strong>throws</strong></span> Exception {
  String path = proxy.path(<span style="color:#2a00ff">"/proxy/path/"</span>);
  <span style="color:#7f0055"><strong>return</strong></span> proxy.uri(home.toString() + <span style="color:#2a00ff">"/foos/"</span> + path).get();
}</span></span></span>

网关处理程序方法可以使用Spring MVC或Webflux的所有功能。因此,例如,您可以注入请求标头和查询参数,并且可以使用映射批注中的声明来约束传入的请求。有关这些功能的更多详细信息,请参见Spring MVC中的@RequestMapping文档。

可以使用ProxyExchange上的header()方法将标头添加到下游响应中。

您还可以通过将映射器添加到get()等方法来操纵响应头(以及响应中您喜欢的任何其他内容)。映射器是Function,它接收传入的ResponseEntity并将其转换为传出的ResponseEntity

为不传递到下游的"敏感"标头(默认情况下为" cookie"和"授权")以及"代理"标头(x-forwarded-*)提供了一流的支持

相关推荐
2401_857439691 小时前
SpringBoot框架在资产管理中的应用
java·spring boot·后端
怀旧6661 小时前
spring boot 项目配置https服务
java·spring boot·后端·学习·个人开发·1024程序员节
阿华的代码王国1 小时前
【SpringMVC】——Cookie和Session机制
java·后端·spring·cookie·session·会话
哎呦没4 小时前
SpringBoot框架下的资产管理自动化
java·spring boot·后端
2401_857600954 小时前
SpringBoot框架的企业资产管理自动化
spring boot·后端·自动化
NiNg_1_2348 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
种树人202408198 小时前
如何在 Spring Boot 中启用定时任务
spring boot
苹果醋311 小时前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx
Wx-bishekaifayuan11 小时前
django电商易购系统-计算机设计毕业源码61059
java·spring boot·spring·spring cloud·django·sqlite·guava
customer0812 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源