服务调用流程源码解读
我们先来看一下官网的集群容错图,也就是整体获取到执行的invker的过程
1.通过Directort获取到当前所有的Invoker
2.通过Router获取当前可执行的(有效的)所有Invoker
3.通过LoadBalance获取当前执行的单一Invoker
4.通过Cluster策略贯穿整个流程,进行容错处理
先看一段代码:
@Autowired
private DemoService demoServiceImpl;
@GetMapping("/sayHello")
@ApiOperation(value = "/sayHello",notes = "说你好")
@ApiImplicitParam(name = "name",value = "名称",required = true,dataType = "String")
public String sayHello(String name) {
checkNotNull(name,"name is not null");
return demoServiceImpl.sayHello(name);
}
这里的demoServiceImpl 是一个代理对象,这里有服务发现的东西,需要看我第五篇文章,
所以走到demoServiceImpl.sayHello(name),代码走的是动态代理模式。进入InvokerInvocationHandler.invoke()方法,在动态代理类里,我们发现有一个invoker字段:MockClusterInvoker对象
MockClusterInvoker.invoke()方法:判断是不是配置了MOCK请求,配置了走mock模式,没有配置接着进入:FailoverClusterInvoker.invoke(),FailoverClusterInvoker继承于AbstractClusterInvoker,所以我们进入AbstractClusterInvoker.invoke()方法。
public Result invoke(final Invocation invocation) throws RpcException {
checkWhetherDestroyed();
LoadBalance loadbalance = null;
① List<Invoker<T>> invokers = list(invocation);
if (invokers != null && !invokers.isEmpty()) {
② loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl()
.getMethodParameter(invocation.getMethodName(), Constants.LOADBALANCE_KEY, Constants.DEFAULT_LOADBALANCE));
}
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
return ③ doInvoke(invocation, invokers, loadbalance);
}
这个方法里我们可以看一下标注
①这里是获取到所有有效的可执行的Invoker
②获取负载均衡的处理方式
③通过负载规则拿到Invoker并执行返回
下面我们开始介筛第一步
protected List<Invoker<T>> list(Invocation invocation) throws RpcException {
List<Invoker<T>> invokers = directory.list(invocation);
return invokers;
}
我们看到了Directort,这里调用的是 AbstractDirectory的list方法
public List<Invoker<T>> list(Invocation invocation) throws RpcException {
if (destroyed) {
throw new RpcException("Directory already destroyed .url: " + getUrl());
}
① List<Invoker<T>> invokers = doList(invocation);
List<Router> localRouters = this.routers; // local reference
if (localRouters != null && !localRouters.isEmpty()) {
for (Router router : localRouters) {
try {
if (router.getUrl() == null || router.g