SpringCloud之网关高级用法

本文将对Spring Cloud GateWay 中的 Predicate 和 Filter进行讲解,因为它们是GateWay中最重要的核心功能。可以说是网关的左膀右臂。

Predicate 和 Filter 是 Spring Cloud Gateway 的核心,通过这两个功能点的灵活配置使用,Spring Cloud Gateway 的使用变得高效、简单。Predicate 的核心作用是路由选择,通过一些列的规则配置,让我们知道哪些请求可以被某个规则转发;Filter 是过滤器,在 Predicate 删选出某些请求需要转发时,Filter 负责在这些请求的执行前或者执行后做一些处理,比如安全校验、参数处理等。

Predicate是用来请求需要处理,而Filter就是对请求需要处理做一些变更。

Predicate

Predicate 是来自于JDK 8中对一个函数,Predicate接受一个输出参数,它返回对一个布尔值,可以用于接口参数的校验,判断新老数据的变化需要进行更新操作。

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

SpringCloud之网关高级用法_第1张图片
可以从上图中看到Predicate路由匹配方式是很多的。

通过时间匹配

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

spring:
  cloud:
    gateway:
      routes:
      - id: time_route
        uri: https://blog.csdn.net/qwe86314
        predicates:
          - After=2019-09-13T17:33:06+08:00[Asia/Shanghai]

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

After Route Predicate 是指在这个时间之后的请求都转发到目标地址。上面的示例是指,请求时间在 2019年9月13日17点33分6秒之后的所有请求都转发到地https://blog.csdn.net/qwe86314。+08:00 是指时间和 UTC 时间相差八个小时,时间地区为Asia/Shanghai

添加完路由规则之后,访问地址http://localhost:8080会自动转发到https://blog.csdn.net/qwe86314

其它的两个时间判断和上面类似,只需要替换对应的 predicates 值即可。

predicates:
	- After=2019-09-13T17:33:06+08:00[Asia/Shanghai]
	- Before=2019-09-13T17:33:06+08:00[Asia/Shanghai]
	- Between=2019-09-13T17:33:06+08:00[Asia/Shanghai], 2019-09-13T17:34:06+08:00[Asia/Shanghai]

通过请求方式匹配

请求方式即使页面表单的请求类型,比如:POST、GET、PUT、DELETE ,Spring Cloud Gateway 内置了 Predicate 可根据不同的请求方式来选择路由。

我们来配置这个GET方式转发:

spring:
  cloud:
    gateway:
      routes:
        - id: method_route
          uri: https://blog.csdn.net/qwe86314
          predicates:
            - Method=GET

配置完成后我们启动项目可以通过curl 命令 如: curl http://localhost:8080 当然你也可以通过这个浏览器输入地址去访问,但是特别注意的是我们这个当前的路由只能是GET,如果尝试用POST去访问,那么返回的结果就是404。

其它的请求方式只需要将Method里面的GET换成POST、PUT等其它方式就可以来。

请求路径匹配

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

我们来配置一下路由匹配:

spring:
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://cxytiandi.com
          predicates:
            - Path=/course/{segment}

当我们在浏览器地址输入http://localhost:8080/course/25 就会返回相应的页面信息,而我们输入http://localhost:8080/course/100就会返回404的页面。

请求参数匹配

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

spring:
  cloud:
    gateway:
      routes:
        - id: query_route
          uri: http://cxytiandi.com
          predicates:
            - Query=course/vipType

我们去浏览器访问:http://localhost:8080/course/vipType?=1

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

我们将 - Query=course/vipType 修改为 - Query=course/vipType,1
这样当请求中包含course/vipType并且属性值为1就会匹配到内容否则会出404,有些网站会出现跨域问题。建议在自己网站测试。

组合使用

在我们日常工作中,往往会使用多个 Predicate 来进行判断,Spring Cloud Gateway 支持同时配置多个 Predicate 条件,各种 Predicates 同时存在于同一个路由时,请求必须同时满足所有的条件才被这个路由匹配。

spring:
  cloud:
    gateway:
      routes:
       - id: mehtod_path_time
        uri: http://cxytiandi.com/course
        predicates:
        - Method=GET
        - Query=vipType,1
        - After=2019-09-14T10:16:13+08:00[Asia/Shanghai]

需要注意的是:一个请求满足多个路由条件时,请求只会被首个成功匹配的路由转发

Filter

Spring Cloud Gateway 的 Filter 的生命周期不像 Zuul 的那么丰富,它只有两个:prepost

  • PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现权限管理、安全校验、记录调试信息等。
  • POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
  • Spring Cloud Gateway 的 Filter 分为两种:GatewayFilter 与 GlobalFilter。GlobalFilter 会应用到所有的路由上,而 GatewayFilter 将应用到单个路由或者一个分组的路由上。

    GateWay Filter
    Spring Cloud Gateway 内置了 25 种 GatewayFilter 和一个 Default Filters。按照不同作用方式我们将它划分为 12 大类。

    SpringCloud之网关高级用法_第2张图片
    Global Filter
    Spring Cloud Gateway 内置了7种 GlobalFilter,比如 Netty Routing Filter、LoadBalancerClient Filter、Websocket Routing Filter 等,根据名字即可看出这些 Filter 的作用。

    多个 Global Filter 可以通过 @Order 或者 getOrder() 方法指定每个 Global Filter 的执行顺序,order 值越小,Global Filter 执行的优先级越高。

    SpringCloud之网关高级用法_第3张图片
    利用 GatewayFilter 可以修改 Http 的请求或者响应,或者根据请求或者响应做一些特殊的限制,更多时候我们会利用 GatewayFilter 做一些具体的路由配置,接下来我们通过示例来学习。

    AddRequestHeader GatewayFilter
    AddRequestHeader GatewayFilter 是匹配的请求中添加Header头相关的参数。

    我们首先创建一个普通的maven项目,然后再依次的在这个父模块下创建子模块:eureka、provider、consumer、gateway模块。然后分别注册到eureka。由于步骤很简单创建的过程我就不再阐述了。

    spring:
      application:
        name: gateway
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true
          routes:
            - id: add_request_parameter_route
              uri: lb://consumer
              filters:
                - AddRequestHeader=Content-Type, application/json
              predicates:
                - Method=POST
    server:
      port: 8083
    
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8888/eureka/
    logging:
      level:
        org.springframework.cloud.gateway: debug
    

    上面关键配置解释:

  • spring.cloud.gateway.discovery.locator.enabled,是否与服务发现组件进行结合,通过 serviceId 转发到具体的服务实例。默认为 false,设为 true 便开启通过服务中心的自动根据 serviceId 创建路由的功能。
  • spring.cloud.gateway.routes.uri=lb://consumer,配置路由转发到名为 provider 的服务消费者。
  • spring.cloud.gateway.routes.filters ,配置需要执行 Filter 的具体实现。
  • spring.cloud.gateway.routes.filters.AddRequestHeader配置请求需要的Header头
  • spring.cloud.gateway.routes.predicates,请求的删选条件, Filter 需要和 Predicate 配合使用。
  • 配置完成后我们分别启动,然后通过postman或者RestletClient Http请求工具然后访问http://localhost:8083/rest/SaveUser 然后加入Content-Type为application/json 然后添加参数然后发送,就返回了正确的结果如下:

    SpringCloud之网关高级用法_第4张图片

    SpringCloud之网关高级用法_第5张图片
    注意这里默认使用了全局过滤器 LoadBalancerClient ,当路由配置中 uri 所用的协议为 lb 时(已uri: lb://provider 为例),gateway 将使用 LoadBalancerClient 把 consumer 通过 eureka 解析为实际的主机和端口,并进行负载均衡。

    其它的 GatewayFilter 使用方式和上述方式比较类似,这里不再一一列举,使用时按照要求的语法配置即可。

    总结

    Spring Cloud Gateway 有非常强大的 Predicate 选择机制,内置的 Predicates 实现已经满足了我们绝大部分工作场景。同时 Spring Cloud Gateway 也提供了请求过程中的各种 Filters ,其中 Filter 又区分为 GatewayFilter 和 GlobalFilter,GatewayFilter 作用于特定请求,GlobalFilter 作用于全局,实际工作中我们根据需求来选择使用。

    源码地址

    github

    你可能感兴趣的:(SpringCloud)