第2章 Dubbo框架内核原理剖析
2.1 Dubbo分层架构概述
本节我们从整体上来看看Dubbo的分层架构设计,架构分层是一个比较经典的模式,比如网络中的7层协议,每层执行固定的功能,上层依赖下层提供的功能,下层的改变对上层不可见等,并且每层都是一个可被替换的组件。
图2.1是Dubbo官方提供的Dubbo整体架构图。
图2.1
Dubbo官方提供的该架构图很复杂,一开始我们没必要深入细节,下面我们简单讲解一下其中的主要模块。
· Service和Config层为API接口层,是为了让Dubbo使用方方便地发布服务和引用服务;对于服务提供方来说需要实现服务接口,然后使用ServiceConfig API来发布该服务;对于服务消费方来说需要使用ReferenceConfig对服务接口进行代理。Dubbo服务发布与引用方可以直接初始化配置类,也可以通过Spring配置自动生成配置类。
· 其他各层均为SPI(Service Provider Interface,服务提供者接口)层,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"说明Protocol扩展接口SPI的默认实现是DubboProtocol。
如果我们想自己写一个Protocol扩展接口的实现类,那么我们需要在实现类所在的Jar包内的META-INF/dubbo/目录下创建一个名字为org.apache.dubbo.rpc.Protocol的文本文件,然后配置它的内容为:
假设该实现类MyProtocol的内容如下:
那么如何使用我们自定义的扩展实现呢?在Dubbo配置模块中,扩展点均有对应配置属性或标签,如下代码通过配置标签方式指定使用哪个扩展实现:
注意这里的name必须与Jar包内META-INF/dubbo/目录下的org.apache.dubbo.rpc.Protocol文件中的等号左侧的key的名字一致。