美文网首页
spring-cloud-gateway之handler

spring-cloud-gateway之handler

作者: Lance_Xu | 来源:发表于2019-04-25 16:19 被阅读0次

    引言

    本篇文字主要讲解spring-cloud-gateway的handler部分,参考官方的gateway处理流程图可以知道handler是gateway的核心控制部分,其控制着request在gateway的整个生命周期。我们可以看到,一个请求由Client发出,被spring-web-server监听,经过gateway-handler-mapping之后请求便进入了gateway部分的代码实现部分,也就表明gateway是通过Gateway Web Hnadler来与web框架交接工作的。那么本节的重点则用于讲解handler的工作交接部分以及如何疏通整个工作流的,扮演这个交接工作角色的是FilteringWebHandler,实现web server的WebHandler接口。

    FilteringWebHandler | loadFilters(List<GlobalFilter> filters)

    关注final List<GatewayFilter> globalFilters的初始化,会将Configuration注入的GlobalFilter bean初始化至globalFilters;这里有两个目标转换类,在loadFilters方法中map函数对每一个GlobalFilter做包装转换,对于实现了Ordered接口最终转换出OrderedGatewayFilter,没有排序的则转换出GatewayFilterAdapter;两个目标类均是GatewayFilter接口的实现类,GatewayFilterAdapter是FilteringWebHandler的私有嵌套类,理想情况不应该存在不实现Ordered接口的全局过滤器;而OrderedGatewayFilter位于filter包下,与GlobalFilter在同一包下声明,仅仅是对GatewayFilterAdapter的包装,将其GatewayFilterAdapter和order映射到字段。

    FilteringWebHandler

    这里的loadFilters加载的是全局过滤器,与RouteDefinitionRouteLocator中的loadFilters函数不同,RouteDefinitionRouteLocator中是加载的配置的gatewayFilter,即每次请求都需要根据Route和过滤器工厂集合来加载一次,而全局过滤器的加载只发生在进程启动时的一次性加载行为,但是最终加载结果类型一样都是OrderedGatewayFilter类型。

    GatewayFilterAdapter OrderedGatewayFilter

    FilteringWebHandler | handle(ServerWebExchange exchange)

    handle方法处理一个来自web server(WebFlux)的http(web server将一个请求的request和response抽象成一个ServerWebExchange)请求,首先在exchange的attributes中获取当前请求配置或者代码预先设置的gatewayFilters,然后与当前全局过滤器转换出来的gatewayFilter进行组合,最后new一个GatewayFilterChain来对exchange过滤。

    GatewayFilterChain处理过程

    RoutePredicateHandlerMapping

    RoutePredicateHandlerMapping两个重要属性,一个是FilteringWebHandler;一个是RouteLocator接口的实现,默认是CachingRouteLocator。

    webHandler就是代理了FilteringWebHandler的处理能力,调用其handle函数处理请求的ServerWebExchange。

    handler模块处理request的入口是getHandlerInternal函数,主要逻辑在lookupRoute(ServerWebExchange exchange)方法中,为每一个请求分配路由,这里并没有将路由作为返回结果,而是将其set进attributes属性集合中。

    路由匹配逻辑触发函数

    从方法逻辑处分析,首先调用了CachingRouteLocator的getRoutes()获取当前内存中所有已存在的Route集合,然后有序遍历concatMap()中通过filterWhen来使用每一个Route的predicate(AsyncPredicate)来匹配当前的request,这个predicate是一个函数接口实现,其中and操作符将多个配置断言进行聚合操作的,这部分可以参考对Route部分的讲解。

    路由断言工厂

    gateway路由断言

    在spring-cloud-gateway的架构设计中,将路由设计为spring-webflux的一部分,对于webflux mapping的请求进行匹配;在此基础上gateway内置了许多的路由断言,均位于handler包的predicate下;主要用于断言匹配Http请求的不同属性,通过断言组合来实现多属性匹配,断言作用发生于filter之前,在Exchange进入Filter之前对请求属性做处理匹配,所以断言仅仅对于request有效。

    从断言的命名可以明白大部分的断言作用,其实在使用过程中,大部分断言应用并不广泛,正常情况下都会配置PathRoutePredicateFactory断言来断言区分path,其他的用于与其组合作用于某个下游服务或者绝对路由设置。下面图片列举出接口-抽象类-实现类的关系图,与GatewayFilter过滤器工厂类继承依赖关系极度相似。

    接口-类

    对于每一个Route的定义中,均有相应的predicate声明,可以在配置文件或者代码中进行配置。

    AfterRoutePredicateFactory

    AfterRoutePredicateFactory断言用于断言请求发生时间,配置参数只有一个datetime的String类型参数,在GatewayAutoConfiguration中注入,匹配配置时间之后的所有请求,在一些预热活动等场景可以配合其他断言来使用。

    BeforeRoutePredicateFactory

    BeforeRoutePredicateFactory与AfterRoutePredicateFactory对应,匹配配置时间之前的所有请求,能够与其他比如Path断言组合使用。

    配置示例

    BetweenRoutePredicateFactory

    BetweenRoutePredicateFactory是BeforeRoutePredicateFactory和AfterRoutePredicateFactory的组合体。

    Between配置示例

    CloudFoundryRouteServiceRoutePredicateFactory

    CloudFoundryRouteServiceRoutePredicateFactory官方并没有作使用说明,从代码提交上看来是配合HeaderRoutePredicateFactory使用,用于对request进行forward的,目前看来应用场景并不明确。

    CookieRoutePredicateFactory

    CookieRoutePredicateFactory断言,用于匹配指定Cookie的请求,结合官方说明可知其意图在过滤指定的请求;比如配置过滤不同设备端的web请求等场景。

    image.png image.png

    HeaderRoutePredicateFactory

    HeaderRoutePredicateFactory是Http Header层的断言,匹配指定header参数,同时也可以指定参数所匹配的表达式,没有进行实际应用过。

    HostRoutePredicateFactory

    HostRoutePredicateFactory配置指定Host模式的请求(比如二级域名的正则匹配),并将匹配结果以键值对形式放入attributes属性集合中。

    MethodRoutePredicateFactory

    MethodRoutePredicateFactory很好理解,即匹配指定Method的请求,否则被忽略,如果一个路由只允许某些Http方法的请求,可以使用此配置,来限制不合法的请求。

    PathRoutePredicateFactory

    PathRoutePredicateFactory是断言中应用最广泛的,也是路由匹配的核心组件,根据请求的Uri进行模式匹配区分路由的。

    QueryRoutePredicateFactory

    QueryRoutePredicateFactory作用于请求的query参数,可以用于限制某些请求必要的query参数。

    ReadBodyPredicateFactory

    ReadBodyPredicateFactory个人觉得不是一个实用的断言,可以参考Filter中ModifyBody部分的实现,涉及异步流的修改。

    RemoteAddrRoutePredicateFactory

    RemoteAddrRoutePredicateFactory断言可以过滤掉非指定ip地址段的请求;个人觉得可以写一个ExcludeRemoteAddrRoutePredicateFactory断言,用于拒绝指定ip的请求,或者从黑名单中匹配拒绝,粗略的防止hack攻击。

    WeightRoutePredicateFactory

    WeightRoutePredicateFactory权重路由,可以用于恢复发布或者AB test场景,互联网应用中常见的需求,这个断言需要集成WeightCalculatorWebFilter过滤器来起作用。

    具体配置可以参考:Canary-test using Spring Cloud Gateway

    Sumarry

    spring-cloud-gateway中predicate是过滤匹配请求的第一步,主要作用是为每个请求精准匹配出其路由,其中关键精彩实现部分在于作者合理利用函数式接口实现类AsyncPredicate类将多个predicate进行了聚合操作,这是值得Java编程学习的。

    相关文章

      网友评论

          本文标题:spring-cloud-gateway之handler

          本文链接:https://www.haomeiwen.com/subject/zpuzgqtx.html