一、Dubbo提供的功能
- 基于接口的远程调用
- 容错和负载均衡
- 自动服务注册和发现
二、Dubbo的总体架构
Dubbo源码的包结构
- dubbo-admin:dubbo自带的控制台管理,用于服务治理和监控
- dubbo-cluster:集群模块,将多个服务提供方伪装为一个提供方,包括负载均衡、容错、路由等。
- dubbo-common:公共逻辑模块
- dubbo-config:配置模块,是Dubbo对外API,用户通过config使用Dubbo,隐藏Dubbo所有细节
- dubbo-containter:容器模块,以简单的Main加载Sping的启动。
- dubbo-filter:主要针对dubbo-rpc里面的Filter进行缓存和校验
- dubbo-monitor:主要统计服务的调用次数和调用时间
- dubbo-register:注册中心模块,基于注册中心下发地址的集群方式,以及对各种注册中心的抽象
- dubbo-remoting:远程通信模块,包括Netty等多种通信方式
- dubbo-rpc:远程调用模块,抽奖各种协议,已经动态代理。
Dubbo的分层
- Service层:这一层与业务实现相结合,根据具体业务实现服务提供者和消费者
- Config层:配置信息层,由spring解析服务提供者和消费者的配置信息,封装到ServiceConfig和ReferenceConfig中
- Proxy层:服务代理层,这一层主要结合SPI机制,动态选取不同的配置类
- Register层:服务注册层,主要负责注册与发现Dubbo服务,以及对Dubbo服务的监听
- Cluster层:服务集群层,负责服务的路由、负载以及失败重试策略
- Protocol层:协议层,在这层进行相关协议的转换与过滤
- Exchange层:封装请求响应模式
- Transport层:网络传输层,抽象Netty等,在这一层进行真正的数据传输
- Serialize层:序列化层,根据不同的协议对数据进行序列化
三、Dubbo Bean的加载
1、spring自定义标签的使用
在spring中完成一个自定义标签需要以下几步
- 设计配置属性和JavaBean
- 编写XSD文件
- 编写BeanDefinitionPaster标签解析类
- 在META-INF下定义spring.handlers和spring.schemas供spring读取
下面来实现spring标签
public class FeiConfig {
private String id;
private String path;
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://fei.ma/schema/fei"
targetNamespace="http://fei.ma/schema/fei">
<xsd:element name="config">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="path" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<!-- XML配置文件 -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:fei="http://fei.ma/schema/fei"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://fei.ma/schema/fei
http://fei.ma/schema/fei/fei.xsd">
<fei:config id="mafei1" path="com.fei.plug.FeiConfig"></fei:config>
<fei:config id="mafei2" path="com.fei.plug.FeiConfig"></fei:config>
</beans>
public class FeiBeanDefinitionParser implements BeanDefinitionParser {
public FeiBeanDefinitionParser() {
}
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
//解析xml内容
String id = element.getAttribute("id");
String path = element.getAttribute("path");
//注册beanDefine到spring容器
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(FeiConfig.class);
beanDefinition.setLazyInit(false);
beanDefinition.getPropertyValues().add("path", path);
parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
return beanDefinition;
}
}
public class FeiNamespaceHandler extends NamespaceHandlerSupport {
private Logger logger = LoggerFactory.getLogger(FeiNamespaceHandler.class);
@Override
public void init() {
logger.info("----{}------", "FeiNamespaceHandler");
//注意此处的config是xml中的标签
registerBeanDefinitionParser("config", new FeiBeanDefinitionParser());
}
}
spring.handler
http://fei.ma/schema/fei=com.fei.plug.FeiNamespaceHandler
spring.schemas
http://fei.ma/schema/fei/fei.xsd=META-INF/fei.xsd
这样spring标签就已经完成了下面我们来看看效果吧
自定义标签配置已经完成了。
2、再看看dubbo是如果实现的
从这段源码中可以看到dubbo的自定义标签有10个,所有的标签都统一使用DubboBeanDefinitionParser进行解析,基于一对一属性映射,将XML标签解析为Bean对象。这里分析了dubbo框架中的对象加载配置与加载的原理,并做了一个demo帮助大家理解。后面继续分析dubbo消费者与生产者的原理与实现。