接触过dubbo的同学,见到下面的配置都非常熟悉了,含义不多说。
本章主要目的,对DUBBO配置原理进行剖析。
代码语言:javascript复制<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
">
<!-- 当前应用信息配置 -->
<dubbo:application name="demo-provider" />
<!-- 连接注册中心配置 -->
<dubbo:registry address="N/A" />
<!-- 暴露服务协议配置 -->
<dubbo:protocol name="dubbo" port="20813" />
<!-- 暴露服务配置 -->
<dubbo:service interface="com.alibaba.dubbo.config.spring.api.DemoService"
ref="demoService" />
<bean id="demoService"
class="com.alibaba.dubbo.config.spring.impl.DemoServiceImpl" />
</beans>
spring加载xml或annotation,第一步需要将这些配置元数据载入spring容器中,首先确认下这些<dubbo:*>标签,对应的数据载体类。
1. 认识标签对应的数据载体
首先,找到dubbo-configdubbo-config-springsrcmainresourcesMETA-INFspring.handlers文件。找到负责具体解析dubbo标签的handler。
代码语言:javascript复制http://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
查看DubboNamespaceHandler 代码
代码语言:javascript复制public class DubboNamespaceHandler extends NamespaceHandlerSupport {
static {
Version.checkDuplicate(DubboNamespaceHandler.class);
}
public void init() {
registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(AnnotationBean.class, true));
}
}
不再进行分析具体代码了。这部分内容和spring的范畴。
1.1对应表格
标签 | 数据配置类 | 含义 |
---|---|---|
<dubbo:application name="demo-provider" /> | ApplicationConfig | 应用级别 |
<dubbo:registry address="N/A" /> | RegistryConfig | 注册中心 |
<dubbo:protocol name="dubbo" port="20813" /> | ProtocolConfig | 协议 |
<dubbo:service interface=".." ref="demoService" /> | ServiceBean | 服务 |
module | ModuleConfig | 模块 |
monitor | MonitorConfig | 监控 |
consumer | ConsumerConfig | 消费者 |
provider | ProviderConfig | 提供者 |
reference | ReferenceBean | 服务引用 |
1.2 Config层次结构
现在,应该很容易找出声明服务的配置入口是哪一个配置类:ServiceBean。其他的类,可以暂时靠边站。其他的配置信息(如ApplicationConfig,RegistryConfig..)主要涉及配置元数据,会决定dubbo运行时行为,但对梳理剖析DUBBO流程不太重要。
2.认识ServiceBean
ServiceBean是声明暴露Service的一个重要组件,需要重点关注。
2.1结构树
还是要感谢spring提供的优秀扩展特性,ServiceBean实现了很多spring的扩展接口。现在,把重点放在AbstractConfig继承树这个层次上。
AbstractConfig提供基础支持方法,比如appendAttributes,check*系列方法等。
AbstractMethodConfig,封装了一些方法级别的相关属性
AbstractInterfaceConfig:封装了接口契约需要的属性
AbstractServiceConfig: 服务相关属性(重在使用运维级别)
ServiceConfig:主要包含一些运行时数据
AbstractMethodConfig 属性片段
代码语言:javascript复制public abstract class AbstractMethodConfig extends AbstractConfig {
// 远程调用超时时间(毫秒)
protected Integer timeout;
// 重试次数
protected Integer retries;
// 最大并发调用
protected Integer actives;
// 负载均衡
protected String loadbalance;
// 是否异步
protected Boolean async;
// 异步发送是否等待发送成功
protected Boolean sent;
// 服务接口的失败mock实现类名
protected String mock;
// 合并器
protected String merger;
// 服务接口的失败mock实现类名
protected String cache;
// 服务接口的失败mock实现类名
protected String validation;
..
}
AbstractInterfaceConfig.java属性片段
代码语言:javascript复制public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
private static final long serialVersionUID = -1559314110797223229L;
// 服务接口的本地实现类名
protected String local;
// 服务接口的本地实现类名
protected String stub;
// 服务监控
protected MonitorConfig monitor;
// 代理类型
protected String proxy;
// 集群方式
protected String cluster;
// 过滤器
protected String filter;
// 监听器
protected String listener;
// 负责人
protected String owner;
// 连接数限制,0表示共享连接,否则为该服务独享连接数
protected Integer connections;
// 连接数限制
protected String layer;
// 应用信息
protected ApplicationConfig application;
// 模块信息
protected ModuleConfig module;
// 注册中心
protected List<RegistryConfig> registries;
// callback实例个数限制
private Integer callbacks;
// 连接事件
protected String onconnect;
// 断开事件
protected String ondisconnect;
// 服务暴露或引用的scope,如果为local,则表示只在当前JVM内查找.
private String scope;
...
}
AbstractServiceConfig 属性片段
代码语言:javascript复制public abstract class AbstractServiceConfig extends AbstractInterfaceConfig {
private static final long serialVersionUID = 1L;
// 服务版本
protected String version;
// 服务分组
protected String group;
// 服务是否已经deprecated
protected Boolean deprecated;
// 延迟暴露
protected Integer delay;
// 是否暴露
protected Boolean export;
// 权重
protected Integer weight;
// 应用文档
protected String document;
// 在注册中心上注册成动态的还是静态的服务
protected Boolean dynamic;
// 是否使用令牌
protected String token;
// 访问日志
protected String accesslog;
// 允许执行请求数
private Integer executes;
protected List<ProtocolConfig> protocols;
// 是否注册
private Boolean register;
...
}
ServiceConfig.java属性片段
代码语言:javascript复制public class ServiceConfig<T> extends AbstractServiceConfig {
private static final long serialVersionUID = 3033787999037024738L;
private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
private static final Map<String, Integer> RANDOM_PORT_MAP = new HashMap<String, Integer>();
// 接口类型
private String interfaceName;
private Class<?> interfaceClass;
// 接口实现类引用
private T ref;
// 服务名称
private String path;
// 方法配置
private List<MethodConfig> methods;
private ProviderConfig provider;
private final List<URL> urls = new ArrayList<URL>();
private final List<Exporter<?>> exporters = new ArrayList<Exporter<?>>();
private transient volatile boolean exported;
private transient volatile boolean unexported;
private transient volatile boolean generic;
...
}
注意ServiceConfig 有几个很服务声明有关的属性
代码语言:javascript复制 private final List<Exporter<?>> exporters = new ArrayList<Exporter<?>>();
private transient volatile boolean exported;
private transient volatile boolean unexported;
这是剖析服务声明的入口。