目录
前言
在上面相关dubbo源码专栏中我们对dubbo rpc模块的服务发布做了分析(此处并未涉及服务注册原理和服务获取原理),这篇博文我们来分析一下dubbo rpc模块中服务调用的一次逻辑分析,首先在之前的博文dubbo源码解析(四) api配置之服务消费者 我们以api编码的形式进行了服务调用并分析了相关逻辑,最终分析聚焦到了createProxy方法 下面我们就继续该方法往后探究。
1、createProxy()
该方法我们之前已经分析过,这次的分析是基于后面探究服务调用模块进行的入口分析,会省略部分代码
private T createProxy(Map<String, String> map) {
//省略本地inIvm调用、点对点调用 注册中心调用获取相关的url逻辑
//。。。
//1、注册中心单个 直接获取对应的Invoker(服务发布和调用的核心对象)
if (urls.size() == 1) {
invoker = refprotocol.refer(interfaceClass, urls.get(0));
} else {
//对于多个注册中心 则不同的注册中心创建一个Invoker 添加到
List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
URL registryURL = null;
for (URL url : urls) {
invokers.add(refprotocol.refer(interfaceClass, url));
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
registryURL = url; // use last registry url
}
}
//2、对于多个Invoker 则通过Cluster(FailoverCluster失败重试)包装成一个Invoker
if (registryURL != null) { // registry url is available
// use AvailableCluster only when register's cluster is available
URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME);
invoker = cluster.join(new StaticDirectory(u, invokers));
} else { // not a registry url
invoker = cluster.join(new StaticDirectory(invokers));
}
}
//省略服务可用调用检测 如果设置 check=false 则不尽兴服务可用检测
//。。。
//3、创建代理对象
return (T) proxyFactory.getProxy(invoker);
}
上述创建代理过程可以分成三部分
- 通过Protocol的refer()获取对应调用对象invoker(在之前的博文中我们介绍过该对象 服务发布和服务调用都会创建该对象)
- 对于多注册中心还需要join()将多次创建的invoker包装成失败重试的invoker
- 服务调用基于invoker通过getProxy()创建代理对象供给我们调用
下面针对上面三个部分我们来分析一下
2、refer()方法
通过dubbo的spi最终实现类为DubboProtocol的refer()方法
public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException {
//根据条件获取更高效的序列化机制
optimizeSerialization(url);
//创建rpc服务调用的Invoker对象
//构造函数需要四个函数嗲用的接口class,dubbo对应的URL,ExchangeClient为服务远程调用底层通信的客户端
//invokers集合 用于该invoker销毁的时候移除该invoker
DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
//所有创建的invoker都统一在该集合中维护
invokers.add(invoker);
return invoker;
}
该方法很简单,我们需要关注是创建DubboInvoker是干什么,该类是我们进行远程调用的核心对象,其中通过ExchangeClient(底层远程通信调用),其中在远程调用过程中doInvoke()方法会通过ExchangeClient进行request请求,ExchangeClient客户端获取通过getClient