目录:

  • 1.Gateway 是什么?
  • 2.Gateway 主要能干什么?
  • 3.Gateway三大核心概念
  • 4.Gateway工作流程
  • 5.使用实例
  • 6.Gateway常用Predicate
  • Ⅰ.After Route Predicate
  • Ⅱ.Before Route Predicate
  • Ⅲ.Between Route Predicate
  • Ⅳ.Cookie Route Predicate
  • Ⅴ.Header Route Predicate
  • Ⅵ.Host Route Predicate
  • Ⅶ.Method Route Predicate
  • Ⅷ.Path Route Predicate
  • Ⅸ.Query Route Predicate
  • 7.Gateway自定义过滤器


1.Gateway 是什么?

Spring Cloud Gateway是基于Spring Boot 2.x,Spring WebFlux和Project Reactor构建的。Gateway易在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤功能,例如:熔断,限流,重试等。

Spring Cloud Gateway作为springcloud生态系统中的网关,目标的替代Zuul,在springcloud 2.0 以上的版本中,没有对Zuul 2.0 以上版本进行集成,仍然使用Zuul 1.x版本的非Reactor模式的老版本。为了提高网关的性能,Spring Cloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层是使用了高性能的Reactor模式通信框架Netty。

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

2.Gateway 主要能干什么?

  • 反向代理
  • 鉴权
  • 流量控制
  • 熔断
  • 日志监控

3.Gateway三大核心概念

Routr(路由):
网关的基本构建模块。它由ID,目标URI,一系列断言和过滤器集合定义。如果断言为true,则匹配路由。

Predicate(断言):
参考Java 8 的java.util.function.Predicate。我们可以匹配HTTP请求中的所有内容,例如请求头或参数。如果请求与断言相匹配则进行路由。

Filter(过滤器):
Spring框架中GatewayFilter的实例。可以在请求被路由之前或之后对请求进行修改。

4.Gateway工作流程

springGateway 传递真实IP spring gateway tcp 网关_Cloud


客户端向Spring Cloud Gateway发出请求。然后在Gateway Handler Mapping中找到与请求相匹配的路由,将其发送到Gateway Web Handdler。Gateway Web Handdler再根据指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开,是因为过滤器可能会在发送代理请求之前或之后,执行业务逻辑。Filter在发送代理请求之前可以做参数校验,权限校验,流量监控,日志输出,协议转换等,Filter在发送代理请求之后可以做响应内容,响应头的修改,日志的输出,流量的监控等。

5.使用实例

Ⅰ.在父工程下,新建Module : cloud-gateway-gateway9527

Ⅱ.引入相关依赖:

<dependencies>
        <!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--引入自己定义的api通用包,可以使用Payment支付Entity-->
        <dependency>
            <groupId>com.mk</groupId>
            <artifactId>cloud-api-common</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

Ⅲ.application.yml 配置文件

server:
  port: 9527


spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment_route          # id  保证唯一性
          uri: lb://CLOUD-PROVIDER-SERVICE    #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/getServer/**     #断言   路径相匹配进行路由
      discovery:
        locator:
          enabled: true  #开启从注册中心动态创建路由的功能,利用微服务名进行路由
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka

Ⅳ.主启动类

@SpringBootApplication
@EnableEurekaClient
public class Gateway9527 {
    public static void main(String[] args) {
        SpringApplication.run(Gateway9527.class,args);
    }
}

访问的getServer方法如下:

@GetMapping("/payment/getServer")
    public String getServer(){
        return this.serverPort;
    }

测试结果:

springGateway 传递真实IP spring gateway tcp 网关_Cloud_02

6.Gateway常用Predicate

Ⅰ.After Route Predicate

After Route Predicate有一个参数为datetime(其是Java8 ZonedDateTime)。该谓词匹配在指定日期时间之后发生的请求。
例如如下配置:

spring:
  cloud:
    gateway:
      routes:
        - id: payment_route          # id  保证唯一性
          uri: lb://CLOUD-PROVIDER-SERVICE    #匹配后提供服务的路由地址
          predicates:
            - After=2021-05-24T11:22:43.136+08:00[Asia/Shanghai]

2021-05-24 11:22 之后的请求都能够访问,这个时间之前访问会404

springGateway 传递真实IP spring gateway tcp 网关_spring_03

Ⅱ.Before Route Predicate

Before Route Predicate有一个参数为datetime(其是Java8 ZonedDateTime)。该谓词匹配在指定日期时间之前发生的请求。
例如如下配置:

spring:
  cloud:
    gateway:
      routes:
        - id: payment_route          # id  保证唯一性
          uri: lb://CLOUD-PROVIDER-SERVICE    #匹配后提供服务的路由地址
          predicates:
            - Before=2021-05-24T11:22:43.136+08:00[Asia/Shanghai]

2021-05-24 11:22 之前的请求都能够访问,这个时间之后访问会404

Ⅲ.Between Route Predicate

Between Route Predicate有两个参数,datetime1和datetime2 (其是Java8 ZonedDateTime)。该谓词匹配在该时间段发生的请求。
例如如下配置:

spring:
  cloud:
    gateway:
      routes:
        - id: payment_route          # id  保证唯一性
          uri: lb://CLOUD-PROVIDER-SERVICE    #匹配后提供服务的路由地址
          predicates:
            - Between=2021-03-24T11:22:43.136+08:00[Asia/Shanghai], 2021-05-24T11:22:43.136+08:00[Asia/Shanghai]

2021-03-24 11:22 到2021-05-24 11:22之间的请求都能够访问,不在这个时间段内访问会404

Ⅳ.Cookie Route Predicate

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

spring:
  cloud:
    gateway:
      routes:
        - id: payment_route          # id  保证唯一性
          uri: lb://CLOUD-PROVIDER-SERVICE    #匹配后提供服务的路由地址
          predicates:
            - Cookie=username, thh

curl 测试

不携带Cookie

springGateway 传递真实IP spring gateway tcp 网关_服务网关_04


携带Cookie

springGateway 传递真实IP spring gateway tcp 网关_Cloud_05

Ⅴ.Header Route Predicate

Header Route Predicate 需要两个参数,报头name和一个regexp(其是Java正则表达式)。该谓词与具有给定名称的标头匹配,该标头的值与正则表达式匹配。
例如如下配置:

spring:
  cloud:
    gateway:
      routes:
        - id: payment_route          # id  保证唯一性
          uri: lb://CLOUD-PROVIDER-SERVICE    #匹配后提供服务的路由地址
          predicates:
            - Header=X-Request-Id, \d+

curl测试:
curl http://localhost:9527/payment/getServer -H "X-Request-Id:123"匹配成功
curl http://localhost:9527/payment/getServer -H "X-Request-Id:hello"会出现404

Ⅵ.Host Route Predicate

Host Route Predicate需要一个参数:主机名的列表patterns。该模式是带有.分隔符的Ant样式的模式。谓词与Host匹配模式的标头匹配。
例如如下配置:

spring:
  cloud:
    gateway:
      routes:
        - id: payment_route          # id  保证唯一性
          uri: lb://CLOUD-PROVIDER-SERVICE    #匹配后提供服务的路由地址
          predicates:
            - Host=**.somehost.org

curl测试:
curl http://localhost:9527/payment/getServer -H "Host:www.somehost.org"匹配成功
curl http://localhost:9527/payment/getServer 会出现404

Ⅶ.Method Route Predicate

Method Route Predicate需要methods的参数,它是一个或多个参数:HTTP方法来匹配。
例如如下配置:

spring:
  cloud:
    gateway:
      routes:
        - id: payment_route          # id  保证唯一性
          uri: lb://CLOUD-PROVIDER-SERVICE    #匹配后提供服务的路由地址
          predicates:
            - Method=GET,POST

方法是GET,POST允许访问,否则404

Ⅷ.Path Route Predicate

Path Route Predicate 接收一个匹配路径的参数来判断是否走路由。
例如如下配置:

spring:
  cloud:
    gateway:
      routes:
        - id: payment_route          # id  保证唯一性
          uri: lb://CLOUD-PROVIDER-SERVICE    #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/getServer/**

curl http://localhost:9527/payment/getServer/1 访问成功
curl http://localhost:9527/payment/getServer/xx 访问成功
curl http://localhost:9527/payment/aa/xx 访问失败

Ⅸ.Query Route Predicate

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

spring:
  cloud:
    gateway:
      routes:
        - id: payment_route          # id  保证唯一性
          uri: lb://CLOUD-PROVIDER-SERVICE    #匹配后提供服务的路由地址
          predicates:
            - Query=username, \d+

curl http://localhost:9527/payment/getServer?username=1 访问成功
curl http://localhost:9527/payment/getServer?username=-1 访问失败
以上这些可以组合使用 如:

spring:
  cloud:
    gateway:
      routes:
        - id: payment_route          # id  保证唯一性
          uri: lb://CLOUD-PROVIDER-SERVICE    #匹配后提供服务的路由地址
          predicates:
            - Query=username, \d+
            - Path=/payment/getServer/**     #断言   路径相匹配进行路由
            - Before=2021-05-24T11:22:43.136+08:00[Asia/Shanghai]

7.Gateway自定义过滤器

内置过滤器:移步官网,主要是太多了,不是我懒(T_T),主要掌握下自定义过滤器。

实现自定义的Gateway Filter,需要GatewayFilter、Ordered两个接口

@Component
@Slf4j
public class MyLogGatewayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("*****************come in MyLogGatewayFilter"+new Date());
        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        if(StringUtils.isEmpty(uname)){
            log.info("非法用户");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

测试 案例比较简单,就是判断下是否携带uname这个参数

springGateway 传递真实IP spring gateway tcp 网关_spring_06


写作不易,加个关注呗求关注、求点赞!

springGateway 传递真实IP spring gateway tcp 网关_正则表达式_07