上一篇文章分析了route、predicate和filter的自动装配,但是还不清楚SCG(Spring Cloud Gateway简称)是如何把三个组件联系起来的,也不知道predicate和filter是如何做选择的,今天带着这些疑问,我们一起从源码中找出答案。
1. 请求分发
SCG是通过DispatcherHandler来做请求分发的,所有的请求会被拦截到这个类的handle方法做处理,其调用链大概是:
DispatcherHandler -->RoutePredicateHandlerMapping --> FilteringWebHandler
显然,这样请求就把predicate和filter联系起来了,具体整合代码如下:
public Mono<Void> handle(ServerWebExchange exchange) {
if (this.handlerMappings == null) {
return createNotFoundError();
}
return Flux.fromIterable(this.handlerMappings)
// 下面这行代码会进入RoutePredicateHandlerMapping,然后找到匹配的路由。默认会加载6个mapping
.concatMap(mapping -> mapping.getHandler(exchange))
// 上面用了concatMap顺序遍历handlerMapping,取到所有的handler后调用下面next方法
// 只会用第一个取到的handler,一般情况下不是每个handlerMapping都能取到handler
.next()
.switchIfEmpty(createNotFoundError())
// 下面这行代码进入FilteringWebHandler的handle方法
.flatMap(handler -> invokeHandler(exchange, handler))
.flatMap(result -> handleResult(exchange, result));
}
加载的6个handlerMapping:
因为filter是跟route绑定的,所以RoutePredicateHandlerMapping匹配到的route要传递到filter handler,源码中是通过会话的attributes实现的,后面代码分析会看到。
2. predicate的选择
上面代码的mapping.getHandler(exchange)最终会调用RoutePredicateHandlerMapping类的getHandlerInternal方法,然后调用lookupRoute方法。96行可以看到,最后选择的route放到了请求的attributes里。
在lookupRoute方法的131,134,152行打上断点,可以从128行那里看到所有加载的route信息。SCG是通过遍历路由列表(通过order升序排列)来选择路由的,追踪134行的执行可以看到具体的选择逻辑,由于容器中有多个predicate工厂,这里就不贴代码分析了。152行是最后选择成功的路由。
3. 执行filter
选中route后,请求会进入FilteringWebHandler的handle方法,76行看到从attributes取出route,然后获取绑定在route的filter,79行获取10个默认加载的全局filter,接着做合并和排序,最后调执行每个filter的逻辑。执行filter这里看估计是用了责任链的模式,后面文章做分析。
10个默认加载的全局filter:
org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter
org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter
org.springframework.cloud.gateway.filter.NettyWriteResponseFilter
org.springframework.cloud.gateway.filter.ForwardPathFilter
org.springframework.cloud.gateway.filter.GatewayMetricsFilter
org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter
org.springframework.cloud.gateway.filter.LoadBalancerClientFilter
org.springframework.cloud.gateway.filter.WebsocketRoutingFilter
org.springframework.cloud.gateway.filter.NettyRoutingFilter
org.springframework.cloud.gateway.filter.ForwardRoutingFilter
4. 总结
这篇文章梳理了请求和route,predicate和filter的关系,回应了文章开头的疑问。
待学习:
- 继续研究请求是如何进来,最后又是如何处理完。
- 学习filter的处理逻辑,确认是否责任链模式。