Gateway源码剖析
源码分析小技巧:可以自己先画一个思维导图,把大致步骤画出来,再根据思维导图去深入到源码里面去看,不容易迷路
Gateway工作流程源码剖析
1.1 Gateway工作流程分析
前面已经学习过Gateway的工作流程,如上工作流程图,我们回顾一下工作流程:
1.2 Gateway工作流程源码
分析源码的时候对应着1.1的步骤,比较容易理解
我们首先来看一下Gateway拦截处理所有请求的入口方法HttpWebHandlerAdapter中
的handle():
上面getDelegate()方法源码如下:
我们进行Debug测试如下:
当前返回的WebHandler是ExceptionHandlingWebHandler
,而ExceptionHandlingWebHandler
的delegate是FilteringWebHandler
,而FilteringWebHandler
的delegate是delegate
是DispatcherHandler
,所有的delegate的handle()
方法都会依次执行,我们可以把断点放到DispatcherHandler.handle()
方法上:
handle()方法会调用所有handlerMappings的getHandler(exchange)
方法,而getHandler(exchange)
方法会调用getHandlerInternal(exchange)
方法:getHandlerInternal(exchange)
该方法由各个HandlerMapping
自行实现,我们可以观察下断言处理的RoutePredicateHandlerMapping
的getHandlerInternal(exchange)
方法会调用lookupRoute方法,该方法用于返回对应的路由信息:
这里的路由匹配其实就是我们项目中对应路由配置的一个一个服务的信息,这些服务信息可以帮我们找到我们要调用的真实服务:
每个Route对象如下:
Route的DEBUG数据如下:
找到对应Route后会返回指定的FilterWebHandler,如下代码:
FilterWebHandler主要包含了所有的过滤器,过滤器按照一定顺序排序,主要是order值,越小越靠前排,过滤器中主要将请求交给指定真实服务处理了,debug测试如下:
这里有RouteToRequestUrlFilter
和ForwardRoutingFilter
以及LoadBalancerClientFilter
等多个过滤器。
1.3 请求处理
这里讲的请求处理的源码并不是很完整,完整的请看思维导图中的流程
在上面FilterWebHandler中有2个过滤器,分别为RouteToRequestUrlFilter
和ForwardRoutingFilter
。
RouteToRequestUrlFilter
:根据匹配的 Route,计算请求地址得到 lb://hailtaxi-order/order/list
ForwardRoutingFilter
:转发路由网关过滤器。其根据 forward:// 前缀( Scheme )过滤处理,将请求转发到当前网关实例本地接口。
RouteToRequestUrlFilter
RouteToRequestUrlFilter源码如下:
debug调试结果如下:
从上面调试结果我们可以看到所选择的Route以及uri和routeUri和mergedUrl,该过滤器其实就是将用户请求的地址换成服务地址,换成服务地址可以用来做负载均衡。
ForwardRoutingFilter
转发路由网关过滤器。其根据 forward:// 前缀( Scheme )过滤处理,将请求转发到当前网关实例本地接口。我们调试该过滤器,可以发现执行了远程调用,代码如下:
Gateway负载均衡源码剖析
前面源码剖析主要剖析了Gateway的工作流程,我们接下来剖析Gateway的负载均衡流程。在最后的过滤器集合中有LoadBalancerClientFilter
过滤器,该过滤器是用于实现负载均衡。
2.1 地址转换
LoadBalancerClientFilter
过滤器首先会将用户请求地址转换成真实服务地址,也就是IP:端口号,源码如下:
2.2 负载均衡服务选择
上面代码的关键是choose(exchange)
的调用,该方法调用其实就是选择指定服务,这里涉及到负载均衡服务轮询调用算法等,我们可以跟踪进去查看方法执行流程。
Gateway自身已经集成Ribbon,所以看到的对象是RibbonLoadBalancerClient,我们跟踪进去接着查看:
上面方法会依次调用到getInstance()方法,该方法会返回所有可用实例,有可能有多个实例,如果有多个实例就涉及到负载均衡算法,方法调用如下图:
此时调用getServer()方法,再调用BaseLoadBalancer.chooseServer()
,这里是根据指定算法获取对应实例,代码如下:BaseLoadBalancer
是属于Ribbon的算法,我们可以通过如下依赖包了解,并且该算法默认用的是RoundRobinRule
,也就是轮循算法,如下代码: