【Dubbo】研究Dubbo框架实现原理,我们到底能学到什么?
首先(分层架构)我们可以学习和深刻体会到分层架构带来的好处,Dubbo框架在整体是分为了业务层(Business)、RPC层、远程调用(Remoting)层
- 业务层提供API让使用者方便的发布与引用服务
- RPC层则是对服务注册与发现、服务代理、路由、负载均衡等功能的封装,该层又可以被划分为好多层
- 远程调用层则是对网络传输与请求数据序列/反序列化等的抽象
使用(分层架构)可以保证下层的改变对上层不可见,并且可以实现关注点分离,比如使用者使用Dubbo时候只关心如何使用业务层的API来发布与引用服务,而不需要关心RPC层的实现,当新版Dubbo升级了RPC层的逻辑时候,使用方只需要升级Dubbo的版本就可以了,这是因为RPC层的修改对业务层使用者来着是透明的。
我们(增强型SPI、AOP)也可以学习到好的框架应该具有可扩展性
- Dubbo就是一个扩展性极强的框架,其RPC层中的所有组件都是基于SPI扩展接口实现的,每个组件都是可以被替换的;并且增强SPI不会一次性实例化扩展点的所有实现类,这避免了当扩展点实现类初始化很耗时,但当前还没用上它的功能时仍进行加载实例化,浪费资源的情况;增强的 SPI 是在具体用某一个实现类的时候才对具体实现类进行实例化。
- Dubbo 增强了 JDK 中提供的标准 SPI 功能,并且增加了对扩展接口的IoC (一个扩展接口可以直接 setter 注入其它扩展接口)
- AOP 的支持(可以使用Wrapper类对扩展接口进行功能增强)
作为(集群容错)高可用分布式RPC框架,其自身必须具有容错能力,以便提高系统的可用性;Dubbo框架则提供了分布式系统中常见的集群容错策略,并且提供了扩展接口,让使用方方便的定制自己的集群容错策略,通过研究Dubbo框架提供的集群容错策略,可以让我们对分布式系统中的容错技术有深入的理解。
在分布式系统中(负载均衡、路由规则)每个微服务都是以集群的方式部署,那么当我们访问一个具体服务时候到底访问哪一台机器提供的服务呢?这就是分布式系统中负载均衡器与路由规则要做的事情
- 作为分布式RPC框架,其自身也必须具有负载均衡的能力,Dubbo框架则提供了分布式系统中常见的负载均衡策略,并且提供了扩展接口,让使用方方便的定制自己的负载均衡策略;
- 另外路由规则提供了服务治理的一种策略,在Dubbo中我们可以通过管理控制台来配置路由规则,让消费者只可访问配置的服务提供者;通过研究Dubbo框架提供的负载均衡与路由策略,可以让我们对分布式系统中的负载均衡技术与路由规则有深入的理解。
在分布式系统(注册中心)中当我们要消费某个服务时候,如何找到其地址是一个要解决的问题,在分布式RPC中一个通用解决方案是引入服务注册中心,当服务提供者启动时候会自动把自己的服务注册到服务注册中心,当消费者启动时会去服务注册中心订阅自己感兴趣的服务的地址列表;在Dubbo框架中则提供了扩展接口来方便的让我们使用zookeeper、redis等作为服务注册中心,通过研究Dubbo原理,我们可以深刻理解服务提供方到底是如何把服务注册到服务注册中心的,以及服务消费端如何动态的感知服务提供方地址列表变化的。
所有RPC框架(透明调用)都要解决的一个问题是,如何让使用者无感知的发起远程过程调用,也就是让使用者在发起远程调用时候,有和本地调用一样的体验;Dubbo框架和其他RPC框架一样采用代理来实现该能力,在Dubbo框架中扩展接口Proxy就是专门来做代理使用的,并且其提供了扩展接口的JDK动态代理与Cglib的实现;研究Dubbo的原理,我们可以学习到消费端如何对服务接口进行的代理以实现透明调用,服务提供端如何使用代理与JavaAssist技术减少反射调用开销的。
在Dubbo(网络通信)的分层架构中Transport 网络传输层把 mina 和 netty 抽象为统一接口,并且默认情况下其使用Netty作为底层网络通信,通过研究Dubbo,我们可以学习到Dubbo的网络协议帧是如何设计的;服务消费端如何启动Netty客户端的,如何把rpc请求封装为协议帧并序列化,然后通过Netty客户端发起网络请求的;服务提供端又是如何启动Netty服务器进行服务监听的,如何处理经典的半包、粘包问题的,如何把接受到的二进制包转换为Dubbo协议帧,并反序列化为POJO对象的;另外使用Netty时都说不要在ChannelHandler中做阻塞的事情,以免阻塞了IO线程,使其他请求得不到及时处理,那么这到底是什么意思呢?研究完Dubbo的线程模型你就会明白了。
对于(异步调用)网络请求来说,同步调用时比较直截了当的,但是同步调用意味着当前发起请求的调用线程在远端机器返回结果前必须阻塞等待,这明显很浪费资源。好的做法应该是发起请求的调用线程发起请求后,注册一个回调函数,然后马上返回去做其他事情,当远端把结果返回后再使用IO线程执行回调函数,也就是发起方实现了异步调用,调用线程不会被阻塞。Dubbo则基于Netty的异步非阻塞能力与JDK8中的CompletableFuture轻松实现RPC请求的异步调用,提高了资源利用率;通过研究Dubbo的实现原理,我们可以对异步编程带来的好处以及实现原理有深刻的体会。
总之研究透彻Dubbo框架原理实现后,你会对分布式系统中的很多技术点有深入的理解;而我坚信分布式系统是应用的发展方向,因为随着业务规模的增大,为了保障系统的可伸缩性、高可用性,系统必然朝着分布式方向发展;所以如果能掌握一些分布式系统中优秀RPC框架的原理以及实现细节,无论是现在还是将来都将会成为自己区别于他人的核心竞争力。