Spring Cloud 网关 您所在的位置:网站首页 springcloud网关路由转发 Spring Cloud 网关

Spring Cloud 网关

2024-06-10 04:17| 来源: 网络整理| 查看: 265

# Spring Cloud 网关

3.1.1

该项目提供了一个构建在 Spring 生态系统之上的 API 网关,包括: Spring 5、 Spring Boot2 和 Project Reactor。 Spring Cloud Gateway 旨在提供一种简单但有效的方法来路由到 API,并向它们提供跨领域的关注,例如:安全性、监视/度量和弹性。

# 1. How to Include Spring Cloud Gateway

要在项目中包含 Spring Cloud网关,请使用组 ID 为org.springframework.cloud和工件 ID 为spring-cloud-starter-gateway的 starter。请参阅Spring Cloud Project page (opens new window),以获取有关使用当前 Spring Cloud发布系列设置构建系统的详细信息。

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

Spring Cloud网关是建立在Spring Boot 2.x (opens new window),Spring WebFlux (opens new window),和项目反应堆 (opens new window)之上的。因此,当你使用 Spring Cloud网关时,许多你熟悉的同步库(例如 Spring 数据和 Spring 安全性)和模式可能不适用,如果你不熟悉这些项目,我们建议你在使用 Spring Cloud Gateway 之前,先阅读他们的文档,以熟悉一些新概念。 Spring Cloud网关需要由 Spring 启动和 Spring WebFlux 提供的 Netty 运行时。它在传统 Servlet 容器中或构建为 WAR 时不工作。 # 2.词汇表

路线:网关的基本构建块。它由一个 ID、一个目标 URI、一组谓词和一组筛选器定义。如果聚合谓词为 true,则匹配路由。

谓词:这是Java8 函数谓词 (opens new window)。输入类型是一个[ Spring FrameworkServerWebExchange](https://DOCS. Spring.io/ Spring/DOCS/5.0.x/javadoc-api/org/springframework/web/server/serverwebexchange.html)。这使你能够匹配 HTTP 请求中的任何内容,例如标题或参数。

过滤器:这些是[GatewayFilter](https://github.com/ Spring-cloud/ Spring-cloud-gateway/tree/main/ Spring-cloud-gateway-server-server/SRC/main/main/java/org/springframework/cloud/gateway/filter/geter/getter/gatewayfilter.java)的实例在这里,你可以在发送下游请求之前或之后修改请求和响应。

# 3.它是如何工作的

下图提供了 Spring Cloud网关如何工作的高级概述:

Spring Cloud Gateway Diagram

客户端向 Spring Cloud网关提出请求。如果网关处理程序映射确定请求与路由匹配,则将请求发送到网关 Web 处理程序。此处理程序通过特定于该请求的筛选链来运行该请求。用虚线划分过滤器的原因是,过滤器可以在发送代理请求之前和之后运行逻辑。所有的“pre”过滤逻辑都会被执行。然后提出代理请求。在提出代理请求之后,将运行“POST”过滤逻辑。

在没有端口的路由中定义的 URI 分别获得 HTTP 和 HTTPS URI 的默认端口号 80 和 443. # 4.配置路由谓词工厂和网关过滤器工厂

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

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

# 4.1.快捷方式配置

快捷方式配置由筛选器名称识别,后面跟着一个等号(=),后面是用逗号分隔的参数值(,)。

应用程序.yml

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

上一个示例用两个参数定义了Cookie路由谓词工厂,cookie 名mycookie和要匹配mycookievalue的值。

# 4.2.完全展开的论证

完全展开的参数看起来更像是带有名称/值对的标准 YAML 配置。通常,会有name键和args键。args键是用于配置谓词或筛选器的键值对的映射。

应用程序.yml

spring: cloud: gateway: routes: - id: after_route uri: https://example.org predicates: - name: Cookie args: name: mycookie regexp: mycookievalue

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

# 5.路线谓词工厂

Spring Cloud网关将路由匹配为 Spring WebFluxHandlerMapping基础设施的一部分。 Spring Cloud网关包括许多内置的路由谓词工厂。所有这些谓词在 HTTP 请求的不同属性上匹配。你可以将多个路由谓词工厂与逻辑and语句组合在一起。

# 5.1.后路由谓词工厂

After路由谓词工厂接受一个参数,adatetime(这是一个 JavaZonedDateTime)。此谓词匹配在指定的 DateTime 之后发生的请求。下面的示例配置一个 after 路由谓词:

示例 1.应用程序.yml

spring: cloud: gateway: routes: - id: after_route uri: https://example.org predicates: - After=2017-01-20T17:42:47.789-07:00[America/Denver]

这条路线符合任何请求后提出的 JAN20,2017 年 17:42 山区时间(丹佛)。

# 5.2.前路由谓词工厂

Before路由谓词工厂接受一个参数,adatetime(这是一个 JavaZonedDateTime)。此谓词匹配在指定的datetime之前发生的请求。下面的示例配置一个 before 路由谓词:

示例 2.application.yml

spring: cloud: gateway: routes: - id: before_route uri: https://example.org predicates: - Before=2017-01-20T17:42:47.789-07:00[America/Denver]

这条路线符合任何在 JAN20,2017 年 17:42 山区时间(丹佛)之前提出的请求。

# 5.3.路由谓词之间的工厂

Between路由谓词工厂接受两个参数,datetime1和datetime2,它们是 JavaZonedDateTime对象。此谓词匹配发生在datetime1之后和datetime2之前的请求。datetime2参数必须位于datetime1之后。下面的示例配置了一个 between 路由谓词:

示例 3.application.yml

spring: cloud: gateway: routes: - id: between_route uri: https://example.org predicates: - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

这条路线符合在 JAN20,2017 年 17:42 山区时间(丹佛)之后和 JAN21,2017 年 17:42 山区时间(丹佛)之前提出的任何请求。这对于维护窗口可能是有用的。

# 5.4.cookie 路由谓词工厂

Cookie路由谓词工厂接受两个参数,cookiename和regexp(这是一个 Java 正则表达式)。此谓词匹配具有给定名称且其值与正则表达式匹配的 cookie。下面的示例配置了一个 Cookie 路由谓词工厂:

示例 4.application.yml

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

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

# 5.5.头路由谓词工厂

Header路由谓词工厂接受两个参数,header和regexp(这是一个 Java 正则表达式)。此谓词与具有给定名称的头匹配,其值与正则表达式匹配。下面的示例配置头路由谓词:

示例 5.application.yml

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

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

# 5.6.主机路由谓词工厂

Host路由谓词工厂接受一个参数:主机名列表patterns。该模式是一种 Ant 样式的模式,以.作为分隔符。此谓词匹配与模式匹配的Host头。下面的示例配置了一个主机路由谓词:

示例 6.application.yml

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

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

如果请求具有Host头,其值为www.somehost.org或beta.somehost.org或www.anotherhost.org,则此路由匹配。

这个谓词提取 URI 模板变量(例如sub,在前面的示例中定义)作为名称和值的映射,并将其放在ServerWebExchange.getAttributes()中,并在ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE中定义一个键。然后这些值可供[GatewayFilter工厂使用](#gateway-route-filters)

# 5.7.路由谓词工厂的方法

Method路由谓词工厂接受一个methods参数,该参数是一个或多个参数:要匹配的 HTTP 方法。下面的示例配置了一个方法路由谓词:

示例 7.application.yml

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

如果请求方法是GET或POST,则此路由匹配。

# 5.8.路径谓词工厂

Path路由谓词工厂接受两个参数: Spring PathMatcher``patterns的列表和一个名为matchTrailingSlash的可选标志(默认为true)。下面的示例配置了一个路径路由谓词:

示例 8.application.yml

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

如果请求路径是:例如:/red/1或/red/1/或/red/blue或/blue/green,则此路由匹配。

如果matchTrailingSlash被设置为false,那么请求路径/red/1/将不会被匹配。

这个谓词提取 URI 模板变量(例如segment,在前面的示例中定义)作为名称和值的映射,并将其放在ServerWebExchange.getAttributes()中,并在ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE中定义一个键。然后这些值可供[GatewayFilter工厂]使用(#gateway-route-filters)

可以使用一种实用方法(称为get)来使对这些变量的访问更容易。下面的示例展示了如何使用get方法:

Map uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange); String segment = uriVariables.get("segment"); # 5.9.查询路由谓词工厂

Query路由谓词工厂接受两个参数:一个必需的param和一个可选的regexp(这是一个 Java 正则表达式)。下面的示例配置一个查询路由谓词:

示例 9.application.yml

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

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

application.yml

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

如果请求包含一个red查询参数,其值与gree.regexp 匹配,则前面的路由匹配,因此green和greet将匹配。

# 5.10.RemoteAddr 路由谓词工厂

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

示例 10.application.yml

spring: cloud: gateway: routes: - id: remoteaddr_route uri: https://example.org predicates: - RemoteAddr=192.168.1.1/24

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

# 5.10.1.修改远程地址的解析方式

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

你可以通过设置自定义RemoteAddressResolver来定制远程地址的解析方式。 Spring Cloud网关带有一个基于X-forward-for 标头 (opens new window),XForwardedRemoteAddressResolver的非默认远程地址解析器。

XForwardedRemoteAddressResolver有两种静态构造函数方法,它们采用不同的方法实现安全性:

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

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

考虑以下标头值:

X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3

以下maxTrustedIndex值产生以下远程地址:

maxTrustedIndex 结果 [Integer.MIN_VALUE,0] (无效,IllegalArgumentException在初始化期间) 1 0.0.0.3 2 0.0.0.2 3 0.0.0.1 [4, Integer.MAX_VALUE] 0.0.0.1

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

例 11.gatewayconfig.java

RemoteAddressResolver resolver = XForwardedRemoteAddressResolver .maxTrustedIndex(1); ... .route("direct-route", r -> r.remoteAddr("10.1.1.1", "10.10.1.1/24") .uri("https://downstream1") .route("proxied-route", r -> r.remoteAddr(resolver, "10.10.1.1", "10.10.1.1/24") .uri("https://downstream2") ) # 5.11.权重路径谓词工厂

Weight路由谓词工厂接受两个参数:group和weight(一个 INT)。权重是按组计算的。下面的示例配置了权重路由谓词:

示例 12.application.yml

spring: cloud: gateway: routes: - id: weight_high uri: https://weighthigh.org predicates: - Weight=group1, 8 - id: weight_low uri: https://weightlow.org predicates: - Weight=group1, 2

此路线将把 80% 的流量转发给weighthigh.org (opens new window),并将 20% 的流量转发给weighlow.org (opens new window)。

# 5.12.XForwarded 远程 addr 路由谓词工厂

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

此路由谓词允许基于X-Forwarded-ForHTTP 报头对请求进行过滤。

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

下面的示例配置了一个 XForWardeDremoteaddr 路由谓词:

示例 13.application.yml

spring: cloud: gateway: routes: - id: xforwarded_remoteaddr_route uri: https://example.org predicates: - XForwardedRemoteAddr=192.168.1.1/24

如果X-Forwarded-For标头包含192.168.1.10,则此路由匹配。

# 6.GatewayFilter工厂

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

有关如何使用以下任何过滤器的更详细示例,请查看unit tests (opens new window)。 # 6.1.AddRequestHeader``GatewayFilter工厂

AddRequestHeader``GatewayFilter工厂接受一个name和value参数。以下示例配置AddRequestHeader``GatewayFilter:

示例 14.application.yml

spring: cloud: gateway: routes: - id: add_request_header_route uri: https://example.org filters: - AddRequestHeader=X-Request-red, blue

对于所有匹配的请求,此清单将X-Request-red:blue头添加到下游请求的头。

AddRequestHeader知道用于匹配路径或主机的 URI 变量。URI 变量可以在值中使用,并在运行时展开。下面的示例配置使用变量的AddRequestHeader``GatewayFilter:

示例 15.application.yml

spring: cloud: gateway: routes: - id: add_request_header_route uri: https://example.org predicates: - Path=/red/{segment} filters: - AddRequestHeader=X-Request-Red, Blue-{segment} # 6.2.AddRequestParameter``GatewayFilter工厂

AddRequestParameter``GatewayFilter工厂接受一个name和value参数。以下示例配置AddRequestParameter``GatewayFilter:

示例 16.application.yml

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

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

AddRequestParameter知道用于匹配路径或主机的 URI 变量。URI 变量可以在值中使用,并在运行时展开。下面的示例配置使用变量的AddRequestParameter``GatewayFilter:

示例 17.application.yml

spring: cloud: gateway: routes: - id: add_request_parameter_route uri: https://example.org predicates: - Host: {segment}.myhost.org filters: - AddRequestParameter=foo, bar-{segment} # 6.3.AddResponseHeader``GatewayFilter工厂

AddResponseHeader``GatewayFilter工厂接受一个name和value参数。以下示例配置AddResponseHeader``GatewayFilter:

示例 18.application.yml

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

这将为所有匹配的请求向下游响应的头添加X-Response-Red:Blue头。

AddResponseHeader知道用于匹配路径或主机的 URI 变量。URI 变量可以在值中使用,并在运行时展开。下面的示例配置使用变量的AddResponseHeader``GatewayFilter:

示例 19.application.yml

spring: cloud: gateway: routes: - id: add_response_header_route uri: https://example.org predicates: - Host: {segment}.myhost.org filters: - AddResponseHeader=foo, bar-{segment} # 6.4.DedupeResponseHeader``GatewayFilter工厂

DedupeResponseHeader GatewayFilter 工厂接受一个name参数和一个可选的strategy参数。name可以包含一个以空格分隔的标题名称列表。下面的示例配置DedupeResponseHeader``GatewayFilter:

示例 20.application.yml

spring: cloud: gateway: routes: - id: dedupe_response_header_route uri: https://example.org filters: - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin

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

DedupeResponseHeader过滤器还接受一个可选的strategy参数。可接受的值是RETAIN_FIRST(默认)、RETAIN_LAST和RETAIN_UNIQUE。

# 6.5. Spring Cloud CircuitBreaker GatewayFilter Factory

Spring Cloud断路器网关过滤器工厂使用 Spring Cloud断路器 API 将网关路由封装在断路器中。 Spring Cloud Circuitbreaker 支持可与 Spring Cloud Gateway 一起使用的多个库。 Spring Cloud支持开箱即用的弹性 4J。

要启用 Spring Cloud电路断路器过滤器,你需要在 Classpath 上放置spring-cloud-starter-circuitbreaker-reactor-resilience4j。以下示例配置了 Spring Cloud电路断路器GatewayFilter:

示例 21.application.yml

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

要配置断路器,请参阅你正在使用的底层断路器实现的配置。

复原力 4J 文档 (opens new window)

Spring Cloud电路断路器过滤器还可以接受可选的fallbackUri参数。目前,只支持forward:模式 URI。如果回退被调用,请求将被转发到与 URI 匹配的控制器。下面的示例配置了这种回退:

示例 22.application.yml

spring: cloud: gateway: routes: - id: circuitbreaker_route uri: lb://backing-service:8088 predicates: - Path=/consumingServiceEndpoint filters: - name: CircuitBreaker args: name: myCircuitBreaker fallbackUri: forward:/inCaseOfFailureUseThis - RewritePath=/consumingServiceEndpoint, /backingServiceEndpoint

下面的列表在 Java 中做了相同的事情:

例 23.应用程序.java

@Bean public RouteLocator routes(RouteLocatorBuilder builder) { return builder.routes() .route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint") .filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis")) .rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088") .build(); }

当调用断路器回退时,此示例转发到/inCaseofFailureUseThisURI。请注意,此示例还演示了(可选的) Spring Cloud负载平衡器负载平衡(由目标 URI 上的lb前缀定义)。

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

示例 24.application.yml

spring: cloud: gateway: routes: - id: ingredients uri: lb://ingredients predicates: - Path=//ingredients/** filters: - name: CircuitBreaker args: name: fetchIngredients fallbackUri: forward:/fallback - id: ingredients-fallback uri: http://localhost:9994 predicates: - Path=/fallback

在此示例中,网关应用程序中没有fallback端点或处理程序。然而,在另一个应用程序中有一个,注册在[localhost:9994](http://localhost:9994)下。

在请求被转发到 Fallback 的情况下, Spring Cloud Circuitbreaker 网关过滤器还提供了导致它的Throwable。它被添加到ServerWebExchange中,作为ServerWebExchangeUtils.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR属性,该属性可以在处理网关应用程序内的回退时使用。

对于外部控制器/处理程序场景,可以添加带有异常详细信息的头。你可以在FallbackHeaders GatewayFilter 工厂部分中找到有关这样做的更多信息。

# 6.5.1.按状态码切断断路器

在某些情况下,你可能希望基于从其封装的路由返回的状态码来跳闸断路器。断路器配置对象获取一系列状态代码,如果返回这些代码,将导致断路器跳闸。在设置要跳闸的状态码时,可以使用带有状态码值的整数,也可以使用HttpStatus枚举的字符串表示。

示例 25.application.yml

spring: cloud: gateway: routes: - id: circuitbreaker_route uri: lb://backing-service:8088 predicates: - Path=/consumingServiceEndpoint filters: - name: CircuitBreaker args: name: myCircuitBreaker fallbackUri: forward:/inCaseOfFailureUseThis statusCodes: - 500 - "NOT_FOUND"

例 26.应用程序.java

@Bean public RouteLocator routes(RouteLocatorBuilder builder) { return builder.routes() .route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint") .filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis").addStatusCode("INTERNAL_SERVER_ERROR")) .rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088") .build(); } # 6.6.FallbackHeaders``GatewayFilter工厂

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

示例 27.application.yml

spring: cloud: gateway: routes: - id: ingredients uri: lb://ingredients predicates: - Path=//ingredients/** filters: - name: CircuitBreaker args: name: fetchIngredients fallbackUri: forward:/fallback - id: ingredients-fallback uri: http://localhost:9994 predicates: - Path=/fallback filters: - name: FallbackHeaders args: executionExceptionTypeHeaderName: Test-Header

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

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

executionExceptionTypeHeaderName("Execution-Exception-Type")

executionExceptionMessageHeaderName("Execution-Exception-Message")

rootCauseExceptionTypeHeaderName("Root-Cause-Exception-Type")

rootCauseExceptionMessageHeaderName("Root-Cause-Exception-Message")

有关断路器和网关的更多信息,请参见Spring Cloud CircuitBreaker Factory section。

# 6.7.MapRequestHeader``GatewayFilter工厂

MapRequestHeader``GatewayFilter工厂接受fromHeader和toHeader参数。它创建一个新的命名头(toHeader),并从传入的 HTTP 请求中从现有的命名头(fromHeader)中提取该值。如果输入标头不存在,则过滤器不会产生任何影响。如果新的命名标头已经存在,那么它的值将被新的值扩充。以下示例配置MapRequestHeader:

示例 28.application.yml

spring: cloud: gateway: routes: - id: map_request_header_route uri: https://example.org filters: - MapRequestHeader=Blue, X-Request-Red

这会将X-Request-Red:头添加到下游请求,并从传入的 HTTP 请求的Blue头更新其值。

# 6.8.PrefixPath``GatewayFilter工厂

PrefixPath``GatewayFilter工厂接受一个prefix参数。以下示例配置PrefixPath``GatewayFilter:

示例 29.application.yml

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

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

# 6.9.PreserveHostHeader``GatewayFilter工厂

PreserveHostHeader``GatewayFilter工厂没有参数。此筛选器设置一个请求属性,路由筛选器将检查该属性以确定是否应发送原始的主机头,而不是由 HTTP 客户机确定的主机头。以下示例配置PreserveHostHeader``GatewayFilter:

示例 30.application.yml

spring: cloud: gateway: routes: - id: preserve_host_route uri: https://example.org filters: - PreserveHostHeader # 6.10.RequestRateLimiter``GatewayFilter工厂

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

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

keyResolver是实现KeyResolver接口的 Bean。在配置中,使用 spel 通过名称引用 Bean。#{@myKeyResolver}是一个 spel 表达式,它引用名为myKeyResolver的 Bean。下面的清单显示了KeyResolver接口:

例 31.keyresolver.java

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

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

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

默认情况下,如果KeyResolver没有找到密钥,请求将被拒绝。你可以通过设置spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key(true或false)和spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code属性来调整此行为。

RequestRateLimiter不能使用“shortcut”符号进行配置。下面的示例是无效:

示例 32.application.properties

# INVALID SHORTCUT CONFIGURATIONspring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}

# 6.1 0.1.RedisRateLimiter

Redis 实现基于在Stripe (opens new window)上完成的工作。它需要使用spring-boot-starter-data-redis-reactive Spring 引导启动器。

使用的算法是令牌桶算法 (opens new window)。

redis-rate-limiter.replenishRate属性是你希望用户在不删除任何请求的情况下每秒可以执行多少个请求。这是令牌桶被填满的速率。

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

redis-rate-limiter.requestedTokens属性是一个请求需要多少令牌。这是每个请求从 bucket 中获取的令牌的数量,默认为1。

通过在replenishRate和burstCapacity中设置相同的值,可以实现稳定的速率。可以通过将burstCapacity设置为高于replenishRate来允许临时突发。在这种情况下,速率限制器需要在两次突发之间允许一段时间(根据replenishRate),因为连续两次突发将导致丢弃请求(HTTP 429 - Too Many Requests)。下面的列表配置了redis-rate-limiter:

速率限制1 request/s通过将replenishRate设置为所需的请求数,requestedTokens设置为秒内的时间跨度,burstCapacity设置为replenishRate和requestedTokens的乘积,例如,设置replenishRate=1,requestedTokens=60和burstCapacity=60将导致1 request/min的限制。

示例 33.application.yml

spring: cloud: gateway: routes: - id: requestratelimiter_route uri: https://example.org filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 10 redis-rate-limiter.burstCapacity: 20 redis-rate-limiter.requestedTokens: 1

下面的示例在 Java 中配置一个 keyresolver:

例 34.config.java

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

这定义了每个用户 10 个的请求速率限制。允许突发 20 个请求,但在接下来的一秒钟内,只有 10 个请求可用。KeyResolver是一个获得user请求参数的简单参数(请注意,这不推荐用于生产)。

还可以将速率限制器定义为实现RateLimiter接口的 Bean。在配置中,可以使用 spel 按名称引用 Bean。#{@myRateLimiter}是一个 spel 表达式,它引用名为myRateLimiter的 Bean。下面的清单定义了一个速率限制器,该限制器使用上一个清单中定义的KeyResolver:

示例 35.application.yml

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

RedirectTo``GatewayFilter工厂接受两个参数,status和url。status参数应该是 300 系列重定向 HTTP 代码,例如 301.url参数应该是一个有效的 URL。这是Location标头的值。对于相对重定向,应该使用uri: no://op作为路由定义的 URI。下面的列表配置了RedirectTo``GatewayFilter:

示例 36.application.yml

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

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

# 6.12.TheRemoveRequestHeaderGatewayFilter Factory

RemoveRequestHeader``GatewayFilter工厂接受一个name参数。它是要删除的标头的名称。下面的列表配置了RemoveRequestHeader``GatewayFilter:

示例 37.application.yml

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

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

# 6.13.RemoveResponseHeader``GatewayFilter工厂

RemoveResponseHeader``GatewayFilter工厂接受一个name参数。它是要删除的标头的名称。下面的列表配置了RemoveResponseHeader``GatewayFilter:

示例 38.application.yml

spring: cloud: gateway: routes: - id: removeresponseheader_route uri: https://example.org filters: - RemoveResponseHeader=X-Response-Foo

这将在响应返回到网关客户机之前从响应中删除X-Response-Foo头。

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

# 6.14.RemoveRequestParameter``GatewayFilter工厂

RemoveRequestParameter``GatewayFilter工厂接受一个name参数。它是要删除的查询参数的名称。下面的示例配置RemoveRequestParameter``GatewayFilter:

示例 39.application.yml

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

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

# 6.15.RewritePath``GatewayFilter工厂

RewritePath``GatewayFilter工厂接受一个路径regexp参数和一个replacement参数。这使用 Java 正则表达式以灵活的方式重写请求路径。下面的列表配置了RewritePath``GatewayFilter:

示例 40.application.yml

spring: cloud: gateway: routes: - id: rewritepath_route uri: https://example.org predicates: - Path=/red/** filters: - RewritePath=/red/?(?.*), /$\{segment}

对于/red/blue的请求路径,在发出下游请求之前,将路径设置为/blue。注意,由于 YAML 规范,$应该替换为$\。

# 6.16.RewriteLocationResponseHeader``GatewayFilter工厂

RewriteLocationResponseHeader``GatewayFilter工厂修改Location响应头的值,通常是为了去掉后台特定的细节。它需要stripVersionMode、locationHeaderName、hostValue和protocolsRegex参数。下面的列表配置了RewriteLocationResponseHeader``GatewayFilter:

示例 41.application.yml

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

例如,对于POST [api.example.com/some/object/name](https://api.example.com/some/object/name)的请求,Location的响应头值[object-service.prod.example.net/v2/some/object/id](https://object-service.prod.example.net/v2/some/object/id)被重写为[api.example.com/some/object/id](https://api.example.com/some/object/id)。

stripVersionMode参数具有以下可能的值:NEVER_STRIP、AS_IN_REQUEST(默认)和ALWAYS_STRIP。

NEVER_STRIP:即使原始请求路径不包含版本,也不会剥离版本。

AS_IN_REQUEST只有当原始请求路径不包含版本时,才会剥离版本。

ALWAYS_STRIP即使原始请求路径包含版本,版本也总是被剥离。

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

参数protocolsRegex必须是一个有效的 regexString,协议名称与该 regex 匹配。如果不匹配,过滤器就不会做任何事情。默认值为http|https|ftp|ftps。

# 6.17.RewriteResponseHeader``GatewayFilter工厂

RewriteResponseHeader``GatewayFilter工厂接受name、regexp和replacement参数。它使用 Java 正则表达式以一种灵活的方式重写响应头值。以下示例配置RewriteResponseHeader``GatewayFilter:

示例 42.application.yml

spring: cloud: gateway: routes: - id: rewriteresponseheader_route uri: https://example.org filters: - RewriteResponseHeader=X-Response-Red, , password=[^&]+, password=***

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

# 6.18.SaveSession``GatewayFilter工厂

SaveSession``GatewayFilter工厂强制执行WebSession::save操作在此之前向下游转发呼叫。这在使用带有惰性数据存储的Spring Session (opens new window)之类的东西时特别有用,并且需要确保在进行转发调用之前保存了会话状态。以下示例配置SaveSession``GatewayFilter:

示例 43.application.yml

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

如果将Spring Security (opens new window)与 Spring 会话集成,并希望确保已将安全细节转发到远程进程,这是至关重要的。

# 6.19.SecureHeaders``GatewayFilter工厂

SecureHeaders``GatewayFilter工厂根据这篇博文 (opens new window)中提出的建议,向响应添加了许多标题。

添加了以下标题(以其默认值显示):

X-Xss-Protection:1 (mode=block)

Strict-Transport-Security (max-age=631138519)

X-Frame-Options (DENY)

X-Content-Type-Options (nosniff)

Referrer-Policy (no-referrer)

Content-Security-Policy (default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline)'

X-Download-Options (noopen)

X-Permitted-Cross-Domain-Policies (none)

要更改默认值,请在spring.cloud.gateway.filter.secure-headers名称空间中设置适当的属性。以下属性可供选择:

xss-protection-header

strict-transport-security

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属性。下面的示例展示了如何做到这一点:

spring.cloud.gateway.filter.secure-headers.disable=x-frame-options,strict-transport-security 需要使用安全报头的小写字母全名来禁用它。 # 6.20.SetPath``GatewayFilter工厂

SetPath``GatewayFilter工厂接受一个路径template参数。它提供了一种简单的方法,通过允许模板化的路径段来操作请求路径。这使用了 Spring Framework 中的 URI 模板。允许多个匹配段。下面的示例配置SetPath``GatewayFilter:

示例 44.application.yml

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

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

# 6.21.SetRequestHeader``GatewayFilter工厂

SetRequestHeader``GatewayFilter工厂接受name和value参数。下面的列表配置了SetRequestHeader``GatewayFilter:

示例 45.application.yml

spring: cloud: gateway: routes: - id: setrequestheader_route uri: https://example.org filters: - SetRequestHeader=X-Request-Red, Blue

这个GatewayFilter用给定的名称替换(而不是添加)所有的标题。因此,如果下游服务器用X-Request-Red:1234响应,这将被替换为X-Request-Red:Blue,这是下游服务将接收的内容。

SetRequestHeader知道用于匹配路径或主机的 URI 变量。可以在值中使用 URI 变量,并在运行时对其进行扩展。下面的示例配置了使用变量的SetRequestHeader``GatewayFilter:

示例 46.application.yml

spring: cloud: gateway: routes: - id: setrequestheader_route uri: https://example.org predicates: - Host: {segment}.myhost.org filters: - SetRequestHeader=foo, bar-{segment} # 6.22.SetResponseHeader``GatewayFilter工厂

SetResponseHeader``GatewayFilter工厂接受name和value参数。下面的列表配置了SetResponseHeader``GatewayFilter:

示例 47.application.yml

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

这个 GatewayFilter 用给定的名称替换(而不是添加)所有的头。因此,如果下游服务器使用X-Response-Red:1234进行响应,则将其替换为X-Response-Red:Blue,这是网关客户机将接收的内容。

SetResponseHeader知道用于匹配路径或主机的 URI 变量。URI 变量可以在值中使用,并将在运行时展开。下面的示例配置使用变量的SetResponseHeader``GatewayFilter:

示例 48.application.yml

spring: cloud: gateway: routes: - id: setresponseheader_route uri: https://example.org predicates: - Host: {segment}.myhost.org filters: - SetResponseHeader=foo, bar-{segment} # 6.23.SetStatus``GatewayFilter工厂

SetStatus``GatewayFilter工厂只接受一个参数,status。它必须是有效的 Spring HttpStatus。它可以是整数值404,也可以是枚举的字符串表示:NOT_FOUND。下面的列表配置了SetStatus``GatewayFilter:

示例 49.application.yml

spring: cloud: gateway: routes: - id: setstatusstring_route uri: https://example.org filters: - SetStatus=UNAUTHORIZED - id: setstatusint_route uri: https://example.org filters: - SetStatus=401

在这两种情况下,响应的 HTTP 状态都设置为 401.

你可以将SetStatus``GatewayFilter配置为从响应中的报头中的代理请求返回原始 HTTP 状态代码。如果配置了以下属性,则会将头添加到响应中:

示例 50.application.yml

spring: cloud: gateway: set-status: original-status-header-name: original-http-status # 6.24.StripPrefix``GatewayFilter工厂

StripPrefix``GatewayFilter工厂接受一个参数,parts。parts参数指示在向下游发送请求之前要从请求中剥离的路径中的部件数量。下面的列表配置了StripPrefix``GatewayFilter:

示例 51.application.yml

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

当通过网关向/name/blue/red发出请求时,向nameservice发出的请求看起来像[nameservice/red](https://nameservice/red)。

# 6.25.重试GatewayFilter工厂

Retry``GatewayFilter工厂支持以下参数:

retries:应该尝试的重试次数。

statuses:应该重试的 HTTP 状态代码,用org.springframework.http.HttpStatus表示。

methods:应该重试的 HTTP 方法,用org.springframework.http.HttpMethod表示。

series:要重试的一系列状态代码,用org.springframework.http.HttpStatus.Series表示。

exceptions:应该重试的抛出的异常列表。

backoff:为重试配置的指数退避。在回退间隔firstBackoff * (factor ^ n)之后执行重试,其中n是迭代。如果配置了maxBackoff,则应用的最大退避限制为maxBackoff。如果basedOnPreviousValue为真,则按prevBackoff * factor计算退避。

如果启用,以下默认值将配置为Retry过滤器:

retries:三次

series:5XX 系列

methods:get 方法

exceptions:IOException和TimeoutException

backoff:禁用

下面的清单配置了重试GatewayFilter:

示例 52.application.yml

spring: cloud: gateway: routes: - id: retry_test uri: http://localhost:8080/flakey predicates: - Host=*.retry.com filters: - name: Retry args: retries: 3 statuses: BAD_GATEWAY methods: GET,POST backoff: firstBackoff: 10ms maxBackoff: 50ms factor: 2 basedOnPreviousValue: false 当使用带有forward:前缀 URL 的重试筛选器时,目标端点应该仔细地编写,以便在发生错误的情况下,它不会执行任何可能导致将响应发送到客户机并提交的操作,例如,,如果目标端点是带注释的控制器,则目标控制器方法不应返回带有错误状态码的ResponseEntity,而是应该抛出或发出错误信号(例如,通过Mono.error(ex)返回值),重试筛选器可以配置为通过重试来处理该筛选器。 当在带有主体的任何 HTTP 方法中使用 Retry 过滤器时,主体将被缓存,网关将成为内存约束。主体缓存在由ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR定义的请求属性中。对象的类型是org.springframework.core.io.buffer.DataBuffer。

一个简化的“shortcut”符号可以添加一个status和method。

以下两个例子是等价的:

示例 53.application.yml

spring: cloud: gateway: routes: - id: retry_route uri: https://example.org filters: - name: Retry args: retries: 3 statuses: INTERNAL_SERVER_ERROR methods: GET backoff: firstBackoff: 10ms maxBackoff: 50ms factor: 2 basedOnPreviousValue: false - id: retryshortcut_route uri: https://example.org filters: - Retry=3,INTERNAL_SERVER_ERROR,GET,10ms,50ms,2,false # 6.26.RequestSize``GatewayFilter工厂

当请求大小大于允许的限制时,RequestSize工厂可以限制请求到达下游服务。过滤器接受maxSize参数。maxSize是DataSize类型,因此值可以定义为一个数字,后面跟着一个可选的DataUnit后缀,例如“KB”或“MB”。对于字节,默认值为“B”。它是以字节为单位定义的请求的允许大小限制。下面的列表配置了RequestSize``GatewayFilter:

示例 54.application.yml

spring: cloud: gateway: routes: - id: request_size_route uri: http://localhost:8080/upload predicates: - Path=/upload filters: - name: RequestSize args: maxSize: 5000000

当请求由于大小而被拒绝时,RequestSize工厂将响应状态设置为413 Payload Too Large,并带有一个附加的头errorMessage。下面的示例显示了这样的errorMessage:

errorMessage : Request size is larger than permissible limit. Request size is 6.0 MB where permissible limit is 5.0 MB 如果在路由定义中没有作为筛选参数提供,则默认的请求大小设置为 5MB。 # 6.27.SetRequestHostHeader``GatewayFilter工厂

在某些情况下,主机标题可能需要被重写。在这种情况下,SetRequestHostHeader``GatewayFilter工厂可以用指定的 vaue 替换现有的主机报头。过滤器接受host参数。下面的列表配置了SetRequestHostHeader``GatewayFilter:

示例 55.application.yml

spring: cloud: gateway: routes: - id: set_request_host_header_route uri: http://localhost:8080/headers predicates: - Path=/headers filters: - name: SetRequestHostHeader args: host: example.org

SetRequestHostHeader``GatewayFilter工厂将主机报头的值替换为example.org。

# 6.28.修改请求主体GatewayFilter工厂

你可以使用ModifyRequestBody过滤器过滤器来修改请求主体,然后再由网关向下游发送。

这个过滤器只能通过使用 Java DSL 进行配置。

下面的清单显示了如何修改请求主体GatewayFilter:

@Bean public RouteLocator routes(RouteLocatorBuilder builder) { return builder.routes() .route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org") .filters(f -> f.prefixPath("/httpbin") .modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE, (exchange, s) -> return Mono.just(new Hello(s.toUpperCase())))).uri(uri)) .build(); } static class Hello { String message; public Hello() { } public Hello(String message) { this.message = message; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } 如果请求没有正文,RewriteFilter将被传递null。应该返回Mono.empty()以分配请求中缺少的主体。 # 6.29.修改响应主体GatewayFilter工厂

你可以使用ModifyResponseBody过滤器来修改响应主体,然后再将其发送回客户机。

这个过滤器只能通过使用 Java DSL 进行配置。

下面的清单显示了如何修改响应主体GatewayFilter:

@Bean public RouteLocator routes(RouteLocatorBuilder builder) { return builder.routes() .route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org") .filters(f -> f.prefixPath("/httpbin") .modifyResponseBody(String.class, String.class, (exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri)) .build(); } 如果响应没有主体,则将传递RewriteFilter。应该返回Mono.empty(),以便在响应中分配一个缺少的主体。 # 6.30.令牌中继GatewayFilter工厂

令牌中继是 OAuth2 使用者充当客户端并将传入的令牌转发给传出的资源请求的一种方式。使用者可以是纯客户机(如 SSO 应用程序)或资源服务器。

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

app.java

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

或者这个

应用程序.YAML

spring: cloud: gateway: routes: - id: resource uri: http://localhost:9000 predicates: - Path=/resource filters: - TokenRelay=

并且它将(除了登录用户并获取令牌之外)向下游传递身份验证令牌到服务(在这种情况下/resource)。

要为 Spring Cloud网关启用此功能,请添加以下依赖项

org.springframework.boot:spring-boot-starter-oauth2-client

它是如何工作的?{githubmaster}/SRC/main/java/org/springframework/cloud/gateway/security/tokenrelaygatewayfilterfactory.java[filter]从当前经过身份验证的用户中提取一个访问令牌,并将其放在下游请求的请求头中。

有关完整的工作示例,请参见这个项目 (opens new window)。

只有设置了适当的spring.security.oauth2.client.*属性才会创建TokenRelayGatewayFilterFactory Bean,这将触发创建ReactiveClientRegistrationRepository Bean。 TokenRelayGatewayFilterFactory使用的ReactiveOAuth2AuthorizedClientService的默认实现使用内存中的数据存储。如果需要更健壮的解决方案,则需要提供自己的实现ReactiveOAuth2AuthorizedClientService。 # 6.31.CacheRequestBody``GatewayFilter工厂

由于请求体流只能被读取一次,所以需要对请求体流进行缓存。你可以使用CacheRequestBody过滤器来缓存请求主体,然后再将其发送到下游,并从 exchagne 属性获取主体。

下面的清单显示了如何缓存请求主体GatewayFilter:

@Bean public RouteLocator routes(RouteLocatorBuilder builder) { return builder.routes() .route("cache_request_body_route", r -> r.path("/downstream/**") .filters(f -> f.prefixPath("/httpbin") .cacheRequestBody(String.class).uri(uri)) .build(); }

示例 56.application.yml

spring: cloud: gateway: routes: - id: cache_request_body_route uri: lb://downstream predicates: - Path=/downstream/** filters: - name: CacheRequestBody args: bodyClass: java.lang.String

CacheRequestBody将提取请求主体并将其转换为主体类(如java.lang.String,在前面的示例中定义)。然后将其放置在ServerWebExchange.getAttributes()中,并在ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR中定义一个键。

此过滤器仅适用于 HTTP 请求(包括 HTTPS)。 # 6.32.默认过滤器

要添加筛选器并将其应用到所有路由,你可以使用spring.cloud.gateway.default-filters。此属性接受一个过滤器列表。以下清单定义了一组默认筛选器:

示例 57.application.yml

spring: cloud: gateway: default-filters: - AddResponseHeader=X-Response-Default-Red, Default-Blue - PrefixPath=/httpbin # 7.全局过滤器

GlobalFilter接口具有与GatewayFilter相同的签名。这些是有条件地应用于所有路由的特殊过滤器。

该接口及其使用情况可能会在未来的里程碑版本中发生更改。 # 7.1.组合全局过滤器和GatewayFilter排序

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

Spring 由于云网关对于过滤器逻辑执行区分了“pre”和“post”阶段(参见它是如何工作的),优先级最高的过滤器是“pre”阶段的第一个,“post”阶段的最后一个。

下面的清单配置了一个过滤器链:

例 58.示例 configuration.java

@Bean public GlobalFilter customFilter() { return new CustomGlobalFilter(); } public class CustomGlobalFilter implements GlobalFilter, Ordered { @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info("custom global filter"); return chain.filter(exchange); } @Override public int getOrder() { return -1; } } # 7.2.前向路由滤波器

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

# 7.3.ReactiveLoadBalancerClientFilter

ReactiveLoadBalancerClientFilter在名为ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的 exchange 属性中查找 URI。如果 URL 具有lb方案(例如lb://myservice),则它使用 Spring CloudReactorLoadBalancer将名称(在本例中为myservice)解析为实际的主机和端口,并替换相同属性中的 URI。未修改的原始 URL 被追加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。过滤器还查看ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR属性,以查看它是否等于lb。如果是这样,也适用同样的规则。下面的清单配置了ReactiveLoadBalancerClientFilter:

示例 59.application.yml

spring: cloud: gateway: routes: - id: myRoute uri: lb://service predicates: - Path=/service/** 默认情况下,当ReactorLoadBalancer无法找到服务实例时,将返回一个503。通过设置spring.cloud.gateway.loadbalancer.use404=true,你可以将网关配置为返回一个404。 从ReactiveLoadBalancerClientFilter返回的isSecure值的ServiceInstance覆盖了向网关提出的请求中指定的方案。例如,如果请求通过HTTPS进入网关,但ServiceInstance表明它是不安全的,下游请求是在HTTP上提出的。相反的情况也可以适用。但是,如果GATEWAY_SCHEME_PREFIX_ATTR是在网关配置中为该路由指定的,则前缀被剥离,并且从路由 URL 中得到的方案覆盖了ServiceInstance配置。 网关支持所有的负载平衡器功能。你可以在Spring Cloud Commons documentation (opens new window)中阅读有关它们的更多信息。 # 7.4.Netty 路由过滤器

如果ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTRExchange 属性中的 URL 具有http或https方案,则运行 Netty 路由过滤器。它使用 nettyHttpClient发出下游代理请求。将响应放入ServerWebExchangeUtils.CLIENT_RESPONSE_ATTRexchange 属性中,以便在以后的筛选器中使用。(还有一个实验性的WebClientHttpRoutingFilter,它执行相同的功能,但不需要 netty。

# 7.5.Netty 写响应过滤器

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

# 7.6.RouteToRequestUrl过滤器

如果在ServerWebExchangeUtils.GATEWAY_ROUTE_ATTRexchange 属性中有一个Route对象,则运行RouteToRequestUrlFilter。它根据请求 URI 创建一个新的 URI,但使用Route对象的 URI 属性进行更新。新的 URI 放在ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTRexchange 属性中。

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

# 7.7. The Websocket Routing Filter

如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTRExchange 属性中的 URL 具有ws或wss方案,则运行 WebSocket 路由过滤器。它使用 Spring WebSocket 基础设施向下游转发 WebSocket 请求。

你可以通过在 URI 前加上lb来实现 WebSockets 的负载平衡,比如lb:ws://serviceid。

如果使用SockJS (opens new window)作为普通 HTTP 的后备,则应该配置普通 HTTP 路由和 WebSocket 路由。

下面的清单配置了一个 WebSocket 路由过滤器:

示例 60.application.yml

spring: cloud: gateway: routes: # SockJS route - id: websocket_sockjs_route uri: http://localhost:3001 predicates: - Path=/websocket/info/** # Normal Websocket route - id: websocket_route uri: ws://localhost:3001 predicates: - Path=/websocket/** # 7.8.网关指标过滤器

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

routeId:路径 ID。

routeUri:将 API 路由到的 URI。

outcome:结果,按HttpStatus.series (opens new window)分类。

status:返回给客户机的请求的 HTTP 状态。

httpStatusCode:返回给客户机的请求的 HTTP 状态。

httpMethod:用于请求的 HTTP 方法。

此外,通过属性spring.cloud.gateway.metrics.tags.path.enabled(默认情况下,设置为 false),你可以使用标记激活一个额外的度量指标:

path:请求的路径。

然后可以从/actuator/metrics/spring.cloud.gateway.requests中获取这些指标,并且可以轻松地与 Prometheus 集成以创建Grafana (opens new window)dashboard。

要启用 Prometheus 端点,请添加micrometer-registry-prometheus作为项目依赖项。 # 7.9.将交易所标记为路由

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

ServerWebExchangeUtils.isAlreadyRouted接受一个ServerWebExchange对象,并检查它是否已被“路由”。

ServerWebExchangeUtils.setAlreadyRouted接受一个ServerWebExchange对象,并将其标记为“路由”。

# 8.HttpHeadersFilters

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

# 8.1.转发头过滤器

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

# 8.2.RemoveHopbyHop Headers 过滤器

RemoveHopByHopheaders 过滤器从转发的请求中删除 header。被删除的头的默认列表来自IETF (opens new window)。

默认删除的标题是:

连接

保持活力

代理身份验证

代理授权

TE

预告片

传输编码

升级

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

# 8.3.XForwarded Headers 过滤器

XForwardedheaders filter 创建了各种X-Forwarded-*headers 以发送到下游服务。它使用Host报头、方案、端口和当前请求的路径来创建各种报头。

可以通过以下布尔属性(默认为 true)来控制单个标题的创建:

spring.cloud.gateway.x-forwarded.for-enabled

spring.cloud.gateway.x-forwarded.host-enabled

spring.cloud.gateway.x-forwarded.port-enabled

spring.cloud.gateway.x-forwarded.proto-enabled

spring.cloud.gateway.x-forwarded.prefix-enabled

追加多个头可以由以下布尔属性控制(默认为 true):

spring.cloud.gateway.x-forwarded.for-append

spring.cloud.gateway.x-forwarded.host-append

spring.cloud.gateway.x-forwarded.port-append

spring.cloud.gateway.x-forwarded.proto-append

spring.cloud.gateway.x-forwarded.prefix-append

# 9.TLS 和 SSL

网关可以通过遵循通常的 Spring 服务器配置来监听 HTTPS 上的请求。下面的示例展示了如何做到这一点:

示例 61.application.yml

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

你可以将网关路由到 HTTP 和 HTTPS 后端。如果要路由到 HTTPS 后端,则可以通过以下配置将网关配置为信任所有下游证书:

示例 62.application.yml

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

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

示例 63.application.yml

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

如果 Spring Cloud网关没有提供受信任的证书,则使用默认的信任存储区(你可以通过设置javax.net.ssl.trustStore系统属性来覆盖该存储区)。

# 9.1.TLS 握手

网关维护一个用于路由到后端的客户机池。当通过 HTTPS 进行通信时,客户机发起 TLS 握手。与此握手相关的超时次数很多。你可以配置这些超时可以配置(默认显示)如下:

示例 64.application.yml

spring: cloud: gateway: httpclient: ssl: handshake-timeout-millis: 10000 close-notify-flush-timeout-millis: 3000 close-notify-read-timeout-millis: 0 # 10.配置(#configuration)

Spring Cloud网关的配置由RouteDefinitionLocator实例的集合驱动。下面的清单显示了RouteDefinitionLocator接口的定义:

例 65.RouteDefinitionLocator.java

public interface RouteDefinitionLocator { Flux getRouteDefinitions(); }

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

较早的配置示例都使用快捷方式表示,它使用位置参数而不是命名参数。以下两个例子是等价的:

示例 66.application.yml

spring: cloud: gateway: routes: - id: setstatus_route uri: https://example.org filters: - name: SetStatus args: status: 401 - id: setstatusshortcut_route uri: https://example.org filters: - SetStatus=401

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

# 10.1.路由定义度量(#routedefinition-metrics)

要启用RouteDefinition指标,请添加 Spring-boot-starter-actuator 作为项目依赖项。然后,默认情况下,只要将属性spring.cloud.gateway.metrics.enabled设置为true,这些指标就可用。将添加一个名为spring.cloud.gateway.routes.count的规范度量,其值是RouteDefinitions的数量。该指标将从/actuator/metrics/spring.cloud.gateway.routes.count开始提供。

# 11.路由元数据配置(#route-metadata-configuration)

你可以通过使用元数据为每个路由配置附加参数,如下所示:

示例 67.application.yml

spring: cloud: gateway: routes: - id: route_with_metadata uri: https://example.org metadata: optionName: "OptionValue" compositeObject: name: "value" iAmNumber: 1

你可以从 Exchange 获取所有元数据属性,如下所示:

Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR); // get all metadata properties route.getMetadata(); // get a single metadata property route.getMetadata(someKey); # 12.HTTP 超时配置(#http-timeouts-configuration)

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

# 12.1.全球超时(#global-timeouts)

要配置全局 HTTP 超时:connect-timeout必须以毫秒为单位指定。response-timeout必须指定为 java.time.duration

全局 HTTP 超时示例

spring: cloud: gateway: httpclient: connect-timeout: 1000 response-timeout: 5s # 12.2.每条路线超时(#per-route-timeouts)

要配置每路由超时:connect-timeout必须以毫秒为单位指定。response-timeout必须以毫秒为单位指定。

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

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

使用 Java DSL 的每路由超时配置

import static org.springframework.cloud.gateway.support.RouteMetadataUtils.CONNECT_TIMEOUT_ATTR; import static org.springframework.cloud.gateway.support.RouteMetadataUtils.RESPONSE_TIMEOUT_ATTR; @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder routeBuilder){ return routeBuilder.routes() .route("test1", r -> { return r.host("*.somehost.org").and().path("/somepath") .filters(f -> f.addRequestHeader("header1", "header-value-1")) .uri("http://someuri") .metadata(RESPONSE_TIMEOUT_ATTR, 200) .metadata(CONNECT_TIMEOUT_ATTR, 200); }) .build(); }

带负值的每路由response-timeout将禁用全局response-timeout值。

- id: per_route_timeouts uri: https://example.org predicates: - name: Path args: pattern: /delay/{timeout} metadata: response-timeout: -1 # 12.3.Fluent Java Routes API(#fluent-java-routes-api)

为了允许在 Java 中进行简单的配置,RouteLocatorBuilder Bean 包含了一个 Fluent API。下面的清单展示了它的工作原理:

例 68.GatewaySampleApplication.java

// static imports from GatewayFilters and RoutePredicates @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder, ThrottleGatewayFilterFactory throttle) { return builder.routes() .route(r -> r.host("**.abc.org").and().path("/image/png") .filters(f -> f.addResponseHeader("X-TestHeader", "foobar")) .uri("http://httpbin.org:80") ) .route(r -> r.path("/image/webp") .filters(f -> f.addResponseHeader("X-AnotherHeader", "baz")) .uri("http://httpbin.org:80") .metadata("key", "value") ) .route(r -> r.order(-1) .host("**.throttle.org").and().path("/get") .filters(f -> f.filter(throttle.apply(1, 1, 10, TimeUnit.SECONDS))) .uri("http://httpbin.org:80") .metadata("key", "value") ) .build(); }

这种样式还允许更多的自定义谓词断言。由RouteDefinitionLocatorbean 定义的谓词使用逻辑and进行组合。通过使用 Fluent Java API,你可以在Predicate类上使用and()、or()和negate()运算符。

# [12.4.路由定义定位器](#the-discoveryclient-route-definition-locator)

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

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

# 12.4.1.为DiscoveryClient路由配置谓词和筛选器(#configuring-predicates-and-filters-for-discoveryclient-route)

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

缺省谓词是用模式/serviceId/**定义的路径谓词,其中serviceId是来自DiscoveryClient的服务的 ID。

默认的过滤器是一个重写路径过滤器,regex/serviceId/?(?.*)和替换/${remaining}。这将在向下游发送请求之前从路径中剥离服务 ID。

如果要自定义DiscoveryClient路由所使用的谓词或筛选器,请设置spring.cloud.gateway.discovery.locator.predicates[x]和spring.cloud.gateway.discovery.locator.filters[y]。这样做时,如果你想保留该功能,则需要确保包含前面显示的缺省谓词和筛选器。下面的示例显示了这是什么样子的:

示例 69.application.properties

spring.cloud.gateway.discovery.locator.predicates[0].name: Path spring.cloud.gateway.discovery.locator.predicates[0].args[pattern]: "'/'+serviceId+'/**'" spring.cloud.gateway.discovery.locator.predicates[1].name: Host spring.cloud.gateway.discovery.locator.predicates[1].args[pattern]: "'**.foo.com'" spring.cloud.gateway.discovery.locator.filters[0].name: CircuitBreaker spring.cloud.gateway.discovery.locator.filters[0].args[name]: serviceId spring.cloud.gateway.discovery.locator.filters[1].name: RewritePath spring.cloud.gateway.discovery.locator.filters[1].args[regexp]: "'/' + serviceId + '/?(?.*)'" spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'" # 13.反应堆网络访问日志(#reactor-netty-access-logs)

要启用反应堆网络访问日志,请设置-Dreactor.netty.http.server.accessLogEnabled=true。

它必须是一个 Java 系统属性,而不是一个 Spring 引导属性。

你可以将日志系统配置为具有一个单独的访问日志文件。下面的示例创建了一个注销配置:

示例 70.logback.xml

access_log.log %msg%n # 14.CORS 配置(#cors-configuration)

你可以配置网关来控制 CORS 行为。“全局”CORS 配置是 URL 模式到[[ Spring FrameworkCorsConfiguration](https://DOCS. Spring.io/ Spring/DOCS/5.0.x/javadoc-api/org/springframework/web/cors/corsconfiguration.html)的映射。以下示例配置 CORS:

示例 71.application.yml

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

在前面的示例中,对于所有 GET 请求的路径,允许从源自docs.spring.io的请求发出 CORS 请求。

要为某些网关路由谓词不处理的请求提供相同的 CORS 配置,请将spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping属性设置为spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping。当你试图支持 CORS 的 Preflight 请求,而你的路由谓词不求值到true时,这是有用的,因为 HTTP 方法是options。

# 15.执行机构 API(#actuator-api)

执行器端点允许你监视 Spring Cloud网关应用程序并与之交互。要实现远程访问,端点必须是应用程序属性中的enabled (opens new window)和通过 HTTP 或 JMX 公开 (opens new window)。下面的清单展示了如何做到这一点:

示例 72.application.properties

management.endpoint.gateway.enabled=true # default value management.endpoints.web.exposure.include=gateway # 15.1.详细执行器格式(#verbose-actuator-format)

Spring Cloud网关中添加了一种新的、更详细的格式。它为每条路由添加了更多细节,允许你查看与每条路由相关的谓词和筛选器,以及可用的任何配置。以下示例配置/actuator/gateway/routes:

[ { "predicate": "(Hosts: [**.addrequestheader.org] && Paths: [/headers], match trailing slash: true)", "route_id": "add_request_header_test", "filters": [ "[[AddResponseHeader X-Response-Default-Foo = 'Default-Bar'], order = 1]", "[[AddRequestHeader X-Request-Foo = 'Bar'], order = 1]", "[[PrefixPath prefix = '/httpbin'], order = 2]" ], "uri": "lb://testservice", "order": 0 } ]

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

示例 73.application.properties

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

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

# 15.2.检索路由过滤器(#retrieving-route-filters)

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

全局过滤器

[[gateway-route-filters]](#gateway-route-filters)

# 15.2.1.全局过滤器(#gateway-global-filters)

要检索应用于所有路由的GET,请对/actuator/gateway/globalfilters发出GET请求。由此产生的反应类似于以下情况:

{ "org.spring[email protected]77856cc5": 10100, "o[email protected]4f6fd101": 10000, "or[email protected]32d22650": -1, "[email protected]6459d9": 2147483647, "[email protected]5e0": 2147483647, "[email protected]d23": 0, "org.s[email protected]135064ea": 2147483637, "[email protected]23c05889": 2147483646 }

响应包含已到位的全局过滤器的详细信息。对于每个全局过滤器,有一个字符串表示过滤器对象(例如,org.spring[[email protected]](/cdn-cgi/l/email-protection)77856cc5)和相应的order在过滤器链中。}

# 15.2.2.路由过滤器(#gateway-route-filters)

要检索应用于路由的[GatewayFilter工厂](#gatewayfilter-factories),对GET请求/actuator/gateway/routefilters。由此产生的反应类似于以下情况:

{ "[[email protected] configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null, "[[email protected] configClass = Object]": null, "[[email protected] configClass = Object]": null }

响应包含应用于任何特定路径的GatewayFilter工厂的详细信息。对于每个工厂,都有一个对应对象的字符串表示(例如,GatewayFilter)。请注意,null值是由于端点控制器的实现不完整造成的,因为它试图设置过滤器链中对象的顺序,这不适用于GatewayFilter工厂对象。

# 15.3.刷新路径缓存(#refreshing-the-route-cache)

要清除路由缓存,请对POST请求/actuator/gateway/refresh。该请求返回一个没有响应体的 200.

# 15.4.检索在网关中定义的路由(#retrieving-the-routes-defined-in-the-gateway)

要检索在网关中定义的路由,请对GET请求/actuator/gateway/routes。由此产生的反应类似于以下情况:

[{ "route_id": "first_route", "route_object": { "predicate": "org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/[email protected]", "filters": [ "OrderedGatewayFilter{delegate=org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory$$Lambda$436/[email protected], order=0}" ] }, "order": 0 }, { "route_id": "second_route", "route_object": { "predicate": "org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/[email protected]", "filters": [] }, "order": 0 }]

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

Path Type 说明 route_id String 路线 ID。 route_object.predicate Object 路线谓词。 route_object.filters Array [GatewayFilter工厂](#gatewayfilter-factories)应用于该路由。 order Number 路线顺序。 # 15.5.检索有关特定路线的信息(#gateway-retrieving-information-about-a-particular-route)

要检索有关单个路由的信息,请对GET请求/actuator/gateway/routes/{id}(例如,/actuator/gateway/routes/first_route)。由此产生的反应类似于以下情况:

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

下表描述了响应的结构:

Path Type 说明 id String 路线 ID。 predicates Array 路由谓词的集合。每个项定义给定谓词的名称和参数。 filters Array 应用于路由的过滤器的集合。 uri String 路线的目的地 URI。 order Number 路线顺序。 # 15.6.创建和删除特定的路由(#creating-and-deleting-a-particular-route)

要创建一个路由,使用指定路由字段的 JSON 主体对POST请求/gateway/routes/{id_route_to_create}(参见检索有关特定路线的信息)。

要删除一个路由,请对DELETE请求/gateway/routes/{id_route_to_delete}。

# 15.7.回顾:所有端点的列表(#recap-the-list-of-all-endpoints)

下面的 FolloiWNG 表总结了 Spring Cloud网关执行器端点(请注意,每个端点都以/actuator/gateway作为基本路径):

ID HTTP Method 说明 globalfilters GET 显示应用于路由的全局筛选器列表。 routefilters GET 显示应用于特定路径的GatewayFilter工厂的列表。 refresh POST 清除路由缓存。 routes GET 显示在网关中定义的路由列表。 routes/{id} GET 显示有关特定路线的信息。 routes/{id} POST 为网关添加了一条新的路径。 routes/{id} DELETE 从网关删除现有的路由。 # 15.8.在多个网关实例之间共享路由(#sharing-routes-between-multiple-gateway-instances)

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

为了跨 Spring Cloud网关实例的集群共享路由,可以使用RedisRouteDefinitionRepository。要启用这种存储库,以下属性必须设置为 true:spring.cloud.gateway.redis-route-definition-repository.enabled同样,对于 RedisrateLimiter 过滤器工厂,它需要使用 Spring-boot-starter-data-redis-active Spring boot starter。

# 16.故障排除(#troubleshooting)

本节介绍了在使用 Spring Cloud网关时可能出现的常见问题。

# 16.1.日志级别(#log-levels)

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

org.springframework.cloud.gateway

org.springframework.http.server.reactive

org.springframework.web.reactive

org.springframework.boot.autoconfigure.web

reactor.netty

redisratelimiter

# 16.2.窃听(#wiretap)

反应堆网络HttpClient和HttpServer可以启用窃听功能。当与将reactor.netty日志级别设置为DEBUG或TRACE相结合时,它可以记录信息,例如通过连接发送和接收的标题和主体。要启用窃听,分别为HttpServer和HttpClient设置spring.cloud.gateway.httpclient.wiretap=true。

# 17.开发者指南(#developer-guide)

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

# 17.1.编写自定义路由谓词工厂(#writing-custom-route-predicate-factories)

为了编写路由谓词,你需要将RoutePredicateFactory实现为 Bean。有一个名为AbstractRoutePredicateFactory的抽象类,你可以对其进行扩展。

MyRoutepredicateFactory.java

@Component public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory { public MyRoutePredicateFactory() { super(Config.class); } @Override public Predicate apply(Config config) { // grab configuration from Config object return exchange -> { //grab the request ServerHttpRequest request = exchange.getRequest(); //take information from the request to see if it //matches configuration. return matches(config, request); }; } public static class Config { //Put the configuration properties for your filter here } } # 17.2.编写自定义网关过滤器工厂(#writing-custom-gatewayfilter-factories)

要编写GatewayFilter,你必须将GatewayFilterFactory实现为 Bean。你可以扩展一个名为AbstractGatewayFilterFactory的抽象类。下面的例子说明了如何做到这一点:

例 74.Pregatewayfilterfactory.java

@Component public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory { public PreGatewayFilterFactory() { super(Config.class); } @Override public GatewayFilter apply(Config config) { // grab configuration from Config object return (exchange, chain) -> { //If you want to build a "pre" filter you need to manipulate the //request before calling chain.filter ServerHttpRequest.Builder builder = exchange.getRequest().mutate(); //use builder to manipulate the request return chain.filter(exchange.mutate().request(builder.build()).build()); }; } public static class Config { //Put the configuration properties for your filter here } }

Postgatewayfilterfactory.java

@Component public class PostGatewayFilterFactory extends AbstractGatewayFilterFactory { public PostGatewayFilterFactory() { super(Config.class); } @Override public GatewayFilter apply(Config config) { // grab configuration from Config object return (exchange, chain) -> { return chain.filter(exchange).then(Mono.fromRunnable(() -> { ServerHttpResponse response = exchange.getResponse(); //Manipulate the response in some way })); }; } public static class Config { //Put the configuration properties for your filter here } } # 17.2.1.在配置中命名自定义过滤器和引用(#naming-custom-filters-and-references-in-configuration)

自定义过滤器类名称应该以GatewayFilterFactory结尾。

例如,要在配置文件中引用名为Something的过滤器,该过滤器必须位于名为SomethingGatewayFilterFactory的类中。

可以创建一个没有GatewayFilterFactory后缀的网关过滤器,例如class AnotherThing。在配置文件中,这个过滤器可以被引用为AnotherThing。这是不是所支持的命名约定,该语法可能会在将来的版本中删除。请更新过滤器名称以使其兼容。 # 17.3.编写自定义全局过滤器(#writing-custom-global-filters)

要编写自定义的全局过滤器,你必须将class AnotherThing接口实现为 Bean。这将过滤器应用于所有请求。

以下示例分别展示了如何设置全局 pre 和 post 过滤器:

@Bean public GlobalFilter customGlobalFilter() { return (exchange, chain) -> exchange.getPrincipal() .map(Principal::getName) .defaultIfEmpty("Default User") .map(userName -> { //adds header to proxied request exchange.getRequest().mutate().header("CUSTOM-REQUEST-HEADER", userName).build(); return exchange; }) .flatMap(chain::filter); } @Bean public GlobalFilter customGlobalPostFilter() { return (exchange, chain) -> chain.filter(exchange) .then(Mono.just(exchange)) .map(serverWebExchange -> { //adds header to response serverWebExchange.getResponse().getHeaders().set("CUSTOM-RESPONSE-HEADER", HttpStatus.OK.equals(serverWebExchange.getResponse().getStatusCode()) ? "It worked": "It did not work"); return serverWebExchange; }) .then(); } # 18. Building a Simple Gateway by Using Spring MVC or Webflux(#building-a-simple-gateway-by-using-spring-mvc-or-webflux) 下面描述了一种替代样式的网关。以前的文件都不适用于下面的内容。

Spring Cloud网关提供了一种名为ProxyExchange的实用对象。你可以在常规的 Spring Web 处理程序中使用它作为方法参数。它通过镜像 HTTP 动词的方法支持基本的下游 HTTP 交换。对于 MVC,它还支持通过forward()方法转发到本地处理程序。要使用ProxyExchange,在 Classpath 中包含正确的模块(spring-cloud-gateway-mvc或spring-cloud-gateway-webflux)。

下面的 MVC 示例将请求代理到/test下游的远程服务器:

@RestController @SpringBootApplication public class GatewaySampleApplication { @Value("${remote.home}") private URI home; @GetMapping("/test") public ResponseEntity proxy(ProxyExchange proxy) throws Exception { return proxy.uri(home.toString() + "/image/png").get(); } }

下面的示例对 WebFlux 做了相同的处理:

@RestController @SpringBootApplication public class GatewaySampleApplication { @Value("${remote.home}") private URI home; @GetMapping("/test") public Mono proxyPath(ProxyExchange proxy) throws Exception { String path = proxy.path("/proxy/path/"); return proxy.uri(home.toString() + "/foos/" + path).get(); }

Spring MVC 和 WebFlux 的所有特性都可用于网关处理程序方法。因此,例如,你可以插入请求头和查询参数,并且可以通过映射注释中的声明来约束传入的请求。有关这些特性的更多详细信息,请参见 Spring MVC 中ProxyExchange的文档。

可以使用ProxyExchange上的header()方法向下游响应添加标题。

你还可以通过向get()方法(和其他方法)添加一个映射器来操作响应头(以及响应中喜欢的任何其他方法)。映射器是一个Function,它接收传入的ResponseEntity并将其转换为传出的。

为“敏感”头(默认情况下,cookie和authorization)和“代理”头(x-forwarded-*)提供了一流的支持。

# 19.配置属性(#configuration-properties)

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

在 GitCode 上编辑此页 (opens new window) 上次更新: Wed Mar 09 2022 21:35:30 GMT+0800

← Spring Cloud 功能参考文档 Spring Cloud Kubernetes →



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有