作者:凌波_薇步 | 来源:互联网 | 2024-11-18 03:51
Dubbo开篇综述
Dubbo是由阿里巴巴开源的高性能RPC(远程过程调用)框架,是阿里巴巴SOA(面向服务的架构)服务治理方案的核心组件。目前,Dubbo已被广泛应用于各大企业,如滴滴、京东、考拉等。
Dubbo的架构设计如下图所示:
当Provider启动时,会将自己的元数据(服务IP和端口、服务接口信息)注册到注册中心。Consumer启动时会从注册中心订阅服务元数据(首次订阅会拉取全量数据并缓存到本地),注册中心数据发生变化时会推送给订阅的Consumer。Consumer获取到服务元数据后,会发起RPC调用,并将调用信息上报给Monitor。
Dubbo的核心特性总结如下:
1. 面向接口的RPC调用:提供高性能的基于代理的远程调用能力,服务以接口为粒度,为开发者屏蔽了远程调用的复杂性。
2. 服务注册与发现:支持多种注册中心(如ZooKeeper、Redis、Multicast,官方推荐ZooKeeper),能够实时感知服务实例的上下线情况。
3. 运行期流量控制:内置条件、脚本等策略,通过配置不同的路由规则,轻松实现灰度发布和同机房优先等功能。
4. 智能负载均衡:内置多种负载均衡策略,智能感知下游节点的健康状况,减少系统调用延迟,提高系统吞吐量。
5. 高度可扩展性:遵循微内核设计,核心能力如协议、传输、序列化被设计成扩展点,支持平滑集成内置和第三方实现。
6. 可视化的服务治理与运维:提供丰富的服务治理和运维工具,支持实时查询服务元数据、服务健康状态及调用统计,以及实时下发路由策略和调整配置参数。
Dubbo的总体分层设计如下:
Dubbo总体分为业务逻辑层(Biz)、RPC层、Remote层。各层的具体划分如下图所示:
Service:业务层,包括业务代码接口和具体实现,即开发者实现的业务代码。
Config:配置层,主要包括ServiceConfig(暴露的服务配置)和ReferenceConfig(引用的服务配置)两个类,负责初始化配置信息,管理整个Dubbo的配置。
Proxy:服务代理层,Dubbo框架会为生产者和消费者生成服务代理类,整个过程对上层透明,使业务层对远程调用无感,如同调用本地接口。
Registry:注册层,负责Dubbo框架的服务注册与发现,当有新的服务加入或旧的服务下线时,注册中心会感知并通知所有订阅方,整个过程无需人工干预。
Cluster:集群容错层,负责远程过程调用失败时的容错策略,如快速失败、快速重试、立即返回等。
Monitor:监控层,负责调用次数和调用时间的统计等。
Protocol:远程调用层,封装RPC调用的具体过程,Protocol是Invoker暴露(发布一个服务供他人调用)和引用(引用一个远程服务到本地)的主要功能入口,负责管理Invoker的整个生命周期。Invoker是Dubbo的核心模型,框架中的其他模型都会转换成它,代表一个可执行体,允许向其发起调用,可能是本地接口实现、远程实现或集群实现。
Exchange:信息交换层,负责Request-Response模型的建立,封装请求响应模式,如将同步请求转换为异步请求。
Transport:网络传输层,将网络传输抽象成统一的接口,Dubbo将底层的通信框架如Mina和Netty封装成统一的接口,用户也可以自定义网络传输。
Serialize:序列化层,负责管理整个框架网络传输时的序列化/反序列化工作,确保数据在网络中传输时的正确性和效率。
Dubbo的整体调用过程如下:
服务端(服务提供者)在框架启动时,会初始化服务实例,通过Proxy组件调用具体协议(Protocol),将服务端要暴露的接口封装成Invoker,然后转换成Exporter。此时,框架会打开服务端口并记录服务实例到内存中,最后通过Registry将服务元数据注册到注册中心,完成服务提供者的接口暴露过程。
组件解析:
Proxy:服务端/消费端接口调用代理类,自动发起本地/远程调用并返回结果。
Protocol:根据不同的协议转换成不同的Invoker对象,如DubboInvoker将XML中的远程配置接口转换为DubboInvoker。
Exporter:用于暴露到注册中心的对象,内部持有Invoker对象。
Registry:将Exporter注册到注册中心。
调用过程整体分析如下:
调用从一个Proxy开始,Proxy持有一个Invoker对象。触发Invoker调用时,需要使用Cluster,Cluster负责容错,处理调用失败的快速返回或重试等。Cluster在调用前会通过Directory获取远程可调用的Invoker列表,如果用户配置了路由规则,会根据路由规则过滤Invoker。
存活下来的Invoker可能还有多个,会通过LoadBalance方法进行负载均衡,最终选择一个可调用的Invoker。这个Invoker会经过一系列过滤链,用于处理上下文、限流、计数等。
接着,使用Client进行传输,如Netty、Mina等。传输前会使用私有协议构造数据包,此时会用到Codec接口对数据包进行序列化,然后传输到服务端。服务端接收到数据包后,使用Codec接口进行协议处理,处理半包、粘包等问题,并对数据进行反序列化。
随后,Request会被分配到请求的线程池中进行处理。Server会处理这些Request,根据请求查找对应的Exporter(内部持有Invoker)。Invoker被用装饰器模式层层包装了许多Filter,因此在调用最终实现类之前,会经过服务端的过滤链。
最终,调用具体接口的真实实现并返回结果。