开发者社区> 程序员果果~> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Spring Cloud Gateway 之 Predict

简介: 在之前的文章的Spring Cloud Gateway初体验中,大家已经对Spring Cloud Gateway的功能有一个初步的认识,网关作为一个系统的流量的入口,有着举足轻重的作用。
+关注继续查看

文章首发于公众号《程序员果果》
地址:https://mp.weixin.qq.com/s/2twx-aCEM2GXluDUIubGZg

Spring Cloud gateway工作流程

在之前的文章的Spring Cloud Gateway初体验中,大家已经对Spring Cloud Gateway的功能有一个初步的认识,网关作为一个系统的流量的入口,有着举足轻重的作用,通常的作用如下:

  • 协议转换,路由转发
  • 流量聚合,对流量进行监控,日志输出
  • 作为整个系统的前端工程,对流量进行控制,有限流的作用
  • 作为系统的前端边界,外部流量只能通过网关才能访问系统
  • 可以在网关层做权限的判断
  • 可以在网关层做缓存

Spring Cloud Gateway作为Spring Cloud框架的第二代网关,在功能上要比Zuul更加的强大,性能也更好。随着Spring Cloud的版本迭代,Spring Cloud官方有打算弃用Zuul的意思。在笔者调用了Spring Cloud Gateway的使用和功能上,Spring Cloud Gateway替换掉Zuul的成本上是非常低的,几乎可以无缝切换。Spring Cloud Gateway几乎包含了zuul的所有功能。

如上图所示,客户端向Spring Cloud Gateway发出请求。 如果Gateway Handler Mapping确定请求与路由匹配(这个时候就用到predicate),则将其发送到Gateway web handler处理。 Gateway web handler处理请求时会经过一系列的过滤器链。 过滤器链被虚线划分的原因是过滤器链可以在发送代理请求之前或之后执行过滤逻辑。 先执行所有“pre”过滤器逻辑,然后进行代理请求。 在发出代理请求之后,收到代理服务的响应之后执行“post”过滤器逻辑。这跟zuul的处理过程很类似。在执行所有“pre”过滤器逻辑时,往往进行了鉴权、限流、日志输出等功能,以及请求头的更改、协议的转换;转发之后收到响应之后,会执行所有“post”过滤器的逻辑,在这里可以响应数据进行了修改,比如响应头、协议的转换等。

在上面的处理过程中,有一个重要的点就是讲请求和路由进行匹配,这时候就需要用到predicate,它是决定了一个请求走哪一个路由。

Predicate 介绍

Predicate 来源于 Java 8,是 Java 8 中引入的一个函数,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。

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

说白了 Predicate 就是为了实现一组匹配规则,方便让请求过来找到对应的 Route 进行处理,接下来我们接下 Spring Cloud GateWay 内置几种 Predicate 的使用。

Predicate 实战

通过时间匹配

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

spring:
  cloud:
    gateway:
      routes:
        - id: after_route
          uri: http://httpbin.org
          predicates:
          - After=2018-02-15T00:00:00+08:00[Asia/Shanghai]

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

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

添加完路由规则之后,访问地址 http://127.0.0.1:8080/get 会自动转发到 http://httpbin.org/get

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

spring:
  cloud:
    gateway:
      routes:
        - id: before_route
          uri: http://httpbin.org
          predicates:
          - Before=2019-02-15T00:00:00+08:00[Asia/Shanghai]

就表示在2019-02-14之前可以进行路由,在这时间之后停止路由,修改完之后重启项目再次访问地址http://localhost:8080,页面会报 404 没有找到地址。

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

spring:
  cloud:
    gateway:
      routes:
        - id: between_route
          uri: http://httpbin.org
          predicates:
          - Between=2018-02-14T00:00:00+08:00[Asia/Shanghai], 2019-02-16T23:59:59+08:00[Asia/Shanghai]

这样设置就意味着在 2019-02-14到2019-02-16 时间段内可以匹配到此路由,超过这个时间段范围则不会进行匹配。通过时间匹配路由的功能很酷,可以用在限时抢购的一些场景中。

通过 Cookie 匹配

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

spring:
  cloud:
    gateway:
      routes:
        - id: cookie_route
          uri: http://httpbin.org:80
          predicates:
          - Cookie=name, chengxuyuanguoguo

上面的配置中,请求带有cookie名为name, cookie值为chengxuyuanguoguo 的请求将都会转发到uri为 http://httpbin.org的地址上。

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

curl http://127.0.0.1:8080/get --cookie "name=chengxuyuanguoguo"

则有正确返回,如果去掉--cookie "name=chengxuyuanguoguo",没有匹配成功,出现 404 错误。

通过 Header 属性匹配

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

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

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

curl http://127.0.0.1:8080/get  -H "X-Request-Id:111111" 

则正常返回,将参数 "X-Request-Id:111111" 改为 "X-Request-Id:xxxx" 再次执行时返回404。

通过 Host 匹配

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

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

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

curl http://127.0.0.1:8080/get  -H "Host:www.httpbin.com" 

测试上述 host 可匹配到 host_route 路由,去掉 host 参数则会报 404 错误。

通过请求方式匹配

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

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

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

curl http://127.0.0.1:8080/get

测试返回正确,证明匹配到路由,再以 POST 的方式请求测试:

curl -X POST http://127.0.0.1:8080/get

返回 404 没有找到,没有匹配上路由。

通过请求路径匹配

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

spring:
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://httpbin.org
          predicates:
            - Path=/foo/{segment}

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

curl http://127.0.0.1:8080/foo/1
curl http://127.0.0.1:8080/fee/1

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

通过请求参数匹配

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

spring:
  cloud:
    gateway:
      routes:
        - id: query_route
          uri: http://httpbin.org
          predicates:
          - Query=foo

测试发现只要请求带有 foo 参数即会匹配路由,不带 foo 参数则会报 404 错误。

通过请求 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://httpbin.org
          predicates:
          - RemoteAddr=172.16.1.73/24

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

curl http://172.17.1.73:8080/get

测试返回正确,改为请求 127.0.0.1:8080/get 则会报 404 错误。

组合使用

Predicate还可以组合在一起使用。

spring:
  cloud:
    gateway:
      routes:
        - id: group_route
          uri: http://httpbin.org
          predicates:
          - Host=**.httpbin.com
          - Header=X-Request-Id, \d+
          - Cookie=name, chengxuyuanguoguo
          - After=2019-02-15T00:00:00+08:00[Asia/Shanghai]

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

curl http://127.0.0.1:8080 -H "X-Request-Id:111111" -H "Host:www.httpbin.com" --cookie "name=chengxuyuanguoguo"

测试返回正确,错误的规则或去除一个规则,则会报 404 错误。

总结

Predict作为断言,它决定了请求会被路由到哪个router 中。在断言之后,请求会被进入到filter过滤器的逻辑,下篇文章将会介绍Spring Cloud Gateway过滤器相关的内容。

源码

https://github.com/gf-huanchupk/SpringCloudLearning/tree/master/chapter13/springcloud-gateway-predict

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Spring Boot引用配置文件
Spring Boot程序默认从application.properties或者application.yaml读取配置,如何将配置信息外置,方便配置呢?
34 0
Spring Boot 应用可视化监控,一目了然!
Spring Boot 应用可视化监控,一目了然!
196 0
Spring Boot中使用Spring Security进行安全控制
Spring Boot中使用Spring Security进行安全控制
154 0
Spring Boot 实现定时任务的 4 种方式
定时任务实现的几种方式: Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。
116 0
Spring Boot 配置文件中的花样,看这一篇足矣!
在快速入门一节中,我们轻松的实现了一个简单的RESTful API应用,体验了一下Spring Boot给我们带来的诸多优点,我们用非常少的代码量就成功的实现了一个Web应用,这是传统的Spring应用无法办到的,虽然我们在实现Controller时用到的代码是一样的,但是在配置方面,相信大家也注意到了,在上面的例子中,除了Maven的配置之后,就没有引入任何的配置。
2536 0
企业级 SpringBoot 教程 (二)Spring Boot配置文件详解
springboot采纳了建立生产就绪Spring应用程序的观点。 Spring Boot优先于配置的惯例,旨在让您尽快启动和运行。在一般情况下,我们不需要做太多的配置就能够让spring boot正常运行。
1141 0
Spring boot 通用配置文件模板
001 # =================================================================== 002 # COMMON SPRING BOOT PROPERTIES 003 # 004 # This sample file is provided as a guideline.
1616 0
Spring Boot 启动加载数据 CommandLineRunner
实际应用中,我们会有在项目服务启动的时候就去加载一些数据或做一些事情这样的需求。 为了解决这样的问题,Spring Boot 为我们提供了一个方法,通过实现接口 CommandLineRunner 来实现。
966 0
Spring Boot属性配置文件详解
相信很多人选择Spring Boot主要是考虑到它既能兼顾Spring的强大功能,还能实现快速开发的便捷。我们在Spring Boot使用过程中,最直观的感受就是没有了原来自己整合Spring应用时繁多的XML配置内容,替代它的是在pom.xml中引入模块化的Starter POMs,其中各个模块都有自己的默认配置,所以如果不是特殊应用场景,就只需要在application.properties中完成一些属性配置就能开启各模块的应用。
915 0
+关注
程序员果果~
欢迎关注公众号『 程序员果果 』分享SpringBoot、SpringCloud、Dubbo、Golang、Docker相关知识与技巧。
48
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载