dubbo使用和源码分析系列文章

时间:2021-6-5 作者:qvyue

                                      dubbo开篇综述

   dubbo是阿里开源的高性能RPC框架,是阿里SOA服务化治理方案的核心框架。同时被业界大量使用,公司如滴滴、京东、考拉等。

  dubbo架构设计如下图:

dubbo使用和源码分析系列文章

Provider启动会向注册中心把自己的元数据注册上去(服务ip和端口,facade服务信息)。consumer启动时从注册中心订阅(第一次订阅会拉取全量数据缓存到本地)服务方提供的元数据,注册中心数据发生变更会推送订阅服务的Consumer,在获取服务元数据之后,Consumer会发起RPC调用,并将调用信息上报Monitor。

Dubbo特性总结:

1.面向接口的RPC调用:提供高性能的基于代理的远程调用能力,服务以接口为粒度,为开发者屏蔽了远程调用的细节

2.服务注册与发现:支持多种注册中心(zookeeper、redis、mulitcast 官方推荐zk),服务实例上下线实时感知。

3.运行期流量调用:内置条件、脚本等策略、通过配置不同的路由规则,轻松实现灰度发布和同机房优先等功能。

4.智能负载均衡:内置了多种负载均衡策略,智能感知下游节点健康状况,减少系统调用延迟,提高系统吞吐量。

5.高度可扩展能力:遵循微内核的设计,核心能力protocol、Transport、Serialize被设计成扩展点,能平滑实现内置和第三方实现。

6.可视化的服务治理与运维:提供了丰富的服务治理、运维工具、实时查询服务元数据、服务健康状态及调用统计、实时下发路由策略、调整配置参数。

Dubbo总体分层设计:

Dubbo总体分为业务逻辑层(Biz开发者业务逻辑代码)、RPC层、Remote层。每层又可以大致细分如下图:

dubbo使用和源码分析系列文章
左边是具体的分层,右边是比较重要的接口

service:业务层,包括业务代码接口和具体实现,即开发者实现的业务代码

config:配置层,主要是ServiceConfig(暴露的服务配置)和ReferenceConfig(引用的服务配置)两个类展开,初始化配置信息。可理解为该层管理了整个dubbo的配置。

proxy:服务代理层,在dubbo中,框架会为生产者和消费者都会生成一个服务代理类,整个过程对上层透明,业务层对远程调用无感如同调用本地接口

registry:注册层,负责Dubbo框架的服务注册与发现,当有新的服务加入或者旧的服务下线时,注册中心都会感知并通知给所有的订阅方。整个过程不需要人工干预

cluster:集群容错层,该层主要负责远程过程调用失败时的容错策略(快速失败、快速重试、立即返回等)

monitor:监控层,主要负责调用次数和调用时间的统计等等。

protocol:远程调用层,封装PRC的调用具体过程,Protocol是Invoker暴露(发布一个服务让别人调用)和引用(引用一个远程服务到本地)的主要功能入口。负责管理Invoker的整个生命周期。Invoker是dubbo的核心模型,框架中的其他模型都会装换成它,它代表了一个可执行体。允许向它发起Invoker调用,它可能是一个本地的接口实现、也可能是一个远程的实现、还可能是一个集群实现。

exchange:信息交换层,负责Request-Reponse模型的建立,封装请求响应模式,如将同步请求转化为异步请求

transport:网络传输层,将网络传输抽象成统一的接口,Dubbo将底层的通信框架如mina和netty封装成统一的接口,用户也可以定制自己的网络传输

Serialize:序列化层,如果数据要通过网络进行发送,则需要先经过序列化,变成二进制流,序列化层负责管理整个框架网络传输时的序列化/反序列化工作。

Dubbo整体调用过程:

dubbo使用和源码分析系列文章
Dubbo组件调用总体流程

服务端(服务提供者)在框架启动的时,会初始化服务实例,通过proxy组件调用具体协议(protocol),把服务端要暴露的接口封装成Invoker,然后转换成exporter,这个时候框架会打开服务端口等并记录服务实例到内存中,最后通过Registry把服务元数据注册到注册中心,这就是服务提供者整个接口暴露的过程。组件解析:

Proxy:服务端/消费端接口调用代理类,自动发起本地/远程调用,返回结果

Protocol:根据不同的协议转换成不同的Invoker对象,如DubboInvoker将XML中的远程配置接口转为DubboInvoker

Exporter:用于暴露到注册中心的对象,内部持有了Invoker对象

Registry:将Exporter注册到注册中心。

调用过程整体分析如下:

调用从一个Proxy开始的,Proxy持有了一个Invoker对象。然后出发Invoker调用,在Invoker调用过程中需要使用到Cluster,Cluster负责容错,调用失败的快速返回或者重试等,Cluster在调用之前会通过Directroy获取远程可以调用的Invoker列表,如果用户配置了路由规则,会根据路由规则将Invoker过滤一遍。

存活下来的Invoker可能还有很多,会通过LoadBalance方法做负载均衡,最后选出一个可以调用的Invoker。这个Invoker会经过一个过滤链,用来出出力上线文、限流、计数等。

接着会用Client进行传输,如Netty、Mina等,传输之前会用到私有协议的构造,此时会用到Codec接口对数据包做序列化(Serialization),然后传输到服务端,服务端收到数据包,会使用Codec接口做协议处理,半包、粘包等。对数据做反序列化处理。

随后这个Request会被分配到请求的线程池(ThreadPool)中进行处理,Server会处理这些Request,根据请求查到到Exportor(内部持有了Invoker),Invoker是被用装饰器模式一层一层套了很多的Filter,因此在调用最终的实现类之前,会经过一个服务者端的过滤链。

我们得到具体接口的真实实现并调用,再原路把结果返回。

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。