1、为什么用网关?能做什么?为什么选择Gateway?

1.1、为什么用网关

网关api:封装了系统内部架构,为每个客户端提供一个定制的 API。在微服务架构中,服务网关的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。

1.2、能做什么

服务网关在完成客户端与服务器端报文格式转换的同时,它可能还具有身份验证、监控、缓存、请求管理、静态响应处理等功能。另一方面,也可以在网关层制定灵活的路由策略。针对一些特定的 API,我们需要设置白名单、路由规则等各类限制
在这里插入图片描述
Spring Cloud Gateway是专为为网关的角色而设计的,功能强大,而且是官方出品

1.3、为什么选择Gateway/Gateway特征功能

  • 能够匹配任何请求属性上的路由;

  • 谓词和过滤器特定于路由;

  • Hystrix、sentinel集成;

  • Spring Cloud DiscoveryClient的集成

  • 易于编写的谓词和过滤器;

  • 请求速率限制;

  • 路径改写;

在这里插入图片描述

2、简介

Spring Cloud Gateway是Spring Cloud官方推出的第二代网关框架,取代Zuul网关(1.0不再维护了,2.0不再集成)。基于Spring5.0+SpringBoot2.0+WebFlux(高性能的Reactor模式响应式通信框架Netty,异步非阻塞),性能高于zuul 1.0,提供一种简单而高效的方法来将请求路由到API。网关作为流量的入口,在微服务系统中有着非常作用,网关常见的功能有路由转发、权限校验、限流控制等作用。

spring cloud gateway至少要求JDK8(函数式编程);

Spring Cloud Gateway工作流程
在这里插入图片描述

3、项目创建

gitee项目地址,可下载查看

  • jar
<!-- 配置管理服务 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 服务发现 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--spring-cloud-starter-gateway 网关-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
  • yaml
spring:
  application:
    #服务名字
    name: travel-post-it-gateway-api
  cloud:
    # 服务发现
    nacos:
      discovery:
        server-addr: localhost:8448
        namespace: ${spring.profiles.active}
        file-extension: yaml      
        username: nacos
        password: nacos
    #配置网关
    gateway:
      discovery:
        locator:
          #启用DiscoveryClient网关集成,可以实现服务的发现
          enabled: true 

      #配置网关路由转发规则
      routes:
          # 路由的id唯一
        - id: route1
          # 服务地址 lb:负载均衡
          uri: lb://demo-web-api
          # #谓词 是否匹配
          predicates: 
            #- Path:拦截的路径
            - Path=/**
            #- After=2020-08-15T22:35:25.335+08:00[Asia/Shanghai]
            #- Before=2020-09-15T17:35:25.335+08:00[Asia/Shanghai]
            #- Between=2020-08-13T17:35:25.335+08:00[Asia/Shanghai], 2020-08-14T17:35:25.335+08:00[Asia/Shanghai]
            #- Cookie=token, 123456
            #- Header=X-Request-Id, \d+
            #- Query=token
            #- Token=123456
            #- AccessTime=下午6:00, 上午6:00
            # 过滤器
          # filters:
              # 请求头过滤
          #   - AddRequestHeader=X-Request-red, blue
              # 请参数过滤
          #   - AddRequestParameter=color, red

3.1、参数说明

  • Route:网关的基本构建块。 它由id,目标uri,predicates集合和filters集合定义。 如果聚合谓词为true,则匹配路由。

  • Predicate:这是Java 8函数谓词。 输入类型是Spring Framework ServerWebExchange。 这使您可以匹配HTTP请求中的所有内容,例如标头或参数。

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

官方文档中有如下内容,非常强大

1.如何包括Spring Cloud Gateway
2.词汇表
3.工作原理
4.配置路由谓词工厂和网关过滤工厂
5.路由谓词工厂
6. GatewayFilter工厂
7.全局过滤器
8. HttpHeadersFilters
9. TLS和SSL
10.配置
11.路由元数据配置
12. Http超时配置
13. Reactor Netty访问日志
14. CORS配置
15.执行器API
16.故障排除
17.开发人员指南
18.使用Spring MVC或Webflux构建一个简单的网关
19.配置属性

4、路线谓词工厂

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

datetime(这是一个Java ZonedDateTime)。

  • 时区生成:2019-09-15T20:58:18.786182+08:00[Asia/Shanghai]
    public static void main(String[] args) {
       ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
        System.out.println(zbj);
    }
    

官网copy的谓词工厂如下

4.1、After路由谓词工厂

该谓词匹配在指定日期时间之后发生的请求。

以下示例配置了路由后谓词:

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

4.2、Before由谓词工厂

匹配在指定日期时间之前发生的请求

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

4.3、Between 路径谓词工厂

此谓词匹配发生在datetime1之后和datetime2之前的请求。datetime2参数必须在datetime1之后。

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]

4.4、Cookie路由谓词工厂

Cookie路由谓词工厂接受两个参数,Cookie名称和regexp(这是一个Java正则表达式)。

此谓词匹配具有给定名称且其值与正则表达式匹配的Cookie。

spring:
  cloud:
    gateway:
      routes:
      - id: cookie_route
        uri: https://example.org
        predicates:
        - Cookie=chocolate, \d+

4.5、Header 路由谓词工厂

标头路由谓词工厂使用两个参数,标头名称和一个regexp(这是Java正则表达式)。

该谓词与具有给定名称的 header匹配,该header 的值与正则表达式匹配。

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

4.6、Host 路由谓词工厂

主机路由谓词工厂接受一个参数:主机名模式列表。","作为分隔符。匹配请求接口的url路径是否合法

该谓词匹配匹配模式的主机头,,支持通配符

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

4.7、 Method 路由谓词工厂

接受一个methods参数

该参数是一个或多个参数:要匹配的HTTP方法

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

4.8、Path 路由谓词工厂

路径谓词工厂有两个参数:Spring PathMatcher模式列表和一个名为matchTrailingSlash(默认为true)的可选标志。以下示例配置路径谓词:
matchTrailingSlash :是否匹配末尾"/"
``

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

4.9、Query 路由谓词工厂

查询路由谓词工厂有两个参数:一个必需的参数和一个可选的regexp(这是一个Java正则表达式)

请求的参数中是否含有某个值

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

4.10、RemoteAddr 路由谓词工厂

远程调用地址 路由谓词工厂获取源的列表(最小大小1),这些源是CIDR表示法(IPv4或IPv6)字符串

例如192.168.0.1/16(其中192.168.0.1是IP地址,16是子网掩码)

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

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

4.11、 路由谓词工厂

权重路由谓词工厂有两个参数:group和Weight(int)。每组计算权重。

请求分流

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

5、过滤器配置

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

官网copy的网关过滤器工厂如下

5.1、AddRequestHeader网关过滤器工厂

添加请求头:AddRequestHeader 网关过滤器工厂采用名称和值参数。

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

URI变量可以在值中使用,并在运行时展开

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

5.2、AddRequestParameter 网关过滤器工厂

添加请求参数:采用名称和值参数

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

URI变量可以在值中使用,并在运行时展开

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

5.3、AddResponseHeader 网关过滤器工厂

添加相应头

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

URI变量可以在值中使用,并在运行时展开。

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

5.4、DedupeResponseHeader网关过滤器工厂

删除重复响应头:采用名称参数和可选策略参数。名称可以包含以空格分隔的标题名称列表。
可选的 strategy 参数:RETAIN_FIRST(默认,先保留)、RETAIN_LAST(后保留)、RETAIN_UNIQUE(唯一保留).

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

5.5、Spring Cloud CircuitBreaker 网关过滤器工厂

Spring Cloud CircuitBreaker 网关过滤器工厂使用Spring Cloud CircuitBreaker API将网关路由包装在断路器中。 Spring Cloud CircuitBreaker支持多个可与Spring Cloud Gateway一起使用的库。 Spring Cloud开箱即用地支持Resilience4J。

要启用Spring Cloud CircuitBreaker过滤器,您需要在类路径上放置spring-cloud-starter-circuitbreaker-reactor-resilience4j。

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

要配置断路器,请参阅所使用的基础断路器实现的配置。

Resilience4J文档

Spring Cloud CircuitBreaker过滤器还可以接受可选的fallbackUri参数。 当前,仅支持转发:计划的URI。 如果调用了后备,则请求将转发到与URI匹配的控制器。 以下示例配置了这种后备:

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

5.6、FallbackHeaders 网关过滤器工厂

FallbackHeaders工厂使您可以在转发到外部应用程序中的fallbackUri的请求的标头中添加Spring Cloud CircuitBreaker执行异常详细信息,如以下情况所示:

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上运行的应用程序中的回退端点或处理程序。 FallbackHeaders过滤器将具有异常类型,消息和(如果有)根本原因异常类型和消息的标头添加到该请求。

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

executionExceptionTypeHeaderName ("Execution-Exception-Type")

executionExceptionMessageHeaderName ("Execution-Exception-Message")

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

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

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

5.7、MapRequestHeader 网关过滤器工厂

MapRequestHeader 网关过滤器工厂采用fromHeader和toHeader参数。它创建一个新的命名头(toHeader),并从传入http请求的现有命名头(fromHeader)中提取该值。如果输入标头不存在,则筛选器没有影响。如果新的命名头已经存在,则其值将用新值进行扩充。以下示例配置MapRequestHeader:

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

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

5.8、PrefixPath 网关过滤器工厂

采用单个前缀参数

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

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

5.9、PreserveHostHeader 网关过滤器工厂

没有参数。此筛选器设置路由筛选器检查的请求属性,以确定是否应发送原始主机标头,而不是HTTP客户端确定的主机标头。

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

5.10、RequestRateLimiter 网关过滤器工厂

请求速率限制器
RequestRateLimiter GatewayFilter工厂使用RateLimiter实现来确定是否允许继续当前请求。 如果不是,则会返回HTTP 429-太多请求(默认情况下)的状态。

该过滤器采用可选的keyResolver参数和特定于速率限制器的参数(本节稍后将介绍)。

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

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

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

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

默认情况下,如果KeyResolver找不到密钥,则拒绝请求。 您可以通过设置spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key(正确或错误)和spring.cloud.gateway.filter.request-rate-limiter.empty-key来调整此行为。 状态代码属性。
.
.
.
更多内容查看官网

5.11、RedirectTo 网关过滤器工厂

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

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

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

5.12、RemoveRequestHeader 网关过滤器工厂

RemoveRequestHeader GatewayFilter工厂采用名称参数。 它是要删除的Header的名称。

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

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

5.13、RemoveResponseHeader网关过滤器工厂

RemoveResponseHeader GatewayFilter工厂采用名称参数。它是要删除的header 的名称。

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

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

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

5.14、RemoveRequestParameter 网关过滤器工厂

它是要删除的查询参数的名称

这将删除red 参数,然后再将其发送到下游。

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

5.15、RewritePath网关过滤器工厂

重写路径网关过滤器工厂采用路径regexp参数和替换参数。这使用Java正则表达式来灵活地重写请求路径。

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

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

5.16、RewriteLocationResponseHeader 网关过滤器工厂

RewriteLocationResponseHeader GatewayFilter工厂修改位置响应头的值,通常是为了消除后端特定的详细信息。它使用stripVersionMode、locationHeaderName、hostValue和protocolsRegex参数。

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

例如,对于POST api.example.com/some/object/name的请求,object-service.prod.example.net/v2/some/object/id的位置响应标头值被重写为api.example.com/some/object/id。

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

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

  • AS_IN_REQUEST :仅当原始请求路径不包含任何版本时,才剥离该版本。

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

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

protocolRegex参数必须是一个有效的正则表达式字符串,协议名称与该字符串匹配。 如果不匹配,则过滤器不执行任何操作。 默认值为http | https | ftp | ftps。

5.17、RewriteResponseHeader 网关过滤器工厂

RewriteResponseHeader GatewayFilter工厂采用名称,正则表达式和替换参数。 它使用Java正则表达式以灵活的方式重写响应头值。 以下示例配置RewriteResponseHeader GatewayFilter:

对于 /42?user=ford&password=omg!what&flag=true的header 值,在发出下游请求后将其设置为/42?user=ford&password=***&flag=true。

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

5.18、SaveSession 网关过滤器工厂

SaveSession 网关过滤器工厂在向下游转发呼叫之前强制执行WebSession::save操作。 这在使用类似Spring Session的延迟数据存储时特别有用,您需要确保在进行转发调用之前保存了会话状态。 以下示例配置SaveSession GatewayFilter:

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

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

5.19、SecureHeaders 网关过滤器工厂

SecureHeaders GatewayFilter工厂将许多头添加到响应中。

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

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

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

  • X-Frame-Options (DENY)

  • X-Content-Type-Options (nosniff)

  • Referrer-Policy (no-referrer)

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

  • X-Download-Options (noopen)

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

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

  • xss-protection-header

  • strict-transport-security

  • 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

5.20、SetPath网关过滤器工厂

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

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

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

5.21、SetRequestHeader 网关过滤器工厂

工厂采用名称和值参数

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

该网关过滤器用给定名称替换(而不是添加)所有headers 。 因此,如果下游服务器响应X-Request-Red:1234,则将其替换为X-Request-Red:Blue,这是下游服务将收到的内容。

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

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

5.22、SetResponseHeader 网关过滤器工厂

工厂采用名称和值参数

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

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

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

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

5.23、SetStatus 网关过滤器工厂

单个参数status。 它必须是有效的Spring HttpStatus。 它可以是整数值404或枚举的字符串表示形式:NOT_FOUND。

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

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

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

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

5.24、StripPrefix 网关过滤器工厂

工厂采用一个参数,即parts。 parts参数指示在向下游发送请求之前,要从请求中剥离的路径中的部分数量。

当通过网关向/name/blue/red发出请求时,对nameservice的请求去除掉前面两个前缀变为:nameservice/red。

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

5.25、Retry 网关过滤器工厂

重试GatewayFilter工厂支持以下参数:

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

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

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

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

  • exceptions:应重试的引发异常的列表。

  • backoff:为重试配置的指数补偿。 在firstBackoff *(因子^ n)的退避间隔之后执行重试,其中n是迭代。 如果配置了maxBackoff,则将应用的最大退避限制为maxBackoff。 如果basedOnPreviousValue为true,则通过使用prevBackoff * factor计算退避量。

如果启用了以下默认值,则为“Retry”过滤器配置:

  • retries:3次

  • series:5XX系列

  • methods:GET方法

  • exceptions:IOException和TimeoutException

  • backoff:disabled

spring:
  cloud:
    gateway:
      routes:
      - id: retry_test
        uri: http://localhost:8080/flakey
        predicates:
        - Host=*.retry.com
        filters:
        - name: Retry
          args:
            retries: 3
            statuses: BAD_GATEWAY
            methods: GET,POST
            backoff:
              firstBackoff: 10ms
              maxBackoff: 50ms
              factor: 2
              basedOnPreviousValue: false

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

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

5.26、RequestSize 网关过滤器工厂

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

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

当请求由于大小而被拒绝时,RequestSize GatewayFilter工厂将响应状态设置为413 Payload Too Large,并带有附加的报头errorMessage。

errorMessage:Request size is larger than permissible limit. Request size is 6.0 MB where permissible limit is 5.0 MB

如果未在路由定义中作为过滤器参数提供,则默认请求大小将设置为5 MB。

5.27、SetRequestHostHeader网关过滤器工厂

在某些情况下,可能需要覆盖主机头。 在这种情况下,SetRequestHostHeader GatewayFilter工厂可以用指定的值替换现有的主机头。 过滤器采用主机参数。 下面的清单配置了SetRequestHostHeader GatewayFilter:

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

SetRequestHostHeader GatewayFilter工厂用example.org替换主机头的值。

5.28、Modify a Request Body网关过滤器工厂

您可以使用ModifyRequestBody筛选器筛选器来修改请求主体,然后将其由网关向下游发送。

以下清单显示了如何修改请求正文GatewayFilter:

如果请求没有正文,则RewriteFilter将传递为null。 应该返回Mono.empty()以便在请求中分配丢失的正文。

@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;
    }
}

5.29、Modify a Response Body 网关过滤器工厂

您可以使用ModifyResponseBody筛选器在将响应正文发送回客户端之前对其进行修改。

只能使用Java DSL来配置此过滤器。

如果响应没有主体,则RewriteFilter将传递为null。 应该返回Mono.empty()以便在响应中分配丢失的主体。

@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();
}

5.30、Token Relay网关过滤器工厂

Token Relay 是OAuth2使用者充当客户端并将传入token 转发到传出资源请求的地方。 使用者可以是纯客户端(如SSO应用程序)或资源服务器。

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

  • 如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 Gateway启用此功能,请添加以下依赖项

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

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

有关完整的工作示例,请参见此项目

仅当设置了适当的spring.security.oauth2.client.*属性(会触发创建ReactiveClientRegistrationRepository bean)时,才会创建TokenRelayGatewayFilterFactory bean。

TokenRelayGatewayFilterFactory使用的ReactiveOAuth2AuthorizedClientService的默认实现使用内存中的数据存储。 如果需要更强大的解决方案,则需要提供自己的实现ReactiveOAuth2AuthorizedClientService。

5.31、Default过滤器

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

spring:
  cloud:
    gateway:
      default-filters:
      - AddResponseHeader=X-Response-Default-Red, Default-Blue
      - PrefixPath=/httpbin

6、Global Filters全局过滤器

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

此接口及其用法可能会在将来的迭代版本中发生更改。

6.1、组合全局过滤器和网关过滤器排序

当请求与路由匹配时,筛选web处理程序将全局筛选器的所有实例以及网关筛选器的所有路由特定实例添加到筛选器链。此组合过滤器链按org.springframework.core.orderd接口,您可以通过实现getOrder()方法来设置它。

由于SpringCloudGateway区分了过滤器逻辑执行的“pre”和“post”阶段,优先级最高的过滤器在“pre”(预)阶段是第一个,最后一个在“post”阶段。

客户端向Spring Cloud Gateway发出请求。 如果网关处理程序映射确定请求与路由匹配,则将其发送到网关Web处理程序。 该处理程序通过特定于请求的过滤器链来运行请求。 筛选器由虚线分隔的原因是,筛选器可以在发送代理请求之前和之后运行逻辑。 所有“pre”过滤器逻辑均被执行。 然后发出代理请求。 发出代理请求后,将运行“post”过滤器逻辑。
在这里插入图片描述

以下列表配置筛选器链:

@Bean
public GlobalFilter customFilter() {
    return new CustomGlobalFilter();
}

public class CustomGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("custom global filter");
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -1;
    }
}

6.2、转发路由筛选器

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

6.3、负载平衡器客户端筛选器(利用Ribbon实现)

LoadBalancerClientFilter在名为ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的交换属性中查找URI。 如果URL的方案为lb(例如 lb://myservice),它将使用Spring Cloud LoadBalancerClient将名称(在本例中为myservice)解析为实际的主机和端口,并替换同一属性中的URI。 未经修改的原始URL会附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。 筛选器还会在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR属性中查找其是否等于lb。如果是,则应用相同的规则。 下面的清单配置一个LoadBalancerClientFilter:

spring:
  cloud:
    gateway:
      routes:
      - id: myRoute
        uri: lb://service
        predicates:
        - Path=/service/**

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

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

网关支持所有负载平衡器功能。您可以在Spring Cloud Commons文档中阅读更多关于它们的内容。

6.4、ReactiveLoadBalancerClientFilter

ReactiveLoadBalancerClientFilter在名为ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的交换属性中查找URI。 如果URL具有lb方案(例如lb://myservice),它将使用Spring Cloud ReactorLoadBalancer将名称(在本示例中为myservice)解析为实际的主机和端口,并替换同一属性中的URI。 未经修改的原始URL会附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。 筛选器还会在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR属性中查找其是否等于lb。如果是,则应用相同的规则。 以下清单配置了ReactiveLoadBalancerClientFilter:

spring:
  cloud:
    gateway:
      routes:
      - id: myRoute
        uri: lb://service
        predicates:
        - Path=/service/**

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

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

6.5、The Netty Routing Filter

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

6.6、The Netty Write Response Filter

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

6.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中,以供稍后在过滤器链中使用。

6.8、Websocket路由过滤器

如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR交换属性中的URL具有ws或wss方案,则将运行websocket路由筛选器。 它使用Spring WebSocket基础结构将websocket请求转发到下游。

您可以通过为URI加上lb前缀来平衡websocket的负载,例如lb:ws://serviceid。

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

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

6.9、网关指标过滤器

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

  • routeId:路由ir

  • routeUri:API路由到的URI。

  • outcome:结果,按HttpStatus.Series分类。

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

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

  • httpMethod:用于请求的HTTP方法。

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

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

6.10、Marking An Exchange As Routed将交换标记为路由

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

  • ServerWebExchangeUtils.isAlreadyRouted接收ServerWebExchange对象,并检查其是否已“routed”。

  • ServerWebExchangeUtils.setAlreadyRouted接收一个ServerWebExchange对象,并将其标记为“routed”。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐