dubbo
dubbo源码构建参考
官方文档
Provider: 暴露服务的服务提供方
Protocol 负责提供者和消费者之间协议交互数据
Service 真实的业务服务信息 可以理解成接口 和 实现
Container Dubbo的运行环境
Consumer: 调用远程服务的服务消费方
Protocol 负责提供者和消费者之间协议交互数据
Cluster 感知提供者端的列表信息
Proxy 可以理解成 提供者的服务调用代理类 由它接管 Consumer中的接口调用逻辑
Registry: 注册中心,用于作为服务发现和路由配置等工作,提供者和消费者都会在这里进行注册
Monitor: 用于提供者和消费者中的数据统计,比如调用频次,成功失败次数等信息。
启动和执行的流程如上图
提供者端启动 容器负责把Service信息加载 并通过Protocol 注册到注册中心
消费者端启动 通过监听提供者列表来感知提供者信息 并在提供者发生改变时 通过注册中心及时 通知消费端
消费方发起请求 通过Proxy模块
利用Cluster模块 来选择真实的要发送给的提供者信息
交由Consumer中的Protocol 把信息发送给提供者
提供者同样需要通过 Protocol 模块来处理消费者的信息
最后由真正的服务提供者 Service 来进行处理
调用链路
淡绿色代表了 服务生产者的范围 淡蓝色 代表了服务消费者的范围 红色箭头代表了调用的方向
- 消费者通过Interface进行方法调用 统一交由消费者端的 Proxy 通过ProxyFactory 来进行代理 对象的创建 使用到了 jdk javassist技术
- 交给Filter 这个模块 做一个统一的过滤请求
- 接下来会进入最主要的Invoker调用逻辑
通过Directory 去配置中新读取信息 最终通过list方法获取所有的Invoker
通过Cluster模块 根据选择的具体路由规则 来选取Invoker列表
通过LoadBalance模块 根据负载均衡策略 选择一个具体的Invoker 来处理我们的请求
如果执行中出现错误 并且Consumer阶段配置了重试机制 则会重新尝试执行 - 继续经过Filter 进行执行功能的前后封装 Invoker 选择具体的执行协议
- 客户端 进行编码和序列化 然后发送数据
- 到达Provider中的 Server 在这里进行 反编码 和 反序列化的接收数据
- 使用Exporter选择执行器
- 交给Filter 进行一个提供者端的过滤 到达 Invoker 执行器
- 通过Invoker 调用接口的具体实现 然后返回
Business 业务逻辑层
service 业务层 包括我们的业务代码 比如 接口 实现类 直接面向开发者
RPC层 远程过程调用层
config 配置层 对外提供配置 以ServiceConfig ReferenceConfig 为核心 可以直接初始化配置 类 也可以解析配置文件生成
proxy 服务代理层 无论是生产者 还是消费者 框架都会产生一个代理类 整个过程对上层透明 就是 业务层对远程调用无感
registry 注册中心层 封装服务地址的注册与发现 以服务的URL为中心
cluster 路由层 (集群容错层) 提供了多个提供者的路由和负载均衡 并且它桥接注册中心 以Invoker为核心
monitor 监控层 RPC调用相关的信息 如 调用次数 成功失败的情况 调用时间等 在这一层完成
protocol 远程调用层 封装RPC调用 无论是服务的暴露 还是 服务的引用 都是在Protocol中作为主 功能入口 负责Invoker的整个生命周期 Dubbo中所有的模型都向Invoker靠拢
Remoting层 远程数据传输层
exchange 信息交换层 封装请求和响应的模式 如把请求由同步 转换成异步
transport 网络传输层 统一网络传输的接口 比如 netty 和 mina 统一为一个网络传输接口
serialize 数据序列化层 负责管理整个框架中的数据传输的序列化 和反序列化
当dubbo启动后会在zookeeper下生成一个dubbo的子目录,dubbo下面是当前的接口名称
接口下面的四格配置项是
consumers: 当前服务下面所有的消费者列表(URL)
providers: 当前服务下面所有的提供者列表(URL)
configuration: 当前服务下面的配置信息信息,provider或者consumer会通过读取这里的配 置信息来获取配置
routers: 当消费者在进行获取提供者的时,会通过这里配置好的路由来进行适配匹配规则。
可以看到,dubbo基本上很多时候都是通过URL的形式来进行交互获取数据的,在URL中也会保存 很多的信息
服务的注册过程分析
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.test.service.HelloService" ref="helloService"/>
<!-- 和本地bean一样实现服务 -->
<bean id="helloService" class="com.test.service.impl.HelloServiceImpl" />
dubbo在这里的配置会被解析成ServiceConfig,启动的时候会调用doExportUrlsFor1Protocol方法
private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
//省略。。。
//ref是实际提供服务的class,interfaceClass是提供服务的接口
//在这里通过PROXY_FACTORY(JavassistProxyFactory)生成一个invoker
Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString()));
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
//从这里把服务提供方的地址等信息注册到zookeeper
//protocol=RegistryProtocol
Exporter<?> exporter = protocol.export(wrapperInvoker);
exporters.add(exporter);
//省略。。。
}
进入RegistryProtocol的export方法
@Override
public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
//...
//获取当前url是否需要进行注册参数
boolean register = providerUrl.getParameter(REGISTER_KEY, true);
if (register) {
//注册
register(registryUrl, registeredProviderUrl);
}
// 对override协议进行注册,用于在接收到override请求时做适配,这种方式用于适配2.6.x及之 前的版本(混用)
registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);
// 设置当前导出中的相关信息
exporter.setRegisterUrl(registeredProviderUrl);
exporter.setSubscribeUrl(overrideSubscribeUrl);
// 返回导出对象(对数据进行封装)
return new DestroyableExporter<>(exporter);
}
public void register(URL registryUrl, URL registeredProviderUrl) {
//获得注册中心
Registry registry = registryFactory.getRegistry(registryUrl);
//注册 调用ListenerRegistryWrapper的register方法
registry.register(registeredProviderUrl);
// ProviderModel 表示服务提供者模型,此对象中存储了与服务提供者相关的信息。
// 比如服务的配置信息,服务实例等。每个被导出的服务对应一个 ProviderModel。
ProviderModel model = ApplicationModel.getProviderModel(registeredProviderUrl.getServiceKey());
model.addStatedUrl(new ProviderModel.RegisterStatedURL(
registeredProviderUrl,
registryUrl,
true
));
}
调用org.apache.dubbo.registry.ListenerRegistryWrapper#register
public void register(URL url) {
try {
//进入FailbackRegistry的register方法
registry.register(url);
}
//...
}
@Override
public void register(URL url) {
if (!acceptable(url)) {
logger.info("URL " + url + " will not be registered to Registry. Registry " + url + " does not accept service of this protocol type.");
return;
}
// 上层调用
// 主要用于保存已经注册的地址列表
super.register(url);
// 将一些错误的信息移除(确保当前地址可以在出现一些错误的地址时可以被删除)
removeFailedRegistered(url);
removeFailedUnregistered(url);
try {
//开始注册
doRegister(url);
} catch (Exception e) {
Throwable t = e;
// 记录日志
boolean check = getUrl().getParameter(Constants.CHECK_KEY, true)
&& url.getParameter(Constants.CHECK_KEY, true)
&& !CONSUMER_PROTOCOL.equals(url.getProtocol());
boolean skipFailback = t instanceof SkipFailbackWrapperException;
if (check || skipFailback) {
if (skipFailback) {
t = t.getCause();
}
throw new IllegalStateException("Failed to register " + url + " to registry " + getUrl().getAddress() + ", cause: " + t.getMessage(), t);
} else {
logger.error("Failed to register " + url + ", waiting for retry, cause: " + t.getMessage(), t);
}
// 后台异步进行重试
addFailedRegistered(url);
}
}
进入org.apache.dubbo.registry.zookeeper.ZookeeperRegistry#doRegister
@Override
public void doRegister(URL url) {
try {
//按dubbo/接口名/provider生成path 注册到zk
zkClient.create(toUrlPath(url), url.getParameter(DYNAMIC_KEY, true));
} catch (Throwable e) {
throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
}
}
url规则
url地址格式为 protocol://host:port/path?key=value&key=value
provider://192.168.20.1:20883/com.test.service.HelloService? anyhost=true&application=service- provider2&bind.ip=192.168.20.1&bind.port=20883&category=configurators&check=fals e&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=com.test.service
URL主要有以下几部分组成:
protocol: 协议,一般像我们的 provider 或者 consumer 在这里都是人为具体的协议
host: 当前 provider 或者其他协议所具体针对的地址,比较特殊的像 override 协议所指定的 host就是 0.0.0.0 代表所有的机器都生效
port: 和上面相同,代表所处理的端口号
path: 服务路径,在 provider 或者 consumer 等其他中代表着我们真实的业务接口
key=value: 这些则代表具体的参数,这里我们可以理解为对这个地址的配置。比如我们 provider 中需要具体机器的服务应用名,就可以是一个配置的方式设置上去。
注意:Dubbo中的URL与java中的URL是有一些区别的,如下:
这里提供了针对于参数的 parameter 的增加和减少(支持动态更改)
提供缓存功能,对一些基础的数据做缓存.
服务本地缓存
在ZookeeperRegistry的父类AbstractRegistry中
public AbstractRegistry(URL url) {
setUrl(url);
// Start file save timer
syncSaveFile = url.getParameter(REGISTRY_FILESAVE_SYNC_KEY, false);
// 默认保存路径(home/.dubbo/dubbo-registry-appName-address-port.cache) String defaultFilename = System.getProperty("user.home") + "/.dubbo/dubbo-
registry-" + url.getParameter(APPLICATION_KEY) + "-" + url.getAddress().replaceAll(":", "-") + ".cache";
String filename = url.getParameter(FILE_KEY, defaultFilename); // 创建文件
File file = null;
if (ConfigUtils.isNotEmpty(filename)) {
file = new File(filename);
if (!file.exists() && file.getParentFile() != null && !file.getParentFile().exists()) {
if (!file.getParentFile().mkdirs()) {
throw new IllegalArgumentException("Invalid registry cache file" + file + ", cause: Failed to create directory " + file.getParentFile() + "!");
}
}
}
this.file = file;
// 加载已有的配置文件
loadProperties();
notify(url.getBackupUrls());
}
跟一下notify(url.getBackupUrls());最后会进入saveProperties(url)方法
private void saveProperties(URL url) {
if (file==null) {
return;
}
try {
StringBuilder buf = new StringBuilder();
// 获取所有通知到的地址
Map<String, List<URL>> categoryNotified = notified.get(url);
if (categoryNotified != null) {
for (List<URL> us : categoryNotified.values()) {
for (URL u : us) {
//多个地址拼接
if (buf.length() > 0) {
buf.append(URL_SEPARATOR);
}
buf.append(u.toFullString());
}
}
}
// 保存数据
properties.setProperty(url.getServiceKey(), buf.toString());
// 保存为一个新的版本号
// 通过这种机制可以保证后面保存的记录,在重试的时候,不会重试之前的版本
long version = lastCacheChanged.incrementAndGet();
// 需要同步保存则进行保存
if (syncSaveFile) {
doSaveProperties(version);
} else {
// 否则则异步去进行处理
registryCacheExecutor.execute(new SaveProperties(version)); }
} catch (Throwable t) {
logger.warn(t.getMessage(), t);
}
}
public void doSaveProperties(long version) {
if (version < lastCacheChanged.get()) {
return;
}
if (file == null) {
return;
}
// Save
try {
// 使用文件级别所,来保证同一段时间只会有一个线程进行读取操作
File lockfile = new File(file.getAbsolutePath() + ".lock");
if (!lockfile.exists()) {
lockfile.createNewFile();
}
try (RandomAccessFile raf = new RandomAccessFile(lockfile, "rw");
FileChannel channel = raf.getChannel()) {
// 利用文件锁来保证并发的执行的情况下,只会有一个线程执行成功(原因在于可能是跨VM的)
FileLock lock = channel.tryLock();
if (lock == null) {
throw new IOException("Can not lock the registry cache file " + file.getAbsolutePath() + ", ignore and retry later, maybe multi java process use the file, please config: dubbo.registry.file=xxx.properties");
}
// Save
try {
if (!file.exists()) {
file.createNewFile();
}
// 将配置的文件信息保存到文件中
try (FileOutputStream outputFile = new FileOutputStream(file)) {
properties.store(outputFile, "Dubbo Registry Cache");
}
} finally {
// 解开文件锁
lock.release();
}
}
} catch (Throwable e) {
// 执行出现错误时,则交给专门的线程去进行重试
savePropertiesRetryTimes.incrementAndGet();
if (savePropertiesRetryTimes.get() >= MAX_RETRY_TIMES_SAVE_PROPERTIES) {
logger.warn("Failed to save registry cache file after retrying " + MAX_RETRY_TIMES_SAVE_PROPERTIES + " times, cause: " + e.getMessage(), e);
savePropertiesRetryTimes.set(0);
return;
}
if (version < lastCacheChanged.get()) {
savePropertiesRetryTimes.set(0);
return;
} else {
registryCacheExecutor.execute(new SaveProperties(lastCacheChanged.incrementAndGet()));
}
logger.warn("Failed to save registry cache file, will retry, cause: " + e.getMessage(), e);
}
}
dubbo消费过程
在ReferenceConfig中的init方法生成代理
public synchronized void init() {
//省略。。
ref = createProxy(map);
//省略。。
}
private T createProxy(Map<String, String> map) {
//获得一个invoker
invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0));
//生成一个invoker的远程服务代理
return (T) PROXY_FACTORY.getProxy(invoker);
}
invoker中有配置信息
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="service-consumer" >
<dubbo:parameter key="qos.enable" value="true" ></dubbo:parameter>
<dubbo:parameter key="qos.port" value="33333"></dubbo:parameter>
<dubbo:parameter key="qos.accept.foreign.ip" value="true" ></dubbo:parameter>
</dubbo:application>
<!-- -->
<dubbo:consumer timeout="2000" check="false" ></dubbo:consumer>
<!-- 使用zookeeper注册中心暴露发现服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2182" timeout="10000"/>
<!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
<dubbo:reference id="helloService" interface="com.test.service.HelloService" timeout="4000" retries="2"/>
Dubbo扩展SPI源码
ExtensionLoader是所有Dubbo中SPI的入口
org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader 方法:获取扩展点加载器 并加载所对应的所有的扩展点实现
org.apache.dubbo.common.extension.ExtensionLoader.getExtension 方法:根据name 获取扩展的指定实现
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
// 必须传入类型
if (type == null) {
throw new IllegalArgumentException("Extension type == null");
}
// 必须是接口类型
if (!type.isInterface()) {
throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!");
}
// 必须有@SPI
if (!withExtensionAnnotation(type)) {
throw new IllegalArgumentException("Extension type (" + type +
") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
}
// 尝试从缓存中加载
ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
if (loader == null) {
// 如果没有才进行初始化 并且放入缓存中
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
}
return loader;
}
private ExtensionLoader(Class<?> type) {
this.type = type;
// 创建ExtensionFactory 对象 ExtensionFactory 也是一个扩展点
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
/**
* ExtensionFactory
* 根据传入的扩展点类型 和 名字 来获取扩展 这里和我们SPI中的具体名称实现挂钩
*/
@SPI
public interface ExtensionFactory {
/**
* Get extension.
*
* @param type object type.
* @param name object name.
* @return object instance.
*/
<T> T getExtension(Class<T> type, String name);
}
它有两个实现(版本不同实现类可能不一样)
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {
private final List<ExtensionFactory> factories;
public AdaptiveExtensionFactory() {
// 获取针对 ExtensionFactory 的扩展加载器
ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
// 获取支持的扩展
for (String name : loader.getSupportedExtensions()) {
// 对扩展进行缓存
list.add(loader.getExtension(name));
}
factories = Collections.unmodifiableList(list);
}
@Override
public <T> T getExtension(Class<T> type, String name) {
// 交给真实的扩展来处理 用ExtensionFactory的实现类的getExtension方法来获取type的实现
for (ExtensionFactory factory : factories) {
T extension = factory.getExtension(type, name);
if (extension != null) {
return extension;
}
}
return null;
}
}
进入org.apache.dubbo.common.extension.ExtensionLoader#getSupportedExtensions
public Set<String> getSupportedExtensions() {
// 扩展类的信息 name 和 Class 对应
Map<String, Class<?>> clazzes = getExtensionClasses();
// 获取扩展点的名字
return Collections.unmodifiableSet(new TreeSet<>(clazzes.keySet()));
}
private Map<String, Class<?>> getExtensionClasses() {
// 从缓存中获取已经加载的扩展类
Map<String, Class<?>> classes = cachedClasses.get();
// 双重检查
if (classes == null) {
// 为空就锁住
synchronized (cachedClasses) {
// 防止重复加载
classes = cachedClasses.get();
if (classes == null) {
// 加载扩展类信息 并缓存
classes = loadExtensionClasses();
cachedClasses.set(classes);
}
}
}
return classes;
}
private Map<String, Class<?>> loadExtensionClasses() {
// 加载默认的扩展实现
cacheDefaultExtensionName();
Map<String, Class<?>> extensionClasses = new HashMap<>();
// 获取每个目录下 名称和实现类对应的关系
for (LoadingStrategy strategy : strategies) {
loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(), strategy.excludedPackages());
loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"), strategy.preferExtensionClassLoader(), strategy.excludedPackages());
}
return extensionClasses;
}
进入org.apache.dubbo.common.extension.ExtensionLoader#cacheDefaultExtensionName方法
private void cacheDefaultExtensionName() {
// 如果没有@SPI 则返回
final SPI defaultAnnotation = type.getAnnotation(SPI.class);
if (defaultAnnotation == null) {
return;
}
// 获取默认的扩展名
// 比如LoadBalance 默认实现是random
String value = defaultAnnotation.value();
if ((value = value.trim()).length() > 0) {
String[] names = NAME_SEPARATOR.split(value);
if (names.length > 1) {
throw new IllegalStateException("More than 1 default extension name on extension " + type.getName()
+ ": " + Arrays.toString(names));
}
if (names.length == 1) {
cachedDefaultName = names[0];
}
}
}
回到org.apache.dubbo.common.extension.ExtensionLoader#loadDirectory()方法
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type,
boolean extensionLoaderClassLoaderFirst, String... excludedPackages) {
// 路径 + 包名.接口名
String fileName = dir + type;
try {
Enumeration<java.net.URL> urls = null;
ClassLoader classLoader = findClassLoader();
// try to load from ExtensionLoader's ClassLoader first
if (extensionLoaderClassLoaderFirst) {
ClassLoader extensionLoaderClassLoader = ExtensionLoader.class.getClassLoader();
if (ClassLoader.getSystemClassLoader() != extensionLoaderClassLoader) {
urls = extensionLoaderClassLoader.getResources(fileName);
}
}
if(urls == null || !urls.hasMoreElements()) {
if (classLoader != null) {
urls = classLoader.getResources(fileName);
} else {
urls = ClassLoader.getSystemResources(fileName);
}
}
// 遍历每一个资源文件,并且进行加载资源信息到extensionClasses(缓存), 主要功能是读取文件内容
if (urls != null) {
while (urls.hasMoreElements()) {
java.net.URL resourceURL = urls.nextElement();
//读取资源文件并加载class
loadResource(extensionClasses, classLoader, resourceURL, excludedPackages);
}
}
} catch (Throwable t) {
logger.error("Exception occurred when loading extension class (interface: " +
type + ", description file: " + fileName + ").", t);
}
}
private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader,
java.net.URL resourceURL, String... excludedPackages) {
try {
// 根据resourceURL 读取文件
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
// # 后面是注释 读取#前面的内容
final int ci = line.indexOf('#');
if (ci >= 0) {
line = line.substring(0, ci);
}
line = line.trim();
if (line.length() > 0) {
try {
String name = null;
int i = line.indexOf('=');
if (i > 0) {
// 加载 key = value 形式的数据
name = line.substring(0, i).trim();
line = line.substring(i + 1).trim();
}
if (line.length() > 0 && !isExcluded(line, excludedPackages)) {
// 对类信息进行加载操作
loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name);
}
} catch (Throwable t) {
IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);
exceptions.put(line, e);
}
}
}
}
} catch (Throwable t) {
logger.error("Exception occurred when loading extension class (interface: " +
type + ", class file: " + resourceURL + ") in " + resourceURL, t);
}
}
private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) throws NoSuchMethodException {
// 当前扩展点 必须是接口的实现
if (!type.isAssignableFrom(clazz)) {
throw new IllegalStateException("Error occurred when loading extension class (interface: " +
type + ", class line: " + clazz.getName() + "), class "
+ clazz.getName() + " is not subtype of interface.");
}
// 如果包含了 @Adaptive 就存储到cacheAdaptiveClass
if (clazz.isAnnotationPresent(Adaptive.class)) {
cacheAdaptiveClass(clazz);
} else if (isWrapperClass(clazz)) {
// 判断是否是wrapper类型, 是否构造函数中有该接口类型的传入
// wrapper类型的意思是,对当前的扩展点实现封装功能处理
cacheWrapperClass(clazz);
} else {
clazz.getConstructor();
// 看是否已经定义过name 如果定义过就是一之前的 否则就是当前的简单名称
if (StringUtils.isEmpty(name)) {
name = findAnnotationName(clazz);
if (name.length() == 0) {
throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + resourceURL);
}
}
// 对name 和 class 做映射
String[] names = NAME_SEPARATOR.split(name);
if (ArrayUtils.isNotEmpty(names)) {
// 如果当前类 有Activate 标注 则加入到 cacheActivateClass 中 意味着需要执行
cacheActivateClass(clazz, names[0]);
for (String n : names) {
// 进行名称映射保存
cacheName(clazz, n);
saveInExtensionClass(extensionClasses, clazz, n);
}
}
}
}
在loadclass方法中会判断是否更新这几个值
cachedAdaptiveClass: 当前Extension类型对应的AdaptiveExtension类型(只能一个)
cachedWrapperClasses: 当前Extension类型对应的所有Wrapper实现类型(无顺序)
cachedActivates: 当前Extension实现自动激活实现缓存(map,无序)
cachedNames: 扩展点实现类对应的名称(如配置多个名称则值为第一个)
根据name获取扩展点的方法 getExtension
public T getExtension(String name) {
if (StringUtils.isEmpty(name)) {
throw new IllegalArgumentException("Extension name == null");
}
// 获取当前SPi的默认扩展实现类
if ("true".equals(name)) {
return getDefaultExtension();
}
// 获取当前类的Holder 建立一个引用 判断 加锁
final Holder<Object> holder = getOrCreateHolder(name);
Object instance = holder.get();
if (instance == null) {
synchronized (holder) {
instance = holder.get();
if (instance == null) {
instance = createExtension(name);
holder.set(instance);
}
}
}
return (T) instance;
}
private Holder<Object> getOrCreateHolder(String name) {
// 根据当前名称 从缓存中获取 holder
Holder<Object> holder = cachedInstances.get(name);
if (holder == null) {
// 如果不存在 则创建一个 放入缓存
cachedInstances.putIfAbsent(name, new Holder<>());
holder = cachedInstances.get(name);
}
return holder;
}
private T createExtension(String name) {
// 从 getExtensionClasses() 中来根据name 获取对应的Class对象
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
throw findException(name);
}
try {
// 获取实例
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
// 如果不存在扩展实例 则使用反射创建一个 放入 EXTENSION_INSTANCES
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
//注入其它的扩展 用于扩展点 和 其它的扩展点互通 给当前扩展点 设置其它的扩展点
injectExtension(instance);
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (CollectionUtils.isNotEmpty(wrapperClasses)) {
for (Class<?> wrapperClass : wrapperClasses) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
initExtension(instance);
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
type + ") couldn't be instantiated: " + t.getMessage(), t);
}
}
private T injectExtension(T instance) {
if (objectFactory == null) {
return instance;
}
try {
for (Method method : instance.getClass().getMethods()) {
// 是否是set方法 参数长度为1 公开的方法
if (!isSetter(method)) {
continue;
}
/**
* Check {@link DisableInject} to see if we need auto injection for this property
*/
if (method.getAnnotation(DisableInject.class) != null) {
continue;
}
Class<?> pt = method.getParameterTypes()[0];
if (ReflectUtils.isPrimitives(pt)) {
continue;
}
try {
//如果这个instance里面有其他的属性也是扩展点
//那么就通过objectFactory.getExtension(pt, property)方法获得这个属性的实例
//并通过set方法(method.invoke(instance, object))设置到instance里面
String property = getSetterProperty(method);
// 从 objectFactory 得到指定的扩展点
Object object = objectFactory.getExtension(pt, property);
if (object != null) {
// 比如一个set方法是 setRandom(LoadBalance loadBalance)
method.invoke(instance, object);
}
} catch (Exception e) {
logger.error("Failed to inject via method " + method.getName()
+ " of interface " + type.getName() + ": " + e.getMessage(), e);
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return instance;
}
Adaptive功能实现
Adaptive的主要功能是对所有的扩展点进行封装为一个类,通过URL传入参数的时动态选择需要使用的 扩展点。其底层的实现原理就是动态代理。
public T getAdaptiveExtension() {
// 双层锁判断
Object instance = cachedAdaptiveInstance.get();
if (instance == null) {
// 如果直接已经有创建并且错误的情况,则直接返回错误信息,防止重复没必要的创建
if (createAdaptiveInstanceError != null) {
throw new IllegalStateException("Failed to create adaptive instance: " +
createAdaptiveInstanceError.toString(),
createAdaptiveInstanceError);
}
synchronized (cachedAdaptiveInstance) {
instance = cachedAdaptiveInstance.get();
if (instance == null) {
try {
// 这里真实的进行创建操作
instance = createAdaptiveExtension();
cachedAdaptiveInstance.set(instance);
} catch (Throwable t) {
createAdaptiveInstanceError = t;
throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
}
}
}
}
return (T) instance;
}
private T createAdaptiveExtension() {
try {
// 这里使用`getAdaptiveExtensionClass`方法进行构建类并且执行实例化
// 然后和普通的其他class相同,依旧使用injectExtension进行扩展
return injectExtension((T) getAdaptiveExtensionClass().newInstance());
} catch (Exception e) {
throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
}
}
private Class<?> getAdaptiveExtensionClass() {
// 确保已经加载了所有的扩展类信息
getExtensionClasses();
// 如果已经加载过了,则直接返回
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
// 否则进行构建操作
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
private Class<?> createAdaptiveExtensionClass() {
// 实例化一个新的Adaptive的代码生成器,并且进行代码生成
//通过type和cachedDefaultName获得
//cachedDefaultName在前面getExtensionClasses()解析@sqi获得
//通过拼接一个string,拼出来一个类的code作为代理
String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
// 获取类加载器
ClassLoader classLoader = findClassLoader();
// 通过扩展点,寻找编译器
org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
// 编译并且生成class
return compiler.compile(code, classLoader);
}
信息缓存接口Directory
Directory是Dubbo中的一个接口,主要用于缓存当前可以被调用的提供者列表信息。我们在消费者进
行调用时都会通过这个接口来获取所有的提供者列表,再进行后续处理。
public interface Directory<T> extends Node {
// 获取服务的类型
Class<T> getInterface();
// 根据本次调用的信息来获取所有可以被执行的提供者信息
List<Invoker<T>> list(Invocation invocation) throws RpcException;
// 获取所有的提供者信息
List<Invoker<T>> getAllInvokers();
}
进入子类RegistryDirectory#doList 方法
public List<Invoker<T>> doList(Invocation invocation) {
// 当没有提供者的时候会直接抛出异常
if (forbidden) {
// 1. No service provider 2. Service providers are disabled
throw new RpcException(RpcException.FORBIDDEN_EXCEPTION, "No provider available from registry " + getUrl().getAddress() + " for service " + getConsumerUrl().getServiceKey() + " on consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", please check status of providers(disabled, not registered or in blacklist).");
}
List<Invoker<T>> invokers = null;
try {
// 交给路由chain去处理并且获取所有的invokers
invokers = routerChain.route(getConsumerUrl(), invocation);
} catch (Throwable t) {
logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
}
return invokers == null ? Collections.emptyList() : invokers;
}
routerChain中的invokers是在refreshInvoker()方法被设置的
private void refreshInvoker(List<URL> invokerUrls) {
//....
//在toinvoke方法中用invoker = new InvokerDelegate<>(protocol.refer(serviceType, url), url, providerUrl)来获取invoker
Map<String, Invoker<T>> newUrlInvokerMap = toInvokers(invokerUrls);// Translate url list to Invoker map
/**
* If the calculation is wrong, it is not processed.
*
* 1. The protocol configured by the client is inconsistent with the protocol of the server.
* eg: consumer protocol = dubbo, provider only has other protocol services(rest).
* 2. The registration center is not robust and pushes illegal specification data.
*
*/
if (CollectionUtils.isEmptyMap(newUrlInvokerMap)) {
logger.error(new IllegalStateException("urls to invokers error .invokerUrls.size :" + invokerUrls.size() + ", invoker.size :0. urls :" + invokerUrls
.toString()));
return;
}
List<Invoker<T>> newInvokers = Collections.unmodifiableList(new ArrayList<>(newUrlInvokerMap.values()));
// pre-route and build cache, notice that route cache should build on original Invoker list.
// toMergeMethodInvokerMap() will wrap some invokers having different groups, those wrapped invokers not should be routed.
//设置routerChain的Invokers
routerChain.setInvokers(newInvokers);
this.invokers = multiGroup ? toMergeInvokerList(newInvokers) : newInvokers;
this.urlInvokerMap = newUrlInvokerMap;
try {
destroyUnusedInvokers(oldUrlInvokerMap, newUrlInvokerMap); // Close the unused Invoker
} catch (Exception e) {
logger.warn("destroyUnusedInvokers error. ", e);
}
}
}
在protocol的实现类RegistryProtocol可以看到
org.apache.dubbo.registry.integration.RegistryProtocol#refer
// type:需要获得的服务(HelloService)
// url: 注册中心地址信息
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
// 获取注册中心的地址URL(主要用于转换协议),比如我们是使用的zookeeper,那么他就会转换为zookeeper://
url = getRegistryUrl(url);
// 获取注册中心配置信息
Registry registry = registryFactory.getRegistry(url);
if (RegistryService.class.equals(type)) {
return proxyFactory.getInvoker((T) registry, type, url);
}
// 适用于多个分组时使用
// group="a,b" or group="*"
Map<String, String> qs = StringUtils.parseQueryString(url.getParameterAndDecoded(REFER_KEY));
String group = qs.get(GROUP_KEY);
if (group != null && group.length() > 0) {
if ((COMMA_SPLIT_PATTERN.split(group)).length > 1 || "*".equals(group)) {
return doRefer(getMergeableCluster(), registry, type, url);
}
}
// 真正去构建 Invoker 和 Directory
return doRefer(cluster, registry, type, url);
}
//他会把registry注册中心和protocol协议都塞到directory里面,通过cluster封装成invoker
private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
// 实例化Directory
RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url);
// 设置注册中心和所使用的协议
directory.setRegistry(registry);
directory.setProtocol(protocol);
// all attributes of REFER_KEY
//生成监听路径URL
Map<String, String> parameters = new HashMap<String, String>(directory.getConsumerUrl().getParameters());
URL subscribeUrl = new URL(CONSUMER_PROTOCOL, parameters.remove(REGISTER_IP_KEY), 0, type.getName(), parameters);
if (directory.isShouldRegister()) {
// 在Directory中设置监听的consumerurl地址
directory.setRegisteredConsumerUrl(subscribeUrl);
// 在注册中心中注册消费者URL
// 也就是我们之前的Zookeeper的node中看到的consumer://
registry.register(directory.getRegisteredConsumerUrl());
}
// 构建路由链
directory.buildRouterChain(subscribeUrl);
// 进行监听所有的的provider
directory.subscribe(toSubscribeUrl(subscribeUrl));
// 加入到集群中
Invoker<T> invoker = cluster.join(directory);
List<RegistryProtocolListener> listeners = findRegistryProtocolListeners(url);
if (CollectionUtils.isEmpty(listeners)) {
return invoker;
}
RegistryInvokerWrapper<T> registryInvokerWrapper = new RegistryInvokerWrapper<>(directory, cluster, invoker, subscribeUrl);
for (RegistryProtocolListener listener : listeners) {
listener.onRefer(this, registryInvokerWrapper);
}
return registryInvokerWrapper;
}
回到 RouterChain#route 方法
public List<Invoker<T>> route(URL url, Invocation invocation) {
// 所有的Invoker 列表
List<Invoker<T>> finalInvokers = invokers;
for (Router router : routers) {
// 根据路由规则 得到我们最终的Invoker 列表
finalInvokers = router.route(finalInvokers, url, invocation);
}
return finalInvokers;
}
路由规则实现
org.apache.dubbo.rpc.cluster.router.condition.ConditionRouter
public class ConditionRouter extends AbstractRouter {
public static final String NAME = "condition";
private static final Logger logger = LoggerFactory.getLogger(ConditionRouter.class);
protected static final Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)");
// 消费者端是否满足判断条件
// protected static final class MatchPair {
// 满足和不满足的具体条件 或者 匹配 和 不匹配的具体条件
//final Set<String> matches = new HashSet<String>();
//final Set<String> mismatches = new HashSet<String>();
//}
protected Map<String, MatchPair> whenCondition;
// 当满足判断条件时如何选择invokers(提供者)
protected Map<String, MatchPair> thenCondition;
}
org.apache.dubbo.rpc.cluster.router.condition.ConditionRouter#route
@Override
public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation)
throws RpcException {
// 不启用的时,则直接返回提供者的列表
if (!enabled) {
return invokers;
}
// 如果不存在任何invoker则直接返回
if (CollectionUtils.isEmpty(invokers)) {
return invokers;
}
try {
// 判断是否满足判断条件,不满足直接返回列表
// 1. 如果判断条件whenCondition为空则直接认定为匹配
// 2. 如果whenCondition条件匹配url则认定为匹配
if (!matchWhen(url, invocation)) {
return invokers;
}
List<Invoker<T>> result = new ArrayList<Invoker<T>>();
if (thenCondition == null) {
logger.warn("The current consumer in the service blacklist. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey());
return result;
}
// 依次判断每一个invoker的url是否满足条件
for (Invoker<T> invoker : invokers) {
if (matchThen(invoker.getUrl(), url)) {
result.add(invoker);
}
}
// 如果不为空则直接返回
if (!result.isEmpty()) {
return result;
} else if (force) {
// 如果为空,并且必须要走这个条件时,则直接返回空
logger.warn("The route result is empty and force execute. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey() + ", router: " + url.getParameterAndDecoded(RULE_KEY));
return result;
}
} catch (Throwable t) {
logger.error("Failed to execute condition router rule: " + getUrl() + ", invokers: " + invokers + ", cause: " + t.getMessage(), t);
}
return invokers;
}
org.apache.dubbo.rpc.cluster.router.condition.ConditionRouter#init
public void init(String rule) {
try {
// 必须包含规则配置
if (rule == null || rule.trim().length() == 0) {
throw new IllegalArgumentException("Illegal route rule!");
}
rule = rule.replace("consumer.", "").replace("provider.", "");
// 根据"=>"来判断when或者then条件
int i = rule.indexOf("=>");
//=>前面是whenRule,后面是thenRule
//rule=URL.encode("host = 10.20.153.10 => host = 10.20.153.11")
//=> 之前的为消费者匹配条件,所有参数和消费者的 URL 进行对比,当消费者满足匹配条件时,对该消费者执行后面的过滤规则。
//=> 之后为提供者地址列表的过滤条件,所有参数和提供者的 URL 进行对比,消费者最终只拿到过滤后的地址列表。
String whenRule = i < 0 ? null : rule.substring(0, i).trim();
String thenRule = i < 0 ? rule.trim() : rule.substring(i + 2).trim();
// 分别根据"=>"来生成前后的规则
Map<String, MatchPair> when = StringUtils.isBlank(whenRule) || "true".equals(whenRule) ? new HashMap<String, MatchPair>() : parseRule(whenRule);
Map<String, MatchPair> then = StringUtils.isBlank(thenRule) || "false".equals(thenRule) ? null : parseRule(thenRule);
this.whenCondition = when;
this.thenCondition = then;
} catch (ParseException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
Cluster组件
在org.apache.dubbo.registry.integration.RegistryProtocol#doRefer使用到了
Invoker<T> invoker = cluster.join(directory);
它主要用于代理真正的Invoker执行时做处理,提供了多种容错方案。
//默认使用Failover作为实现
@SPI(FailoverCluster.NAME)
public interface Cluster {
/**
* Merge the directory invokers to a virtual invoker.
*
* @param <T>
* @param directory
* @return cluster invoker
* @throws RpcException
*/
// 生成一个新的invoker
@Adaptive
<T> Invoker<T> join(Directory<T> directory) throws RpcException;
}
org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster#join
@Override
public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
// 使用拦截器进行了一层封装 真正完成生成Invoker的实现 在子类doJoin(directory)
return buildClusterInterceptors(doJoin(directory), directory.getUrl().getParameter(REFERENCE_INTERCEPTOR_KEY));
}
进入默认实现类org.apache.dubbo.rpc.cluster.support.FailoverCluster#doJoin
@Override
public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
// 构建了 FailoverClusterInvoker 对象
// 最终使用Invoker的时候会使用对应的Invoker的实现类的doinvoke方法
return new FailoverClusterInvoker<>(directory);
}
org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker#doInvoke
public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
// 如果没有任何的invoker则抛出异常
List<Invoker<T>> copyInvokers = invokers;
checkInvokers(copyInvokers, invocation);
// 获取这个方法最大的重试次数
String methodName = RpcUtils.getMethodName(invocation);
int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
if (len <= 0) {
len = 1;
}
// 通过for循环的形式表示可以重试的次数
RpcException le = null; // last exception.
List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size()); // invoked invokers.
Set<String> providers = new HashSet<String>(len);
for (int i = 0; i < len; i++) {
if (i > 0) {
// 每次都执行一次是否关闭当前consumer的判断
checkWhetherDestroyed();
// 重新获取一遍invoker列表
copyInvokers = list(invocation);
// 再次进行一次存在invoker的检查
checkInvokers(copyInvokers, invocation);
}
// 选择具体的invoker(交给负载均衡)
Invoker<T> invoker = select(loadbalance, invocation, copyInvokers, invoked);
// 增加到已经执行过得invoker列表中
invoked.add(invoker);
RpcContext.getContext().setInvokers((List) invoked);
try {
// 让其真正的去进行执行操作
Result result = invoker.invoke(invocation);
if (le != null && logger.isWarnEnabled()) {
logger.warn("Although retry the method " + methodName
+ " in the service " + getInterface().getName()
+ " was successful by the provider " + invoker.getUrl().getAddress()
+ ", but there have been failed providers " + providers
+ " (" + providers.size() + "/" + copyInvokers.size()
+ ") from the registry " + directory.getUrl().getAddress()
+ " on the consumer " + NetUtils.getLocalHost()
+ " using the dubbo version " + Version.getVersion() + ". Last error is: "
+ le.getMessage(), le);
}
return result;
} catch (RpcException e) {
// 如果是业务异常则直接抛出
if (e.isBiz()) {
throw e;
}
le = e;
} catch (Throwable e) {
le = new RpcException(e.getMessage(), e);
} finally {
providers.add(invoker.getUrl().getAddress());
}
}
// 如果重试了指定次数后依旧失败,则直接认定为失败
throw new RpcException(le.getCode(), "Failed to invoke the method "
+ methodName + " in the service " + getInterface().getName()
+ ". Tried " + len + " times of the providers " + providers
+ " (" + providers.size() + "/" + copyInvokers.size()
+ ") from the registry " + directory.getUrl().getAddress()
+ " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version "
+ Version.getVersion() + ". Last error is: "
+ le.getMessage(), le.getCause() != null ? le.getCause() : le);
}
负载均衡实现
上面使用了负载均衡select(loadbalance, invocation, copyInvokers, invoked);
// 默认使用随机算法
@SPI(RandomLoadBalance.NAME)
public interface LoadBalance {
/**
* select one invoker in list.
*
* @param invokers invokers.
* @param url refer url
* @param invocation invocation.
* @return selected invoker.
*/
// 进行选择真正的invoker
@Adaptive("loadbalance")
<T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;
}
进入org.apache.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance#select
public <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) {
// 如果不存在任何的invoker则直接返回
if (CollectionUtils.isEmpty(invokers)) {
return null;
}
// 如果还有一个invoker则直接返回,不需要执行负载均衡
if (invokers.size() == 1) {
return invokers.get(0);
}
// 交给子类进行实现
return doSelect(invokers, url, invocation);
}
不同的子类有不同的doSelect,这里来看看默认的
org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance#doSelect
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
// 总计的invoker列表数量
int length = invokers.size();
// 默认每个invoker的权重都是相同的
boolean sameWeight = true;
// 所有的权重列表
int[] weights = new int[length];
// 首个invoker的权重信息
int firstWeight = getWeight(invokers.get(0), invocation);
weights[0] = firstWeight;
// 计算总共的权重,并且吧每一个invoker的权重进行设置到列表中
int totalWeight = firstWeight;
for (int i = 1; i < length; i++) {
int weight = getWeight(invokers.get(i), invocation);
// save for later use
weights[i] = weight;
// Sum
totalWeight += weight;
if (sameWeight && weight != firstWeight) {
sameWeight = false;
}
}
// 如果权重不相同 10 30 50 100
if (totalWeight > 0 && !sameWeight) {
// 通过总共的权重来随机分配
int offset = ThreadLocalRandom.current().nextInt(totalWeight);
// 看看最终落到哪一个机器上去
for (int i = 0; i < length; i++) {
offset -= weights[i];
if (offset < 0) {
return invokers.get(i);
}
}
}
// 如果权重都是相同的话,则随机选取一个即可
return invokers.get(ThreadLocalRandom.current().nextInt(length));
}
Invoker执行逻辑
前面通过LoadBalance获得了Invoker
Invoker就是我们真实执行请求的组件。这里也会衍生出我们真正的 Dubbo 或者 Grpc(谷歌的) 等其他协议的请
求。
public interface Invoker<T> extends Node {
/**
* get service interface.
*
* @return service interface.
*/
// 当前执行器的服务接口是哪一个
Class<T> getInterface();
/**
* invoke.
*
* @param invocation
* @return result
* @throws RpcException
*/
// 执行请求操作
Result invoke(Invocation invocation) throws RpcException;
}
进入org.apache.dubbo.rpc.protocol.AbstractInvoker#invoke
public Result invoke(Invocation inv) throws RpcException {
// 判断系统是否已经关闭
if (destroyed.get()) {
logger.warn("Invoker for service " + this + " on consumer " + NetUtils.getLocalHost() + " is destroyed, "
+ ", dubbo version is " + Version.getVersion() + ", this invoker should not be used any longer");
}
RpcInvocation invocation = (RpcInvocation) inv;
invocation.setInvoker(this);
// 设置所有的RPCContext中的附加信息
if (CollectionUtils.isNotEmptyMap(attachment)) {
invocation.addObjectAttachments(attachment);
}
Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
if (CollectionUtils.isNotEmptyMap(contextAttachments)) {
invocation.addAttachments(contextAttachments);
}
// 获取执行的模式
invocation.setInvokeMode(RpcUtils.getInvokeMode(url, invocation));
// 设置执行id,主要用于适配异步模式使用
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
// 交给子类进行真正的执行
AsyncRpcResult asyncResult;
try {
asyncResult = (AsyncRpcResult) doInvoke(invocation);
} catch (InvocationTargetException e) {
// 业务异常
Throwable te = e.getTargetException();
if (te == null) {
asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
} else {
if (te instanceof RpcException) {
((RpcException) te).setCode(RpcException.BIZ_EXCEPTION);
}
asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, te, invocation);
}
} catch (RpcException e) {
// RPC阶段出现了异常
if (e.isBiz()) {
asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
} else {
throw e;
}
} catch (Throwable e) {
asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
}
// 设置执行的结果信息
RpcContext.getContext().setFuture(new FutureAdapter(asyncResult.getResponseFuture()));
// 返回结果
return asyncResult;
}
进入子类dubboInvoker
org.apache.dubbo.rpc.protocol.dubbo.DubboInvoker#doInvoke
protected Result doInvoke(final Invocation invocation) throws Throwable {
RpcInvocation inv = (RpcInvocation) invocation;
final String methodName = RpcUtils.getMethodName(invocation);
inv.setAttachment(PATH_KEY, getUrl().getPath());
inv.setAttachment(VERSION_KEY, version);
// 传输的客户端
ExchangeClient currentClient;
if (clients.length == 1) {
currentClient = clients[0];
} else {
currentClient = clients[index.getAndIncrement() % clients.length];
}
try {
// 是否返回值,也就是相当于发送了一个指令,不在乎服务端的返回
// 通常适用于异步请求
boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
// 获取超时的配置
int timeout = getUrl().getMethodPositiveParameter(methodName, TIMEOUT_KEY, DEFAULT_TIMEOUT);
if (isOneway) {
// 如果不需要返回值信息(异步)
boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
// 发送命令
//最后通过netty或者mina等channel的实现类来send
currentClient.send(inv, isSent);
// 告知为异步的结果
return AsyncRpcResult.newDefaultAsyncResult(invocation);
} else {
// 获取真正执行的线程池(ThreadPool中的SPI)
ExecutorService executor = getCallbackExecutor(getUrl(), inv);
// 发送请求并且等待结果
CompletableFuture<AppResponse> appResponseFuture =
currentClient.request(inv, timeout, executor).thenApply(obj -> (AppResponse) obj);
// 在2.6.x中使用,设置完成的额结果信息
FutureContext.getContext().setCompatibleFuture(appResponseFuture);
// 创建新的结果信息并且返回
AsyncRpcResult result = new AsyncRpcResult(appResponseFuture, inv);
result.setExecutor(executor);
return result;
}
} catch (TimeoutException e) {
throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
} catch (RemotingException e) {
throw new RpcException(RpcException.NETWORK_EXCEPTION, "Failed to invoke remote method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
}
}