Gateway 相关的知识点:

使用

如何进行路由配置

支持多级路由 **
整合 nacos :uri 以lb://开头(lb 代表从注册中心获取服务)

  1. server:
  2. port: 2001
  3. spring:
  4. cloud:
  5. gateway:
  6. routes:
  7. - id: path_route
  8. uri: https://blog.zdzy.xyz
  9. predicates:
  10. - Path=/spring_cloud
  11. - id: gs-auth
  12. uri: lb://gs-auth
  13. predicates:
  14. - Path=/gs-auth/**
  15. filters:
  16. - StripPrefix=1

默认路由配置:

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true #使用小写service-id

Spring Cloud Gateway的常用路由断言工厂

1)Path 路由断言工厂

Path 路由断言工厂接收一个参数,根据 Path 定义好的规则来判断访问的 URI 是否匹配。

spring:
  cloud:
    gateway:
      routes:
        - id: host_route
          uri: https://blog.zdzy.xyz
          predicates:
            - Path=/blog/detail/{segment}

如果请求路径为 /blog/detail/xxx,则此路由将匹配。也可以使用正则,例如 /blog/detail/** 来匹配 /blog/detail/ 开头的多级 URI。

2)Query 路由断言工厂

Query 路由断言工厂接收两个参数,一个必需的参数和一个可选的正则表达式。

spring:
  cloud:
    gateway:
      routes:
        - id: query_route
          uri: https://c.biancheng.net
          predicates:
            - Query=foo, ba.

如果请求包含一个值与 ba 匹配的 foo 查询参数,则此路由将匹配。bar 和 baz 也会匹配,因为第二个参数是正则表达式。

3)Method 路由断言工厂

Method 路由断言工厂接收一个参数,即要匹配的 HTTP 方法。

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

4)Header 路由断言工厂

Header 路由断言工厂接收两个参数,分别是 请求头名称正则表达式

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

如果请求中带有请求头名为 x-request-id,其值与 \d+ 正则表达式匹配(值为一个或多个数字),则此路由匹配。

5)自定义路由断言工厂

自定义路由断言工厂需要继承 AbstractRoutePredicateFactory 类,重写 apply 方法的逻辑。

apply 方法中可以通过 exchange.getRequest() 拿到 ServerHttpRequest 对象,从而可以获取到请求的参数、请求方式、请求头等信息。

apply 方法的参数是自定义的配置类,在使用的时候配置参数,在 apply 方法中直接获取使用。


@Component
public class CheckAuthRoutePredicateFactory
        extends AbstractRoutePredicateFactory<CheckAuthRoutePredicateFactory.Config> {
    public CheckAuthRoutePredicateFactory() {
        super(Config.class);
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return exchange -> {
            System.err.println("进入了CheckAuthRoutePredicateFactory\t" + config.getName());
            return config.getName().equals("test");
        };
    }

    public static class Config {
        private String name;

        public void setName(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }
}
spring:
  cloud:
    gateway:
      routes:
        - id: customer_route
          uri: https://blog.zdzy.xyz
          predicates:
            - name: CheckAuth
          args:
            name: test

Spring Cloud Gateway过滤器工厂的使用

GatewayFilter Factory 是 Spring Cloud Gateway 中提供的过滤器工厂。 Spring Cloud Gateway 的路由过滤器允许以某种方式修改传入的 HTTP 请求或输出的 HTTP
响应,只作用于特定的路由。

Spring Cloud Gateway 中内置了很多过滤器工厂,直接采用配置的方式使用即可,同时也支持自定义 GatewayFilter Factory 来实现更复杂的业务需求。

接下来为大家介绍几个常用的过滤器工厂类。

1. AddRequestHeader 过滤器工厂

通过名称我们可以快速明白这个过滤器工厂的作用是添加请求头。

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

符合规则匹配成功的请求,将添加 X-Request-Foo:bar 请求头,将其传递到后端服务中,后方服务可以直接获取请求头信息。代码如下所示。

class TestController {
    @GetMapping("/hello")
    public String hello(HttpServletRequest request) throws Exception {
        System.err.println(request.getHeader("X-Request-Foo"));
        return "success";
    }
}

2. RemoveRequestHeader 过滤器工厂

RemoveRequestHeader 是移除请求头的过滤器工厂,可以在请求转发到后端服务之前进行 Header 的移除操作。

spring:
  cloud:
    gateway:
      routes:
        - id: removerequestheader_route
          uri: https://blog.zdzy.xyz
          filters:
            - RemoveRequestHeader=X-Request-Foo

3. SetStatus 过滤器工厂

SetStatus 过滤器工厂接收单个状态,用于设置 Http 请求的响应码。 它必须是有效的 Spring Http_Status(org.springframework.http.HttpStatus)。 它可以是整数值 404
或枚举类型 NOT_FOUND。

spring:
  cloud:
    gateway:
      routes:
        - id: setstatusint_route
          uri: https://blog.zdzy.xyz
          filters:
            - SetStatus=401

4. RedirectTo过滤器工厂

RedirectTo 过滤器工厂用于重定向操作,比如我们需要重定向到百度。

spring:
  cloud:
    gateway:
      routes:
        - id: prefixpath_route
          uri: https://blog.zdzy.xyz
          filters:
            - RedirectTo=302, https://baidu.com

5.自定义Spring Cloud Gateway过滤器工厂

自定义 Spring Cloud Gateway 过滤器工厂需要继承 AbstractGatewayFilterFactory 类,重写 apply 方法的逻辑。命名需要以 GatewayFilterFactory 结尾,比如
CheckAuthGatewayFilterFactory,那么在使用的时候 CheckAuth 就是这个过滤器工厂的名称。

自定义过滤器工厂代码如下所示。


@Component
public class CheckAuth2GatewayFilterFactory
        extends AbstractGatewayFilterFactory<CheckAuth2GatewayFilterFactory.Config> {

    public CheckAuth2GatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            System.err.println("进入了CheckAuth2GatewayFilterFactory" + config.getName());
            ServerHttpRequest request = exchange.getRequest().mutate().build();
            return chain.filter(exchange.mutate().request(request).build());
        };
    }

    public static class Config {
        private String name;

        public void setName(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }
}
filters:
  - name: CheckAuth2
      args:
        name: 张三

全局过滤器

全局过滤器作用于所有的路由,不需要单独配置,我们可以用它来实现很多统一化处理的业务需求,比如权限认证、IP 访问限制等。

package org.springframework.cloud.gateway.filter;

import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

public interface GlobalFilter {
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

默认的实现:

Spring Cloud Gateway - 图1

Spring Cloud Gateway实战案例(限流、熔断回退、跨域、统一异常处理和重试机制)

1. 限流实战

开发高并发系统时有三把利器用来保护系统:缓存、降级和限流。 API 网关作为所有请求的入口,请求量大,我们可以通过对并发访问的请求进行限速来保护系统的可用性。

目前限流提供了基于 Redis 的实现,我们需要增加对应的依赖,代码如下所示。


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

我们可以通过 KeyResolver 来指定限流的 Key,比如我们需要根据用户来做限流,或是根据 IP 来做限流等。

2. 熔断回退实战

在 Spring Cloud Gateway 中使用 Hystrix 进行回退需要增加 Hystrix 的依赖,代码如下所示。


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

内置了 HystrixGatewayFilterFactory 来实现路由级别的熔断,只需要配置即可实现熔断回退功能。配置方式如下所示。

- id: user-service
  uri: lb://user-service
  predicates:
    - Path=/user-service/**
  filters:
    - name: Hystrix
      args:
        name: fallbackcmd
        fallbackUri: forward:/fallback

上面配置了一个 Hystrix 过滤器,该过滤器会使用 Hystrix 熔断与回退,原理是将请求包装成 RouteHystrixCommand 执行,RouteHystrixCommand 继承于
com.netflix.hystrix.HystrixObservableCommand

fallbackUri 是发生熔断时回退的 URI 地址,目前只支持 forward 模式的 URI。如果服务被降级,该请求会被转发到该 URI 中。

在网关中创建一个回退的接口,用于熔断时处理返回给调用方的信息,代码如下所示:


@RestController
public class FallbackController {

    @GetMapping("/fallback")
    public String fallback() {
        return "fallback";
    }
}

跨域实战

在 Spring Cloud Gateway 中配置跨域有两种方式,分别是代码配置方式和配置文件方式。

spring:
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedOrigins: "*"
            exposedHeaders:
              - content-type
            allowedHeaders:
              - content-type
            allowCredentials: true
              allowedMethods:
                - GET
                - OPTIONS
                - PUT
                - DELETE
                - POST

重试机制

RetryGatewayFilter 是 Spring Cloud Gateway 对请求重试提供的一个 GatewayFilter Factory。配置方式如下所示。

spring:
  cloud:
    gateway:
      routes:
        - id: fsh-house
          uri: lb://fsh-house
          predicates:
            - Path=/house/**
          filters:
            - name: Retry
              args:
                retries: 3
                series:
                  - SERVER_ERROR
                statuses:
                  - OK
                methods:
                  - GET
                  - POST
                exceptions:
                  - java.io.IOException

上述代码中具体参数含义如下所示:

  • retries:重试次数,默认值是 3 次。
  • series:状态码配置(分段),符合某段状态码才会进行重试逻辑,默认值是 SERVER_ERROR,值是 5,也就是 5XX(5 开头的状态码),共有 5 个值,代码如下所示

public enum Series {
    INFORMATIONAL(1), SUCCESSFUL(2), REDIRECTION(3), CLIENT_ERROR(4), SERVER_ERROR(5);
}

public enum HttpMethod {
    GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS,
    TRACE;
}

上述代码中具体参数含义如下所示:

  • statuses:状态码配置,和 series 不同的是这里是具体状态码的配置,取值请参考 org.springframework.http.HttpStatus。
  • methods:指定哪些方法的请求需要进行重试逻辑,默认值是 GET 方法
  • exceptions:指定哪些异常需要进行重试逻辑。默认值是 java.io.IOExceptionorg.springframework.cloud.gateway.support.TimeoutException

spring cloud gateway 原理;

Spring Cloud Gateway 依赖 Spring Boot 和 Spring WebFlux,基于 Netty 运行。它不能在传统的 servlet 容器中工作,也不能构建成 war 包。 在 Spring Cloud
Gateway 中有如下几个核心概念需要我们了解:

1)Route

Route 是网关的基础元素,由 ID、目标 URI、断言、过滤器组成。当请求到达网关时,由 Gateway Handler Mapping 通过断言进行路由匹配(Mapping),当断言为真时,匹配到路由。

2)Predicate

Predicate 是 Java 8 中提供的一个函数。输入类型是 Spring Framework ServerWebExchange。它允许开发人员匹配来自 HTTP 的请求,例如请求头或者请求参数。简单来说它就是匹配条件。

3)Filter

Filter 是 Gateway 中的过滤器,可以在请求发出前后进行一些业务上的处理。

相关的算法;

参考链接

Spring Cloud Gateway核心概念和工作原理