本文基于 Dubbo 2.6.1 版本,望知悉。
友情提示,【配置】这块的内容,会相对比较枯燥。所以,如果看到一些很难懂的地方,建议先跳过。
对于 Dubbo ,重点是要去理解,多协议、RPC、容错等等模块,而不是【配置】。
😈 估计好多胖友被【配置】这章劝退了把???
1. 概述
本文接 《API 配置(一)之应用》 ,分享服务提供者相关的配置:包括 provider-config 和 sub-config 部分。
- 黄框部分,provider-side
- 其他部分,sub-config
还是老样子,我们先来看一段 《Dubbo 用户指南 —— API 配置》 ,服务提供者的初始化代码:
// 服务实现 |
- 相比 ReferenceConfig 的初始化,会多创建 ProtocolConfig 对象,设置到 ServiceConfig 对象中。
友情提示:本文前面部分会比较琐碎,重点在 「8. ServiceConfig」 部分。
2. ProtocolConfig
com.alibaba.dubbo.config.ProtocolConfig
,服务提供者协议配置。
- 具体属性的解释,参见 《Dubbo 用户指南 —— dubbo:protocol》 文档。
3. AbstractMethodConfig
com.alibaba.dubbo.config.AbstractMethodConfig
,方法级配置的抽象类。
- 部分属性的解释,参见 《Dubbo 用户指南 —— dubbo:method》 文档。
4. MethodConfig
com.alibaba.dubbo.config.MethodConfig
,继承 AbstractMethodConfig ,方法级配置。
- 具体属性的解释,《Dubbo 用户指南 —— dubbo:method》 文档。
5. AbstractInterfaceConfig
com.alibaba.dubbo.config.AbstractInterfaceConfig
,继承 AbstractMethodConfig ,抽象接口配置类。
- 具体属性的解释,需要寻找在 《Dubbo 用户指南 —— dubbo:service》 或 《Dubbo 用户指南 —— dubbo:reference》 文档。
- 下面的方法,会在 「8. ServiceConfig」 的初始化被调用,胖友可需要的时候,点击查看。
#checkApplication()
方法,校验 ApplicationConfig 配置。实际上,该方法会初始化 ApplicationConfig 的配置属性。- 🙂 直接点击方法查看,较为简单,已经添加详细注释。
#checkRegistry()
方法,校验 RegistryConfig 配置。实际上,该方法会初始化 RegistryConfig 的配置属性。- 🙂 直接点击方法查看,较为简单,已经添加详细注释。
#checkInterfaceAndMethods(interfaceClass, methods)
方法,校验接口和方法。主要是两方面:- 1、 接口类非空,并是接口
- 2、 方法在接口中已定义
- 🙂 直接点击方法查看,较为简单,已经添加详细注释。
#checkStubAndMock(interfaceClass)
方法,校验 Stub 和 Mock 相关的配置。- 以上未列举的
#loadRegistries(provider)
和#loadMonitor(registryURL)
方法,在后续文章需要使用到时,在详细分享。
6. AbstractServiceConfig
com.alibaba.dubbo.config.AbstractServiceConfig
,实现 AbstractInterfaceConfig ,抽象服务配置类。
- 具体属性的解释,需要寻找在 《Dubbo 用户指南 —— dubbo:service》 或 《Dubbo 用户指南 —— dubbo:provider》 文档。
7. ProviderConfig
com.alibaba.dubbo.config.ProviderConfig
,实现 AbstractServiceConfig ,服务提供者缺省值配置。
- 具体属性的解释,参见 《Dubbo 用户指南 —— dubbo:provider》 文档。
8. ServiceConfig
com.alibaba.dubbo.config.ServiceConfig
,服务提供者暴露服务配置类。
- 具体属性的解释,参见 《Dubbo 用户指南 —— dubbo:service》 文档。
下面,我们进入正戏。
在文初的 ServiceConfig 的初始化示例代码中,最后调用的是 ServiceConfig#export()
方法。从方法的命名,我们可以看出,暴露服务。该方法主要做了如下几件事情:
- 进一步初始化 ServiceConfig 对象。
- 校验 ServiceConfig 对象的配置项。
- 使用 ServiceConfig 对象,生成 Dubbo URL 对象数组。
- 使用 Dubbo URL 对象,暴露服务。
😈 本文重点在服务提供者相关的配置,因此只解析 1+2+3 部分( 不包括 4 )。代码如下:
1: public synchronized void export() { |
- 第 2 至 10 行:当
export
或delay
未配置时,从 ProviderConfig 对象读取。 - 第 11 至 14 行:当配置不需要暴露服务(
export = false
)时,直接返回。 - 第 17 至 22 行:当配置延迟暴露(
delay > 0
)时,使用delayExportExecutor
延迟调度,调用#doExport()
方法。 - 第 23 至 26 行:立即暴露,调用
#doExport()
方法。
#doExport()
方法,代码如下:
1: protected synchronized void doExport() { |
- 第 2 至 9 行:检查是否可以暴露。若可以,标记已经暴露(
exported = true
)。 - 第 10 至 13 行:校验接口名
interfaceName
非空。 - 第 15 行:调用
#checkDefault()
方法,读取属性配置( 环境变量 + properties 属性 )到 ProviderConfig 对象。- 关于“属性配置” ,在 《精尽 Dubbo 源码解析 —— 属性配置》 详细解析。
- 🙂 直接点击方法查看,较为简单,已经添加详细注释。
- 第 16 至 33 行:从 ProviderConfig 对象中,读取
application
、module
、registries
、monitor
、protocols
对象。 - 第 34 至 42 行:从 ModuleConfig 对象中,读取
registries
、monitor
对象。 - 第 43 至 51 行:从 ApplicationConfig 对象中,读取
registries
、monitor
对象。 - 第 52 至 57 行:泛化接口的实现。
- 第 58 至 70 行:普通接口的实现。
- 第 60 至 64 行:根据
interfaceName
,获得对应的接口类,并赋值给interfaceClass
。 - 第 66 行:调用
#checkInterfaceAndMethods(interfaceClass, methods)
方法,检查接口和方法。- 🙂 本文有已经有这个方法的解析。
- 第 68 行:调用
#checkRef()
方法,校验指向的 Service 对象。 - 第 69 行:标记
generic
为非泛化实现。
- 第 60 至 64 行:根据
- 第 71 至 86 行:处理服务接口客户端本地代理(
local
)相关。实际目前已经废弃,此处主要用于兼容,使用stub
属性,参见AbstractInterfaceConfig#setLocal(local)
方法的注释说明。 - 第 87 至 102 行:处理服务接口客户端本地代理(
stub
属性,参见AbstractInterfaceConfig#setLocal(local)
)相关。 - 第 104 行:调用
#checkApplication()
方法,校验 ApplicationConfig 配置。- 🙂 直接点击方法查看,较为简单,已经添加详细注释。
- 第 106 行:调用
#checkRegistry()
方法,校验 RegistryConfig 配置。- 🙂 直接点击方法查看,较为简单,已经添加详细注释。
- 第 108 行:调用
#checkProtocol()
方法,校验 ProtocolConfig 配置数组。- 🙂 直接点击方法查看,较为简单,已经添加详细注释。
- 第 110 行:调用
#appendProperties(config)
方法,读取属性配置( 环境变量 + properties 属性 )到 ServiceConfig 对象(自己)。 - 第 112 行:调用
#checkStubAndMock(interfaceClass)
方法,校验 Stub 和 Mock 相关的配置。 - 第 113 至 116 行:服务路径
path
为空时,缺省为接口名。 - 第 118 行:调用
#doExportUrls()
方法,暴露服务。此方法包含了我们上述的 3+4 部分。 - 第 119 至 121 行:// TODO 芋艿,等待 qos
因为本文不分享 4 部分,所以下面我们只看 #doExportUrls()
方法中,调用 #doExportUrlsFor1Protocol(protocolConfig, registryURLs)
方法,和 3 有关的部分。代码如下:
1: private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) { |
- 第 2 至 6 行:协议名空时,缺省
"dubbo"
。 - 第 9 行:创建参数集合
map
,用于下面创建 Dubbo URL 的parameters
属性。 - 第 10 至 15 行:将
side
dubbo
timestamp
timestamp
pid
添加到map
中。 - 第 16 至 21 行:调用
#appendParameters(map, config)
方法,将各种配置对象添加到map
中。- 🙂
#appendParameters(map, config)
方法,在 《API 配置(一)之应用》
- 🙂
- 第 22 至 83 行:调用 MethodConfig 对象数组,添加到
map
中。- 目的是将每个 MethodConfig 和其对应的 ArgumentConfig 对象数组,添加到
map
中。 - 🙂 代码比较冗长,胖友耐心看注释,建议进行调试每种情况。
- 目的是将每个 MethodConfig 和其对应的 ArgumentConfig 对象数组,添加到
- 第 85 至 102 行:将
generic
methods
revision
到map
中。revision
,可能比较难理解,在 「10. Version」 详细解析。
- 第 103 至 110 行:将
token
添加到map
中。 - 第 111 至 115 行:当协议为
injvm
时,添加notify = false
到map
中,表示不注册,不通知。 - 第 116 至 120 行:获得
contextPath
,基础路径,即java web应用中常说的context path 。 - 第 123 行:调用
#this.findConfigedHosts(protocolConfig, registryURLs, map)
方法,获得注册到注册中心的服务提供者 Host 。- 《Dubbo 用户指南 —— 主机绑定》
- 《dubbo注册服务IP解析异常及IP解析源码分析》
- 指定服务注册地址,参见 dubbo-docker-sample 示例项目。
- 🙂 代码比较冗长,胖友耐心看注释,建议进行调试每种情况。
- 第 124 行:调用
#findConfigedHosts(protocolConfig, name, map)
方法,获得注册到注册中心的服务提供者 Port 。- 🙂 代码比较冗长,胖友耐心看注释,建议进行调试每种情况。
- 第 127 行:创建 Dubbo URL 。
- 第 129 至 134 行:配置规则,后续详细解析。
- 第 136 行:省略【服务暴露】逻辑。
9. 为什么继承???
我们以 ServiceConfig 和 ProviderConfig 来举例子,两者都继承 AbstractServiceConfig。
从属性上,两者有相同的属性,例如 group
/ version
。
同时,也存在着一些差异,例如 ServiceConfig.interfaceName
/ ProviderConfig.host
。
另外,我们在看看 ServiceConfig 和 MethodConfig ,两者都继承 AbstractMethodConfig。
在 ServiceConfig 中,可以配置下属所有方法的 retries
次数,也可以在 MethodConfig 中自定义 retries
次数。
通过继承,获得相同的属性。
10. Version
Version#getVersion(cls, defaultVersion)
方法,获得版本号。代码如下:
1: public static String getVersion(Class<?> cls, String defaultVersion) { |
- 第 3 至 7 行:从
MAINFEST.MF
中获得版本号。以 spring-boot-starter-1.5.10.RELEASE.jar 举例子:MAINFEST.MF
- 第 8 至 36 行:若获取不到,从 jar 包命名中可能带的版本号作为结果。例如上面的例子,
1.5.10.RELEASE
。 - 第 38 行:返回版本号。若不存在,返回默认版本号。
666. 彩蛋
比较冗长。
是不是看的一脸蒙圈。
没关系滴,随着对 Dubbo 源码的愈发了解,配置类很多疑惑的地方,会慢慢解开。
裤子都脱了,果敢的继续加油!