框架设计
概念
Dubbo是一种分布式框架,致力于提供性能和透明的RPC远程服务调用方案,以及SOA服务治理方案。
整体设计:
Dubbo拓扑结构
名词解释
1、Registry:注册中心,一般是使用Zookeeper作为注册中心。用于服务的注册与发现。
2、Provider:暴露服务的服务提供方,会将服务注册到Registry注册中心。
3、Consumer:消费者,调用远程服务的一方,Registry会向消费者发送提醒,提醒已经注册的服务,Consumer负责询问,一旦有服务可用,会向Provider通过RPC的方式调用(invoke)Provider的服务。
4、Monitor,监控中心,统计服务的调用次数和调用时间。
5、Scheduler调度器,基于访问压力自增减服务提供者
6、Container服务运行容器
调用关系说明:
服务容器负责启动、加载、运行服务提供者;服务提供者在启动时,向注册中心注册自己的服务;服务消费者在启动时,向注册中心订阅自己所需要的服务;注册中心返回服务提供者地址列表给服务消费者,如有变更,注册中心将基于长连接推送变更数据给消费者。服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。服务消费者和服务提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
特性一览:
面向接口代理的高性能RPC调用提供高性能的基于代理的远程调用能力,服务以接口为粒度,为开发者屏蔽远程调用的底层细节。
2、服务自动注册与发现
提供多种服务注册中心机制,服务上下线实时感知。
3、运行期流量调度
内置条件、脚本等路由策略,通过配置不同的路由规则,轻松实现灰度发布,同机房优先等功能。
4、智能负载均衡
内置多种负载均衡策略,智能感知下游节点健康状况,显著减少调用延迟,提高系统吞吐量。
5、高度可扩展能力
遵循微内核加插件设计的原则,所有核心能力如Protocol、Transport、Serialization被设计扩展点,平等对待内置实现和第三方实现。
6、可视化服务治理与运维
提供丰富治理与运维工具:随时查询服务元数据、服务健康状态以及调用统计、实施下发路由策略、调整配置参数。
整体设计:
图例说明:
图中的蓝色背景为服务消费者方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为双方都用到的接口。图中从上至下分为十层,各层均为单向依赖,右边的黑色箭头代表层之间的依赖关系,每一层都可以剥离上层被复用,其中Service层和Config层为API。其他各层为SPI(串行外设接口)。图中绿色小块的为扩展接口,蓝色小块为实现类,图中只显示用于联络各层的实现类。图中蓝色虚线为初始化过程,即启动时组装链,红色实现为方法调用过程,即运行时调用链,紫色三角箭头为继承,可以把子类看作父类的同一个节点,线上的文字为调用的方法。
各层说明
config配置层:对外设置接口,以ServiceConfig、ReferenceConfig为中心,可以直接初始化配置类,也可以通过spring解析服务配置生成配置类。proxy服务代理层:服务接口透明代理,生成服务的客户端stub和服务端Skeleton,以ServiceProxy为中心,扩展接口为ProxyFactory。cluster路由层:封装多个提供者的路由及负载均衡,并桥接注册中心,以Invoker为中心,扩展接口为Cluster、Directory、Router、LoadBalancemonitor监控层:RPC调用次数和调用时间监控,以Statistics为中心,扩展接口为MonitorFactory、Monitor、MonitorService。protocol远程调用层:封装RPC调用,以Invocation、Result为中心,扩展接口为Protocol、Invoker、Exporterexchange信息交换层:封装请求响应模式,同步转异步,以Request、Response为中心,扩展接口为Exchange、ExchangeChannel、ExchangeClient、ExchangeServertransport网络传输层:抽象Mina和Netty为统一接口,以Message为中心,扩展为Channel 、Transport、Client、Server、Codecserialize数据序列化层:可复用一些工具,扩展接口为Serialization,ObjectInput、ObjectOutput、ThreadPool
关系说明
在RPC中,Protocol是核心层,也就是只要有Protocol+Invoker+Export就可以完成非透明的RPC调用,然后在Invoker的主过程上Filter拦截点。图中的Consumer和Provider是抽象概念,只是想让看图者更直观的了解哪些分类分属于客户端与服务器端,不用Client和Server的原因是Dubbo在很多场景下都使用Provider、Consumer、Registry、Monitor划分逻辑拓扑节点,保持概念统一。而Cluster是外围概念,所以Cluster的目的是将多个Invoker伪装成一个Invoker,这样其他人只要关注Protocol层Invoker即可,加上Cluster或者去掉Cluster对其他曾都不会造成影响,因为只有一个提供者时,是不需要Cluster的。Proxy层封装了所有接口的透明代理,而在其它层都以Invoker为中心,只有到了暴露给用户使用时,才用Proxy将所有Invoker转成接口,或将接口实现转成Invoker,也就是去掉Proxy层RPC是可以RUN的,只是不那么透明,不那么看起来像调用本地服务一样调用远程服务。而Remoting实现是Dubbo协议的实现,如果你选择RMI协议,整个Remoting都不会用上,Remoting内部再划分为Transport传输层和Exchange信息交换层,Transport层只负责单向消息传输,是对Mina、Netty、Grizzly的抽象,它可以扩展UDP传输,而Exchange层是在传输层之上封装了Request-Response语义。Registry和Monitor实际上不算一层,而是一个独立的节点,只是为了全局概览,用层的方式画在一起。
模块分包
模块说明:
dubbo-common公共逻辑模块:包括Util类和通用模型dubbo-remoting远程通讯模块:相当于Dubbo协议的实现,如果RPC用RMI协议则不需要使用此包;dubbo-rpc远程调用模块:抽象各种协议,以及动态代理,只包含一对一的调用,不关心集群管理。dubbo-cluster集群模块:将多个服务提供方伪装为一个提供方,包括负载均衡,容错。路由等。集群的地址可以是静态配置的,也可由注册中心下发;dubbo-registry注册中心模块:基于注册中心下发地址的集群方式,以及对各种注册中心的抽象;dubbo-monitor监控模块:统计服务调用次数,调用时间的,调用链跟踪的服务。dubbo-config配置模块:是Dubbo对外的API,用户通过Config使用Dubbo,隐藏Dubbo所有细节。dubbo-container容器模块:是一个Standlone的容器,以简单的Main加载Spring启动,因为服务通常不需要Tomcat/Jboss等Web容器的特性,没必要用Web容器去加载服务。
整体上按照分层结构进行分包,与分层的不同点在于:
container为服务容器,用于部署运行服务,没有在层中划出;protocol层和proxy层都是放在rpc模块中,这两层是rpc的核心,在不需要集群也就是只有一个提供者时,可以只使用这两层完成rpc调用。transport层和exchange层 都放在Remoting模块中,为rpc调用的通讯基础;serialize层放在common模块中,以便更大程度复用。
依赖关系
图例说明:
图中小方块Protocol、Cluster、Proxy、Service、Container、Registry、Monitor代表层或模块,蓝色的表示与业务有交互,绿色的表示只对Dubbo内部交互。图中背景方块Consumer、Provider、Registry、Monitor代表部署逻辑拓扑节点;图中蓝色虚线为初始化时调用,红色虚线为运行时异步调用,红色实现为运行时同步调用。图中只包含RPC的层,不包含Remoting 的层,Remoting整体都隐含在Protocol中。
调用链
展开总设计图的红色调用链
暴露服务时序
展开总设计图左边服务提供方暴露服务的蓝色初始化链,时序图如下:
引用服务时序
展开总设计图右边服务消费方引用服务的蓝色初始化链,时序图如下:
领域模型
在Dubbo的核心领域模型中:
Protocol是服务域,它是Invoker暴露和引用的主要功能入口,它负责Invoker的生命周期管理。Invoker是实体域,它是Dubbo的核心模型,其他模型都向它靠拢,或转换它,它代表一个可执行体,可向它发起Invoker调用,它可能是一个本地的实现,也可能是一个远程实现,也可能是一个集群实现。Invoker是会话域,他持有调用过程中的变量,比如方法名、参数等;
基本设计原则
采用Microkernel+Plugin模式,Microkernel只负责组装Plugin,Dubbo自身的功能也是通过扩展点实现的,也就是Dubbo的所有功能点都可以被用户自定义扩展所替换。采用URL作为配置信息的统一格式,所有扩展都可以通过传递URL携带配置信息。官方文档:
https://dubbo.apache.org/zh-cn/docs/user/quick-start.html