Spring Cloud GateWay 服务网关

一,简单的示例 入门

参考地址:

https://cloud.spring.io/spring-cloud-gateway/reference/html/

http://www.ityouknow.com/spring-cloud

1.1 pom.xml

使用 Spring Cloud Finchley 版本,Finchley 版本依赖于 Spring Boot 2.0.6.RELEASE。

 <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.0.6.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
  </parent><dependencyManagement>
      <dependencies>
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-dependencies</artifactId>
              <version>Finchley.SR2</version>
              <type>pom</type>
              <scope>import</scope>
          </dependency>
      </dependencies>
  </dependencyManagement>

项目需要使用的依赖包

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

Spring Cloud Gateway 是使用 netty+webflux 实现因此不需要再引入 web 模块。

1.2 Spring Cloud Gateway 网关路由有两种配置方式:

1.2.1 第一种如下在配置文件 yml 中配置

入门application.yml配置

  
  server:
    port: 8083
  spring:
    cloud:
      gateway:
        routes:
        - id: 1
          uri: http://www.baidu.com
          predicates:
          - Path=/spring-cloud

各字段含义如下:

  • id:我们自定义的路由 ID,保持唯一

  • uri:目标服务地址

  • predicates:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。

  • filters:过滤规则,本示例暂时没用。

上面这段配置的意思是,配置了一个 id 为 1的路由规则,当访问地址 http://localhost:8083/spring-cloud时会自动转发到地址:http://www.ityouknow.com/spring-cloud。配置完成启动项目即可在浏览器访问进行测试,当我们访问地址http://localhost:8083/spring-cloud 时会展示页面展示如下:

1.2.2 第二种通过@Bean自定义 RouteLocator,如下在启动类 GateWayApplication 中添加方法 customRouteLocator() 来定制转发规则。
  
  @SpringBootApplication
  ​
  public class App {
  ​
      public static void main( String[] args ){
  ​
          SpringApplication.run(App.class, args);
  ​
      }
      @Bean
      public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
          return builder.routes()
              .route("2", r -> r.path("/about")
                      .uri("http://ityouknow.com"))
              .build();
      }
  }

上面配置了一个 id 为2 的路由,当访问地址http://localhost:8083/about时会自动转发到地址:http://www.ityouknow.com/about和上面的转发效果一样,只是这里转发的是以项目地址/about格式的请求地址。

二.通过时间匹配

在 Spring Cloud Gateway 中 Spring 利用 Predicate 的特性实现了各种路由匹配规则,有通过 Header、请求参数等不同的条件来进行作为条件匹配到对应的路由。网上有一张图总结了 Spring Cloud 内置的几种 Predicate 的实现。

2.1 Predicate 支持设置一个时间,在请求进行转发的时候,可以通过判断在这个时间之前或者之后进行转发。比如我们现在设置只有在2019年12月20日才会转发到百度的网站,在这之前不进行转发,我就可以这样配置:

  
  server:
    port: 8083
  spring:
    cloud:
      gateway:
        routes:
        - id: 3
          uri: http://www.baidu.com
          predicates:
          - After=2019-12-20T06:06:06+08:00[Asia/Shanghai] 

Spring 是通过 ZonedDateTime 来对时间进行的对比,ZonedDateTime 是 Java 8 中日期时间功能里,用于表示带时区的日期与时间信息的类,ZonedDateTime 支持通过时区来设置时间,中国的时区是:Asia/Shanghai

After Route Predicate 是指在这个时间之后的请求都转发到目标地址。上面的示例是指,请求时间在 2019年12月20日6点6分6秒之后的所有请求都转发到地址http://baidu.com+08:00是指时间和UTC时间相差八个小时,时间地区为Asia/Shanghai

添加完路由规则之后,访问地址http://localhost:8083会自动转发到http://baidu.com

2.2 Before Route Predicate 刚好相反,在某个时间之前的请求的请求都进行转发。我们把上面路由规则中的 After 改为 Before,如下:

 
  server:
    port: 8083
  spring:
    cloud:
      gateway:
        routes:
        - id: 3
          uri: http://www.ityouknow.com
          predicates:
          - Before=2019-12-10T11:06:06+08:00[Asia/Shanghai] 

就表示在这个时间之前可以进行路由,在这时间之后停止路由,修改完之后重启项目如果当前时间已经过了设置时间再次访问地址http://localhost:8083,页面会报 404 没有找到地址。

2.4 除过在时间之前或者之后外,Gateway 还支持限制路由请求在某一个时间段范围内,可以使用 Between Route Predicate 来实现。

server:
  port: 8083
spring:
  cloud:
    gateway:
      routes:
      - id: 3
        uri: http://www.ityouknow.com
        predicates:
        - Between=2018-12-20T11:06:06+08:00[Asia/Shanghai], 2019-12-10T12:06:06+08:00[Asia/Shanghai]

这样设置就意味着在这个时间段内可以匹配到此路由,超过这个时间段范围则不会进行匹配。通过时间匹配路由的功能很酷,可以用在限时抢购的一些场景中。 以上是只会匹配到2019年12月10日11点6分6秒到2019年12月10日12点6分6秒之间的请求,访问地址:http://localhost:8083

三.通过 Cookie 匹配

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

  server:
    port: 8083
  spring:
    cloud:
      gateway:
        routes:
        - id: 5
          uri: http://www.baidu.com
          predicates:
          - Cookie=ityouknow, kee.es

使用 curl 测试,命令行输入:

   curl 192.168.1.206:8083 --cookie "ityouknow=kee.es"

则会返回页面代码,如果cookie的值或者name对不上--cookie "ityouknow=kee.e",后台会报 404 错误。

四.通过 Header 属性匹配

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

  server:
    port: 8083
  spring:
    cloud:
      gateway:
        routes:
        - id: 5
          uri: http://www.baidu.com
          predicates:
          - Header=X-Request-Id, d+

d+表示一到多个数字 ,就是正则表达式里的用法

使用 curl 测试,命令行输入:

  
  curl 192.168.1.206:8083 -H "X-Request-Id:666"

则返回页面代码证明匹配成功。将参数-H "X-Request-Id:666"改为-H "X-Request-Id:hello"再次执行时返回404证明没有匹配。

五.通过 Host 匹配

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

  server:
    port: 8083
  spring:
    cloud:
      gateway:
        routes:
        - id: 5
          uri: http://www.baidu.com
          predicates:
          - Host=**.baidu.com

使用 curl 测试,命令行输入:

curl 192.168.1.206:8083 -H "Host:test5564.baidu.com"

经测试以上 host 以.baidu.com结尾的均可匹配到 host_route 路由,去掉 host 参数则会报 404 错误。

六.通过请求方式匹配(POST、GET、PUT、DELETE)

  
  server:
    port: 8083
  spring:
    cloud:
      gateway:
        routes:
        - id: 5
          uri: https://www.baidu.com
          predicates:
          - Method=GET

使用 curl 测试,命令行输入:

  
# curl 默认是以 GET 的方式去请求
curl 192.168.1.206:8083

测试返回页面代码,证明匹配到路由,

以 POST 的方式请求测试, 返回 404 没有找到,证明没有匹配上路由

七.通过请求路径匹配

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

  
  server:
    port: 8083
  spring:
    cloud:
      gateway:
        routes:
        - id: 7
          uri: http://www.baidu.com
          predicates:
          - Path=/hadoop/{segment}

如果请求路径符合要求,则此路由将匹配,例如:/foo/1 或者 /foo/bar。

使用 curl 测试,命令行输入:

  
http://192.168.1.206:8083/hadoop/hello
  http://192.168.1.206:8083/hadoop/6969
  curl http://192.168.1.206:8083/had/6969

经过测试第一和第二条命令可以正常获取到页面返回值,最后一个命令报404,证明路由是通过指定路由来匹配

八.通过请求参数匹配

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

8.1 如下这样配置,只要请求中包含 token属性的参数即可匹配路由。

  
  server:
    port: 8083
  spring:
    cloud:
      gateway:
        routes:
        - id: 7
          uri: http://www.baidu.com
          predicates:
          - Query=token

浏览器测试:

  https://www.baidu.com/?token=12

 

8.2 指定参数

  
  server:
    port: 8083
  spring:
    cloud:
      gateway:
        routes:
        - id: 7
          uri: http://www.baidu.com
          predicates:
          - Query=token,1_grand

浏览器测试:

  
  http://localhost:8083/?token=1_grand 

要请求中包含 token属性的参数且参数的值只能是1_grand即可匹配路由,还可以正则的方式设置。

九.通过请求 ip 地址进行匹配

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

ipv4的子网掩码是:0~32之间

  server:
    port: 8083
  spring:
    cloud:
      gateway:
        routes:
        - id: 7
          uri: http://192.168.1.206:8081
          predicates:
          - RemoteAddr=192.168.1.206/32

自己写了个测试项目:

  package com.web.kds.hadoop_kafka.Controller;
  ​
  import java.io.IOException;
  import javax.servlet.http.HttpServletResponse;
  import org.springframework.web.bind.annotation.RequestMapping;
  import org.springframework.web.bind.annotation.RestController;
  import lombok.extern.slf4j.Slf4j;
  ​
  @Slf4j
  @RestController
  @RequestMapping("/TestCrolller")
  public class TestCrolller {
  ​
      @RequestMapping("/testfile")
      public void testfile(HttpServletResponse rps,String str) {
          rps.setContentType("application/json; charset=UTF-8");
          try {
              log.info(""+str);
              rps.getWriter().print(""+str);
          } catch (IOException e) {
              e.printStackTrace();
          }
          
      }
      @RequestMapping("/file")
      public void file(HttpServletResponse rps,String str) {
          rps.setContentType("application/json; charset=UTF-8");
          try {
              log.info(""+str);
              rps.getWriter().print(""+str);
          } catch (IOException e) {
              e.printStackTrace();
          }
          
      }
  }

浏览器测试,将此地址设置为本机的 ip 地址进行测试:

  http://192.168.1.206:8083/hadoop_kafka/TestCrolller/testfile?str=6669999

十.组合使用

相同的Predicate也可以配置多个,请求的转发是必须满足所有的Predicate后才可以进行路由转发,组合使用示例如下所示:

  server:
    port: 8083
  spring:
    cloud:
      gateway:
        routes:
        - id: 8
          uri: http://192.168.1.206:8081
          predicates:
          - RemoteAddr=192.168.1.206/28
          - Query=token,hello
          - Query=str
          - Method=GET
          - RemoteAddr=192.168.1.56/24

以上配置测试时需满足以下3个条件:

ip:必须是192.168.1.206或者192.168.1.56

Query:必须有token和str属性,且token的值还只能是“hello”

Method:请求方式必须是GET请求

浏览器测试:

 http://192.168.1.206:8083/hadoop_kafka/TestCrolller/file?token=hello&str=6585575

总结:

一个请求满足多个路由的谓词条件时,请求只会被首个成功匹配的路由转发 。

Spring Cloud Gateway 使用非常的灵活,可以根据不同的情况来进行路由分发,在实际项目中可以自由组合使用。

原文地址:https://www.cnblogs.com/KdeS/p/12024109.html