Spring Cloud Gateway源码导读:
首先我们观察在引入了Spring Cloud Gateway
后自动装配都做了什么?从Spring Cloud Gateway
包下找到spring.factories
,查看EnableAutoConfiguration
项即,仔细观察后不难发现关键配置项即为GatewayAutoConfiguration
与GatewayReactiveLoadBalancerClientAutoConfiguration
(需要配合spring-cloud-loadbalancer
一起使用)。
那么我们分别来看看这两个配置类都做了什么。
GatewayAutoConfiguration
该配置类中主要装配了如下几种类型的对象:
- RouteDefinitionLocator(Properties)
- RouteDefinitionRepository(Redis、InMemory)
- RouteLocator(RouteDefinition)
- RouteRefreshListener
- HandlerMapping(RoutePredicateHandlerMapping)
- WebHandler(FilteringWebHandler)
- GlobalFilters
- Predicate Factory Beans
- GatewayFilter Factory Beans
下面我们依次介绍上述各对象的作用
RouteDefinitionLocator
可以将名称拆开看,即RouteDefinition
和Locator
,其中RouteDefinition
与Spring Beans
中的BeanDefinition
类似,从名字上也能看出其实就是用来定义Route
的,用来记录Route
的关键属性,例如Predicates
、Filters
、url
等。
而Locator
则是用来从特定的位置读取RouteDefinition
,目前Spring Cloud Gateway
默认是从Properties
来读取RouteDefinition
。读取后交给RouteLocator
实例化为Route
对象。
RouteDefinitionRepository
Spring Cloud Gateway
提供InMemory
、Redis
等的RouteDefinitionRepository
,主要用来动态添加RouteDefinition
,需要注意的是InMemory
通常在Spring Actuator
中打开routes
端点即可使用,在添加成功后需要发出RouteRefresh
事件即可更新内存中的路由。
RouteLocator
默认为RouteDefinitionRouteLocator
,主要作用是根据RouteDefinitionLocator
中返回的RouteDefinition
创建Route
对象,核心操作是将RouteDefinition
中定义的Predicate Factory
、Filter Factory
实例化,最终封装在Route
对象中,以供请求进来时筛选路由。
RouteRefreshListener
路由发生更新时需要发布RouteRefresh
事件,该监听器负责更新内存中的路由列表。
HandlerMapping
当DispatcherHandler
分发请求时调用HandlerMapping.getHandler
方法来获取HandlerAdapter
以供后续链式调用,Spring Cloud Gateway
默认是由RoutePredicateHandlerMapping
处理。在该处理器继承自AbstractHandlerMapping
,并实现抽象方法getHandlerInternal
。当有请求进来时,通过lookupRoute
寻找内存中所有的Route
,并通过路由的Predicate
寻找与当前请求相匹配的路由,将其放进exchange后,最终返回FilteringWebHandler
。
WebHandler
当DispatcherHandler
从HandlerMapping
中获取到了HandlerAdapter
后,随即立即调用HandlerAdapter
来处理请求,上述RoutePredicateHandlerMapping
返回的FilteringWebHandler
是一种WebHandler
,由SimpleHandlerAdapter
负责处理,在FilteringWebHandler
中会将Global Filters
与Route
中定义的Gateway Filters
合并,按照Order
排序后封装成DefaultGatewayFilterChain
依次后调用filter
方法。
GlobalFilters
在纯Spring Cloud Gateway
环境下存在9个全局过滤器,他们按照执行顺序分别是:
名称 | Order | 作用 |
---|---|---|
RemoveCachedBodyFilter | Integer.MIN_VALUE | |
AdaptCachedBodyGlobalFilter | Integer.MIN_VALUE + 1000 | |
NettyWriteResponseFilter | -1 | 用来写响应给客户端 |
ForwardPathFilter | 0 | 若Route中定义的uri是forward类型,则将exchange中的request修改为forward类型。 |
RouteToRequestUrlFilter | 10000 | 取出Route中定义的uri,将其设置在exchange中 |
NoLoadBalancerClientFilter | 10150 | 在GatewayNoLoadBalancerClientAutoConfiguration中定义,不使用loadBalance。 |
WebsocketRoutingFilter | Integer.MAX_VALUE - 1 | 从exchange中取出RouteToRequestUrlFilter中设置的uri,处理websocket协议下的路由 |
NettyRoutingFilter | Integer.MAX_VALUE | 从exchange中取出RouteToRequestUrlFilter中设置的uri,处理http、https协议下的路由,主要作用是创建新的httpclient,根据uri发送请求并增加request及response处理,同时超时处理也在这个位置。 |
ForwardRoutingFilter | Integer.MAX_VALUE | 如果是forward类型请求,则交给dispatcherhandler重新处理。 |
Predicate Factory Beans
内置的Predicate
工厂处理类,用来根据RouteDefinition中的配置生成对应的Predicate
。在HandlerMapping
中通过调用Predicate.test
方法匹配请求与路由。
PS.这里有个性能瓶颈,默认策略是循环遍历每一个路由的Predicate.test
方法进行匹配,当路由数量越来越多时性能急剧下降,可根据实际业务中路由的Predicate
类型进行优化。例如全都是PathRoutePredicate
时,可根据固有逻辑建立路由标识与路由的缓存,在请求进来时快速查找,找不到时由默认逻辑兜底。
GatewayFilter Factory Beans
内置的路由级别GatewayFilter
工厂处理类,用来根据RouteDefinition中的配置生成对应的GatewayFilter
。在
FilteringWebHandler
中会与GlobalFilter
合并后对请求进行处理。
GatewayReactiveLoadBalancerClientAutoConfiguration
当引入了spring-cloud-loadbalancer
后,该配置类会自动注入ReactiveLoadBalancerClientFilter
从而替代默认的NoLoadBalancerClientFilter
。当前版本的Spring Cloud Gateway
原生支持Random
、RoundRobin
两种负载策略,默认使用RoundRobin
策略。
注意,ReactiveLoadBalancerClientFilter
的Order
与NoLoadBalancerClientFilter
相同,都为10150。
ReactiveLoadBalancerClientFilter的处理流程
ReactiveLoadBalancerClientFilter
在处理时仅处理lb://
类型的uri
,其原理为从uri
中解析出的host
后,通过利用NamedContextFactory
创建一个新的以Route id
为name
的ApplicationContext
,由LoadBalancerClientConfiguration
自动注入RoundRobinLoadBalancer
到新建的ApplicationContext
中,随后通过LoadBalancer
从ServiceInstanceListSupplier
中查找出指定host
的所有实例,根据负载均衡算法选取一个示例后返回给ReactiveLoadBalancerClientFilter
,接着将实例的uri
与原有请求的uri
合并后替换exchange
中的GATEWAY_REQUEST_URL_ATTR
以供后续NettyRoutingFilter
使用。
大体上的Spring Cloud Gateway
的初始化及处理流程就是这样,至于每个Filter
的细节可以根据项目中使用到的情况来继续研读。