【Dubbo】深入理解Apache Dubbo(一):带你走近高性能RPC通信框架

1. 简介

从本篇开始,笔者将会带你进入Apache顶级项目——Dubbo的学习。本篇侧重介绍Dubbo的来龙去脉,会从架构的演进过程说明Dubbo的重要性和意义。

2. 应用架构的演进过程

2.1 单体应用

1. JEE时期

特征 优点 缺点
JEE是早期提供了企业级应用开发环境的工具,整体上分为展示层、业务逻辑层和数据存储层。各层的组件都被聚合在一起运行在统一的服务器上(如Tomcat、JBoss等)。 分层设计明确了团队分工,职责清晰;开发简单,所有的类都能直接本地引用。 大多数都部署在同一个JVM中,性能随着应用的增大急剧下降;业务之间耦合性太高。

2. MVC框架时期

特征 优点 缺点
Model:模型部分,负责具体的业务逻辑和数据存取;View:视图层,负责应用的展示;Controller:控制器,主要处理和用户的交互。 分工明确,分层更加简单,Spring、Spring MVC、Mybatis更加轻量级。 耦合问题一直没有得到改善,并且在垂直划分的应用中,这种架构虽然满足了服务之间完全独立,但是无法进行远程调用,很多基础代码不能复用。

2.2 分布式应用

1. 早期SOA
在上述说明的单体应用中,所有服务部署在一个JVM中,随着应用的不断增大, 势必会出现难以维护的情况;并且随着to C业务的不断发展,传统单应用也无法满足高并发的需求。为了解决这个问题,面向服务的架构(SOA)应运而生。
在这里插入图片描述
2. 微服务
无论是Web Service还是ESB,早期SOA不可避免的问题就是过于笨重,这个时候微服务就呼之欲出。

所谓的微服务,是指一个应用被拆分成一个个独立的、可配置、可运行、可维护的子服务,极大的方便了服务的复用。

3. 云原生
为了解决微服务架构中小服务资源的浪费以及让应用变得更加轻量级,基于云原生的服务网格也开始出现。

3. 初探Dubbo

首先对Dubbo做个简单的介绍,它是一个分布式高性能的RPC服务框架,它的核心设计原则是:微内核+插件体系

3.1 Dubbo是什么

在这里插入图片描述
如上图Dubbo的架构所示,其中,Provider启动时会向注册中心把自己的元数据注册上去,Consumer在启动时从注册中心订阅(首次订阅会拉取全量数据)服务提供方的元数据,注册中心发生数据变更会推送给Consumer。在获取服务元数据之后,Consumer可以发起RPC调用,并且在调用前后会向监控中心上报统计信息(如并发数等)。

3.2 Dubbo解决什么问题

在弄清楚Dubbo需要解决的问题之前,不妨先回过头探讨一下互联网架构演进的过程。早期的单体应用及垂直应用架构现在已经满足不了高并发、实时计算的需求,现在基本都是分布式以及流式计算框架。架构的演进及特征见下表,需要注意的是,事实上分布式架构及流动计算架构也属于垂直应用架构的范畴。

架构演进 规模 特征 架构关键
单一应用架构 1~10 将所有的应用都部署在一起,部署节点及成本较低,但是性能瓶颈较大。 ORM框架
垂直应用架构 10~1000 将单一应用拆分成若干互不相干的应用以提升效率 MVC框架
分布式服务架构 1000~10000 将核心业务抽取出来作为独立的业务,形成稳定的服务中心 RPC框架
流动计算结构 10000+ 增加了一个调度中心基于访问压力实时管理集群容量 调度中心

初期的远程服务引用可以采用远程方法调用RMI(Remote Method Invoke),但是在服务规模不断演进的情况下,RMI根本满足不了技术需求,所以需要优秀的RPC框架——Dubbo。Dubbo致力于为用户解决问题包括:

  • 高性能、透明化的调用。Dubbo让开发者就像调用本地的方法一样调用远程服务,负载均衡、路由、序列化等皆由Dubbo保证,开发者只需要接收对应的调用结果。
  • 服务的自动注册于发现。对于大规模的服务,URL配置要想人工管理几乎不可能,Dubbo自带了服务注册中心,动态的注册也发现服务,将服务的位置透明化。

3.3 Dubbo的总体分层

Dubbo的总体分为三层:业务层(Biz)、RPC层、Remote。再细分的话一共有十层,如下图:
在这里插入图片描述
如上图所示,Service和Config两层可以认为是API层,使用者只要基于这两层配置完成业务即可;后面的所有层结合在一起可以认为是SPI(Service Provider Interface)层,主要提供给扩展者使用。

3.4 Dubbo的核心组件

Dubbo框架中不同的分层代表了不同的逻辑实现,事实上它们是一个个组件,如下表所示:

层次名 作用
Service 业务层,由开发者实现的业务代码
Config 配置层。主要围绕ServiceConfig(暴露的服务位置)和ReferenceConfig(引用的服务位置)两个类展开初始化配置信息,可以理解为该层管理了整个Dubbo的配置
Proxy 服务代理层。在Dubbo中无论是生产者还是消费者,框架都会生成一个代理类。代理层负责做远程调用,让业务层对远程调用完全无感
Registry 注册层。负责Dubbo所有的服务注册与发现,实现当服务发生变更时及时推送给所有的订阅方
Cluster 集群容错层。主要负责在远程调用失败时的容错策略(如失败重试、快速失败);负载均衡策略(如随机、一致性Hash等);路由策略(如某个消费者只会调用固定IP的生产者)
Monitor 监控层。负责监控统计调用次数和时间
Protocol 远程调用层。封装RPC调用具体过程,Protocol是Invoker暴露(发布一个服务让别人可以调用)和引用(引用一个远程服务到本地)的主功能入口,该层负责管理Invoker的整个生命周期,Invoker是Dubbo的核心模型。
Exchange 信息交换层。建立Request-Response模型,封装请求响应模式,如把同步请求转换为异步请求
Transport 网络传输层。把网络传输抽象为统一的接口。如Mina和Netty虽然接口不一致,但是Dubbo在它们的上层又封装了一个统一的接口
Serialize 序列化层。当数据需要进行网络传输则需要先进行序列化。该层负责管理整个框架网络传输时的序列化/反序列化工作

3.5 Dubbo的总体调用过程

在消费者调用服务之前,首先服务有一个暴露过程,形象的描述一下:**在Dubbo框架启动时,通过Proxy组件调用具体协议(Protocol),把服务端要暴露的接口封装成Invoker(真实类型是AbstractProxyInvoker),然后转换成Exporter,此时Dubbo会打开服务端口记录服务实例到内存,最后通过Registry把服务元数据注册到注册中心。**在暴露过程中各个组件的含义为:

  • Proxy组件:Dubbo框架通过Proxy组件为生产者和消费者生成代理类,通过代理类发起服务调用,整个过程对用户完全透明。
  • Protocol组件:顾名思义,协议就是对数据格式的一种约定。通过不同的协议将对接口的配置转换成不同的Invoker对象,例如用DubboProtocol可以把XML文件中一个远程接口的配置转换成一个DubboInvoker。
  • Exporter组件:用于暴露到注册中心的对象,它的内部属性持有了一个Invoker对象。
  • Registry组件:把Exporter注册到注册中心。
    服务调用过程如下图所示:
    在这里插入图片描述
    接下来对服务调用过程的部分组件进行说明:
  • Proxy组件:调用过程的开始组件,持有一个Invoker对象,然后触发invoke调用。
  • Directory组件:获取所有可以调用的远程服务Invoker列表。
  • Router组件:如果用户配置了路由规则(如指定某些方法只能调用某个节点),则由Router组件根据该路由规则将Invoker列表过滤。
  • LoadBalance组件:对依然存活的Invoker做负载均衡,最终选出了可以调用的Invoker。
  • Filter组件:在最终选出的Invoker调用之前会经过该Filter过滤器链,用于处理上下文、限流、计数等。
  • Client组件:做数据传输,如Netty Client等。
  • Codec组件:构造私有协议,处理 协议头及一些半包、粘包等。
  • Serialization组件:协议构造完成之后就对数据包进行序列化,然后传输到服务提供者端。
  • ThreadPool:线程池分配处理Request请求的Server。
  • Server:处理上一步分配过来的Request请求。

小结

本篇介绍了框架的演进历史以及Dubbo产生的背景。另外也概述了Dubbo的总体架构图和核心组件,讲解了总体调用过程。下一篇笔者将用一个简单的示例演示Dubbo的使用。附Dubbo的官方文档:
Dubbo的官方文档