3.1.0

本项目提供了一个构建在 Spring 生态之上的 API Gateway,包括:Spring 5、Spring Boot 2 和 Project Reactor。Spring Cloud Gateway 旨在提供一种简单而有效的方式来路由到 API,并为它们提供横切关注点,例如:安全性、监控/指标和弹性。

1.如何包含Spring Cloud Gateway

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

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

Spring Cloud Gateway 建立在Spring Boot 2.x、Spring WebFlux和Project Reactor之上。因此,当您使用 Spring Cloud Gateway 时,您所知道的许多熟悉的同步库(例如 Spring Data 和 Spring Security)和模式可能并不适用。如果您不熟悉这些项目,我们建议您在使用 Spring Cloud Gateway 之前先阅读他们的文档以熟悉一些新概念。

Spring Cloud Gateway 需要 Spring Boot 和 Spring Webflux 提供的 Netty 运行时。它不适用于传统的 Servlet 容器或构建为 WAR 时。

2. 词汇表

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

  • 谓词:这是一个Java 8 Function Predicate。输入类型是Spring Framework ServerWebExchange。这使您可以匹配来自 HTTP 请求的任何内容,例如标头或参数。

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

3. 它是如何工作的

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

spring_cloud_gateway_diagram.png

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

在没有端口的路由中定义的 URI 分别获得 HTTP 和 HTTPS URI 的默认端口值 80 和 443。

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

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

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

4.1。快捷方式配置

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

application.yml

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

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

4.2. 完全扩展的参数

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

application.yml

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

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

5.路由谓词工厂

Spring Cloud Gateway 将路由匹配为 Spring WebFlux HandlerMapping基础架构的一部分。Spring Cloud Gateway 包含许多内置的路由谓词工厂。所有这些谓词都匹配 HTTP 请求的不同属性。您可以将多个路由谓词工厂与逻辑and语句结合起来。

5.1. 路由后谓词工厂

After路由谓词工厂采用一个参数 a (datetime它是一个 java ZonedDateTime)。此谓词匹配在指定日期时间之后发生的请求。以下示例配置了一个 after 路由谓词:
示例 1.application.yml

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

此路线匹配 2017 年 1 月 20 日 17:42 Mountain Time(丹佛)之后提出的任何请求。

5.2. 路由前谓词工厂

Before路由谓词工厂采用一个参数 a (datetime它是一个 java ZonedDateTime)。此谓词匹配在指定的 之前发生的请求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]

此路由与 2017 年 1 月 20 日 17:42 Mountain Time (Denver) 之前提出的任何请求相匹配。

5.3. 路由间谓词工厂

Between路由谓词工厂有两个参数,它们datetime1是datetime2 javaZonedDateTime对象。此谓词匹配发生在 afterdatetime1和 before的请求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]

此路线匹配 2017 年 1 月 20 日 17:42 山区时间(丹佛)和 2017 年 1 月 21 日 17:42 山区时间(丹佛)之前提出的任何请求。这对于维护窗口可能很有用。

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

示例 4.application.yml

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

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

5.5. 标头路由谓词工厂

Header路由谓词工厂有两个参数,the和headera 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 模板变量(例如.myhost.org)。

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

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

5.7. 方法路由谓词工厂

MethodRoute Predicate Factory 接受一个参数,该methods参数是一个或多个参数:要匹配的 HTTP 方法。以下示例配置方法路由谓词:

示例 7.application.yml

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

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

5.8. 路径路由谓词工厂

PathRoute Predicate Factory 有两个参数:一个 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/1or/red/1/或/red/blueor /blue/green。

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

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

可以使用一种实用方法(称为get)来更轻松地访问这些变量。以下示例显示了如何使用该get方法:

Map<String, String> uriVariables = ServerWebExchangeUtils.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.表达式匹配的查询参数,则前面的路由匹配,因此green并且greet会匹配。

5.10. RemoteAddr 路由谓词工厂

路由谓词工厂采用的RemoteAddr列表(最小大小为 1)sources,它们是 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 Gateway 位于代理层后面,这可能与实际客户端 IP 地址不匹配。

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

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

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

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

考虑以下标头值:

X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3

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

maxTrustedIndexresult
[Integer.MIN_VALUE,0](invalid, IllegalArgumentException during initialization)
10.0.0.3
20.0.0.2
30.0.0.1
[4, Integer.MAX_VALUE]0.0.0.1

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

示例 11.application.yml

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)。权重是按组计算的。以下示例配置权重路由谓词:

示例 11.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,将约 20% 的流量转发到weightlow.org