SpringCloud-gateway之RoutePredicateFactory

SpringCloud早期整合了Netflix 公司的开源项目Zuul 1.0作为网关,但后期Zuul 推出了2.0,但 Spring Cloud 貌似没有整合计划,看了下spring-cloud-netflix-zuul引用的还是1.0的Zuul,Spring Cloud 后面推出了自己的服务网关:Spring Cloud Gateway,使用起来比 Zuul 更简单,配置更方便。

而作为一个网关,应当具备以下功能:

性能:API高可用,负载均衡,容错机制。

安全:权限身份认证、脱敏,流量清洗,后端签名(保证全链路可信调用),黑名单(非法调用的限制)。

日志:日志记录(spainid,traceid)一旦涉及分布式,全链路跟踪必不可少。

缓存:数据缓存。

监控:记录请求响应数据,api耗时分析,性能监控。

限流:流量控制,错峰流控,可以定义多种限流规则。

灰度:线上灰度部署,可以减小风险。

路由:动态路由规则。
 

要知道网关,先说明一下网关中常见的三大术语:

 1)Filter(过滤器):

和Zuul的过滤器在概念上类似,可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。过滤器为org.springframework.cloud.gateway.filter.GatewayFilter类的实例。

    2)Route(路由):

网关配置的基本组成模块,和Zuul的路由配置模块类似。一个Route模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI会被访问。

    3)Predicate(断言):

这是一个 Java 8 的 Predicate,可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。断言的输入类型是一个 ServerWebExchange。

这里我们以这段配置为例子:

server:
  port: 8081
spring:
  cloud:
    gateway:
      routes:
        - id: lb_route
          uri: https://www.baidu.com
          predicates:
            - Path=/mypath1
        - id: lb_route2
          uri: https://www.taobao.com
          predicates:
            - Path=/mypath2
            - After=2021-08-18T18:00:00+08:00[Asia/Shanghai] 
            

 这段配置的含是:配置了二个route(lb_route,lb_route2),当访问localhost:8081/mypath1会转发到https://www.baidu.com:443/mypath1,当访问localhost:8081/mypath2,且在配置的时间(此时间为UTC时间格式)之后才会转发到https://www.taobao.com:443/mypath2。

Predicate接口在JDK8中的定义:
​​​​​​​

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

  • boolean test(T t); 判断
  • Predicate<T> and(Predicate<? super T> other) 接收一个Predicate类型,也就是将传入的条件和当前条件以并且(AND)的关系组合
  • Predicate<T> or(Predicate<? super T> other)接收一个Predicate类型,也就是将传入的条件和当前条件以或(OR)的关系组合

    ​​​​​​

说白了 Predicate 就是为了实现一组匹配规则,方便让请求过来找到对应的 Route 进行处理,其实Predicate的默认实现有很多,网上有张图总结了spring cloud-gateway内置的几种实现

在这里插入图片描述

规则实例说明
Path- Path=/gate/,/rule/## 当请求的路径为gate、rule开头的时,转发到http://localhost:9023服务器上
Before- Before=2017-01-20T17:42:47.789-07:00[America/Denver]在某个时间之前的请求才会被转发到 http://localhost:9023服务器上
After- After=2017-01-20T17:42:47.789-07:00[America/Denver]在某个时间之后的请求才会被转发
Between- Between=2017-01-20T17:42:47.789-07:00[America/Denver],2017-01-21T17:42:47.789-07:00[America/Denver]在某个时间段之间的才会被转发
Cookie- Cookie=chocolate, ch.p名为chocolate的表单或者满足正则ch.p的表单才会被匹配到进行请求转发
Header- Header=X-Request-Id, \d+携带参数X-Request-Id或者满足\d+的请求头才会匹配
Host- Host=www.hd123.com当主机名为www.hd123.com的时候直接转发到http://localhost:9023服务器上
Method- Method=GET只有GET方法才会匹配转发请求,还可以限定POST、PUT等请求方式

也就是说通过简简单单的几个配置即可实现怎么多功能,那它如何实现的呢?我们来看看RoutePredicateFactory

 可以看到这是一个接口,并且被@FunctionalInterface注解修饰,被此注解修饰说明这是一个函数式接口(函数式接口的就是一个接口有且只有一个抽象方法,那么该接口就是一个函数式接口),apply是它唯一的抽象方法,我们再看看apply的具体实现类

这里我们随便点进去一个XXXRoutePredicateFactory 

 发现都是return一个GatewayPredicate,而GatewayPredicate是一个接口,它继承了Predicate,而Predicate也是一个函数式接口。

也就是通过test()方法,返回是否匹配路由条件,那它是在何时调用的test()方法进行判断的呢,来看一波gateway的请求流程图。

Spring-Cloud-Gateway请求整体流程图 

 从图中可以看到在RoutePredicateHandlerMapping的lookupRoute来匹配路由是否可用。

 首先通过routeLocator的getRoutes方法获取所有路由(读取配置文件转成路由),然后得到对应路由的predicate,然后进入apply方法,就可以看到它真正调用了对应的PathRoutePredicateFactory的test方法()

 

参考文章:

https://www.cnblogs.com/webor2006/p/8135873.html

https://www.cnblogs.com/crazymakercircle/p/11704077.html

https://www.jianshu.com/p/6ff196940b67

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值