# Spring Cloud Gateway网关

# 说明

  • 什么是API网关

    网关的角色是作为一个 API 架构,用来保护、增强和控制对于 API 服务的访问。 API网关是一个处于应用程序或服务(提供 REST API 接口服务)之前的系统,用来管理授权、访问控制和流量限制等, 这样 REST API 接口服务就被 API 网关保护起来,对所有的调用者透明。 因此,隐藏在 API 网关后面的业务系统就可以专注于创建和管理服务,而不用去处理这些策略性的基础设施。

  • Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的网关,

  • Spring Cloud Gateway旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。

  • Spring Cloud Gateway作为Spring Cloud生态系中的网关,目标是替代ZUUL,其不仅提供统一的路由方式, 并且基于Filter链的方式提供了网关基本的功能,例如:安全,监控/埋点,和限流等。

# Gateway使用说明

# 1、Gateway 3大术语

  • Filter(过滤器):

    可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。 过滤器为org.springframework.cloud.gateway.filter.GatewayFilter类的实例。

  • Route(路由):

    网关配置的基本组成模块。一个Route模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。 如果断言为真,则路由匹配,目标URI会被访问。

  • Predicate(断言):

    这是一个 Java 8 的 Predicate,可以使用它来匹配来自 HTTP 请求的任何内容, 例如 headers 或参数。断言的输入类型是一个 ServerWebExchange。

# 2、Predicate介绍

# 2.1通过时间匹配

Predicate 支持设置一个时间,在请求进行转发的时候,可以通过判断在这个时间之前或者之后进行转发。 在某个时间点之前:

spring:
  cloud:
    gateway:
      routes:
        - id: time_route
          uri: http://ityouknow.com
          predicates:
            - After=2018-01-20T06:06:06+08:00[Asia/Shanghai]

在某个时间点之后:

spring:
  cloud:
    gateway:
      routes:
        - id: after_route
          uri: http://ityouknow.com
          predicates:
            - Before=2018-01-20T06:06:06+08:00[Asia/Shanghai]

在某段时间之间

spring:
  cloud:
    gateway:
      routes:
        - id: after_route
          uri: http://ityouknow.com
          predicates:
            - Between=2018-01-20T06:06:06+08:00[Asia/Shanghai], 2019-01-20T06:06:06+08:00[Asia/Shanghai]

Cookie Route Predicate 可以接收两个参数,一个是 Cookie name , 一个是正则表达式,路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配, 如果匹配上就会执行路由,如果没有匹配上则不执行。

spring:
  cloud:
    gateway:
      routes:
        - id: cookie_route
          uri: http://ityouknow.com
          predicates:
            - Cookie=ityouknow, kee.e

# 2.3通过hearder进行匹配

Header Route Predicate 和 Cookie Route Predicate 一样,也是接收 2 个参数, 一个 header 中属性名称和一个正则表达式,这个属性值和正则表达式匹配则执行。

spring:
  cloud:
    gateway:
      routes:
        - id: header_route
          uri: http://ityouknow.com
          predicates:
            - Header=X-Request-Id, \d+

# 2.4通过 Host 匹配

Host Route Predicate 接收一组参数,一组匹配的域名列表,这个模板是一个 ant 分隔的模板, 用.号作为分隔符。它通过参数中的主机地址作为匹配规则。

spring:
  cloud:
    gateway:
      routes:
        - id: host_route
          uri: http://ityouknow.com
          predicates:
            - Host=**.ityouknow.com

# 2.5通过请求方式匹配

可以通过是 POST、GET、PUT、DELETE 等不同的请求方式来进行路由。

spring:
  cloud:
    gateway:
      routes:
        - id: method_route
          uri: http://ityouknow.com
          predicates:
            - Method=GET

# 2.6通过请求路径匹配

Path Route Predicate 接收一个匹配路径的参数来判断是否走路由, 如果请求路径符合要求,则此路由将匹配。

spring:
  cloud:
    gateway:
      routes:
        - id: host_route
          uri: http://ityouknow.com
          predicates:
            - Path=/foo/{segment}

# 2.7通过请求参数匹配

Query Route Predicate 支持传入两个参数,一个是属性名一个为属性值,属性值可以是正则表达式。

spring:
  cloud:
    gateway:
      routes:
        - id: query_route
          uri: http://ityouknow.com
          predicates:
            - Query=smile

还可以将 Query 的值以键值对的方式进行配置,这样在请求过来时会对属性值和正则进行匹配,匹配上才会走路由。

spring:
  cloud:
    gateway:
      routes:
        - id: query_route
          uri: http://ityouknow.com
          predicates:
            - Query=keep, pu.

这样只要当请求中包含 keep 属性并且参数值是以 pu 开头的长度为三位的字符串才会进行匹配和路由。

# 2.8通过请求 ip 地址进行匹配

Predicate 也支持通过设置某个 ip 区间号段的请求才会路由, RemoteAddr Route Predicate 接受 cidr 符号 (IPv4 或 IPv6) 字符串的列表(最小大小为 1), 例如 192.168.0.1/16 (其中 192.168.0.1 是 IP 地址,16 是子网掩码)。

spring:
  cloud:
    gateway:
      routes:
        - id: remoteaddr_route
          uri: http://ityouknow.com
          predicates:
            - RemoteAddr=192.168.1.1/24

# 2.9组合使用

各种 Predicates 同时存在于同一个路由时,请求必须同时满足所有的条件才被这个路由匹配。

spring:
  cloud:
    gateway:
      routes:
        - id: host_foo_path_headers_to_httpbin
          uri: http://ityouknow.com
          predicates:
            - Host=**.foo.org
            - Path=/headers
            - Method=GET
            - Header=X-Request-Id, \d+
            - Query=foo, ba.
            - Query=baz
            - Cookie=chocolate, ch.p
            - After=2018-01-20T06:06:06+08:00[Asia/Shanghai]

# 3、Filter介绍

共26种Filter, 1 AddRequestHeader GatewayFilter Factory

2 AddRequestParameter GatewayFilter Factory

3 AddResponseHeader GatewayFilter Factory

4 DedupeResponseHeader GatewayFilter Factory

5 Hystrix GatewayFilter Factory

6 FallbackHeaders GatewayFilter Factory

7 PrefixPath GatewayFilter Factory

8 PreserveHostHeader GatewayFilter Factory

9 RequestRateLimiter GatewayFilter Factory

10 RedirectTo GatewayFilter Factory

11 RemoveHopByHopHeadersFilter GatewayFilter Factory

12 RemoveRequestHeader GatewayFilter Factory

13 RemoveResponseHeader GatewayFilter Factory

14 RewritePath GatewayFilter Factory

15 RewriteResponseHeader GatewayFilter Factory

16 SaveSession GatewayFilter Factory

17 SecureHeaders GatewayFilter Factory

18 SetPath GatewayFilter Factory

19 SetResponseHeader GatewayFilter Factory

20 SetStatus GatewayFilter Factory

21 StripPrefix GatewayFilter Factory

22 Retry GatewayFilter Factory

23 RequestSize GatewayFilter Factory

24 Modify Request Body GatewayFilter Factory

25 Modify Response Body GatewayFilter Factory

26 Default Filters

下面举例说明几个常用的过滤器,其他详细信息请参考官文文档 spring-cloud-gateway GatewayFilter介绍 (opens new window)

# 3.1 AddRequestHeader(添加请求头信息)

对于所有匹配的请求,将会给传给下游的请求添加一个请求头 X-Request-Foo:Bar

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

# 3.2 AddRequestParameter(添加参数)

对于所有匹配的请求,将给传给下游的请求添加一个查询参数 foo=bar

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

# 3.3 AddResponseHeader(添加相应头信息)

对于所有匹配的请求,添加一个响应头X-Response-Foo:Bar

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

# 3.4 PrefixPath(添加前缀)

所有匹配的请求都将加上前缀/mypath。 例如,如果请求是/hello,那么经过这个过滤器后,发出去的请求变成/mypath/hello

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

# 3.5 RequestRateLimiter(限流)

RequestRateLimiter网关过滤器使用一个RateLimiter实现来决定是否当前请求可以继续往下走。 如果不能,默认将返回HTTP 429 - Too Many Requests 这个过滤器接受一个可选的参数keyResolver,这个参数是一个特定的rate limiter

KeyResolver默认的实现是PrincipalNameKeyResolver,它从ServerWebExchange中检索Principal, 并调用Principal.getName()方法。 默认情况下,如果KeyResolver没有找到一个key,那么请求将会被denied(译:否认,拒绝)。 这种行为可以通过 spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key(true or false) 和spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code属性 来进行调整.

# 3.6 Default Filters(默认过滤器)

如果你想要添加一个过滤器并且把它应用于所有路由的话, 你可以用spring.cloud.gateway.default-filters。 这个属性接受一个过滤器列表。

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

# 3.7 Global Filters(全局过滤器)

当一个请求过来的时候,将会添加所有的GatewayFilter实例和所有特定的GatewayFilter实例到过滤器链上。 过滤器链按照org.springframework.core.Ordered接口对该链路上的过滤器进行排序。 你可以通过实现接口中的getOrder()方法或者使用@Order注解。 Spring Cloud Gateway将过滤器执行逻辑分为“pre”和“post”阶段。 优先级最高的过滤器将会是“pre”阶段中的第一个过滤器,同时它也将是“post”阶段中的最后一个过滤器。

自定义全局过滤器例子:

gateway_01.png

# 4、CORS配置(跨域)

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

上面的例子中,所有原始为docs.spring.io的GET请求均被允许跨域请求。

# SpringCloud集成

# 1、引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<!--如果不使用Redis RateLimiter可以不导入-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

# 2、添加配置项(application.yml)

spring:
  cloud: 
    gateway:
      routes:
        - id: header_route
          uri: http://10.0.29.187:8080/
          predicates:
            - Header=X-Request-Id, \d+
        - id: path_route
          uri: http://10.0.29.187:8080/
          predicates:
        - id: query_route
          uri: http://10.0.29.187:8080/
          predicates:
            - Query=baz

# 3、启动类(application.java)

gateway_02.png