本节我们从整体上来看看 Dubbo 的分层架构设计,架构分层是一个比较经典的模式,比如网络中的7层协议,每层执行固定的功能,上层依赖下层提供的功能,下层对上层提供功能,下层的改变对上层不可见,并且每层都是一个可被替换的组件。
如下图是 Dubbo 官方提供的Dubbo的整体架构图:
图2.1.1
Dubbo 官方提供的该架构图很复杂,一开始我们没必要深入细节,下面我们简单讲解下其中的主要模块:
其中 Service 和 Config 层为 API接口层,是为了方便的让Dubbo使用方发布服务和引用服务;对于服务提供方来说需要实现服务接口,然后使用 ServiceConfig API 来发布该服务;对于服务消费方来说需要使用ReferenceConfig 对服务接口进行代理。Dubbo服务发布与引用方可以直接初始化配置类,也可以通过 Spring 配置自动生成配置类。
其它各层均为 SPI层,SPI 意味着下面各层都是组件化可以被替换的,这也是 Dubbo 设计的比较好的一点。Dubbo 增强了 JDK 中提供的标准 SPI 功能,在 Dubbo 中除了 Service 和 Config 层外,其它各层都是通过实现扩展点接口来提供服务的;Dubbo 增强的 SPI 增加了对扩展点 IoC 和 AOP 的支持,一个扩展点可以直接 setter 注入其它扩展点;并且不会一次性实例化扩展点的所有实现类,这避免了当扩展点实现类初始化很耗时,但当前还没用上它的功能时仍进行加载实例化,浪费资源的情况;增强的 SPI 是在具体用某一个实现类的时候才对具体实现类进行实例化。后续会具体讲解 Dubbo 增强的 SPI 的实现原理。
Proxy 服务代理层:该层主要是对服务消费端使用的接口进行代理,把本地调用透明的转换为远程调用;另外对服务提供方的服务实现类进行代理,把服务实现类转换为 Wrapper 类,这是为了减少反射的调用,后面会具体讲解到。Proxy层的SPI扩展接口为 ProxyFactory,Dubbo 提供的实现主要有 JavassistProxyFactory(默认使用)和 JdkProxyFactory,用户可以实现ProxyFactory SPI接口,自定义代理服务层的实现。
Registry 服务注册中心层:服务提供者启动时候会把服务注册到服务注册中心,消费者启动时候会去服务注册中心获取服务提供者的地址列表,Registry层主要功能是封装服务地址的注册与发现逻辑,扩展接口 Registry 对应的扩展实现为 ZookeeperRegistry、RedisRegistry、MulticastRegistry、DubboRegistry等。扩展接口 RegistryFactory 对应的扩展接口实现为 DubboRegistryFactory、DubboRegistryFactory、RedisRegistryFactory、ZookeeperRegistryFactory。另外该层扩展接口Directory实现类有RegistryDirectory、StaticDirectory用来透明的把invoker列表转换为一个invoker;用户可以实现该层的一系列扩展接口,自定义该层的服务实现。
Cluster 路由层:封装多个服务提供者的路由规则、负载均衡、集群容错的实现,并桥接服务注册中心;扩展接口 Cluster 对应的实现类有 FailoverCluster(失败重试)、FailbackCluster(失败自动恢复)、FailfastCluster(快速失败)、FailsafeCluster(失败安全)、ForkingCluster(并行调用)等;负载均衡扩展接口 LoadBalance 对应的实现类为 RandomLoadBalance(随机)、RoundRobinLoadBalance(轮询)、LeastActiveLoadBalance(最小活跃数)、ConsistentHashLoadBalance(一致性hash)等。用户可以实现该层的一系列扩展接口,自定义集群容错和负载均衡策略。
Monitor 监控层:用来统计RPC 调用次数和调用耗时时间,扩展接口为 MonitorFactory,对应的实现类为 DubboMonitorFactroy。用户可以实现该层的MonitorFactory扩展接口,实现自定义监控统计策略。
Protocol 远程调用层:封装 RPC 调用逻辑,扩展接口为 Protocol, 对应实现有 RegistryProtocol、DubboProtocol、InjvmProtocol 等。
Exchange 信息交换层:封装请求响应模式,同步转异步,扩展接口 Exchanger,对应扩展实现有 HeaderExchanger 等。
Transport 网络传输层:抽象 mina 和 netty 为统一接口。扩展接口为 Channel,对应实现有 NettyChannel(默认)、MinaChannel 等;扩展接口Transporter对应的实现类有GrizzlyTransporter、MinaTransporter、NettyTransporter(默认实现);扩展接口Codec2对应实现类有DubboCodec、ThriftCodec等
Serialize 数据序列化层:提供可以复用的一些工具,扩展接口为 Serialization,对应扩展实现有 DubboSerialization、FastJsonSerialization、Hessian2Serialization、JavaSerialization等,扩展接口ThreadPool对应扩展实现有 FixedThreadPool、CachedThreadPool、LimitedThreadPool 等。
综上可知Dubbo的分层架构使得Dubbo的每层的功能都是可被替换的,这使得Dubbo的扩展性极强,上面说了那么多关于扩展点的东西,那么具体什么是扩展点呢,下面看下 Dubbo 扩展点一个简单例子。以扩展点 Protocol 为例:
@SPI("dubbo")
public interface Protocol {
...
}
扩展点接口的类上面都含有@SPI注解,这里注解里面的"dubbo"说明Protocol扩展接口SPI的默认实现是DubboProtocol。
如果我们想自己写一个 Protocol 扩展接口的实现类,那么我们需要在实现类所在的 Jar 包内的 META-INF/dubbo/
目录下创建一个名字为 org.apache.dubbo.rpc.Protocol 的文本文件,然后配置它的内容为:
myprotocol=com.alibaba.user.MyProtocol
假设该实现类 MyProtocol 的内容如下:
package com.alibaba.user;
public class MyProtocol implemenets Protocol {
// ...
}
那么如何使用我们自定义的扩展实现呢?Dubbo 配置模块中,扩展点均有对应配置属性或标签,如下代码通过配置标签方式指定使用哪个扩展实现:
<dubbo:protocol name="myprotocol" />
注意这里的 name 必须与 jar 包内 META-INF/dubbo/
目录下 org.apache.dubbo.rpc.Protocol 文件中的等号左侧的key的名字一致。
如上内容摘自《深度剖析Apache Dubbo核心技术内幕》,更多内容单击阅读原文查看。
本文分享自微信公众号 - 技术原始积累(gh_805ebfd2deb0)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。