什么是 Dubbo?

Apache Dubbo (incubating) |ˈdʌbəʊ| 是一款高性能、轻量级的开源 Java RPC 框架。

根据 Dubbo 官方文档的介绍,Dubbo 提供了六大核心能力

  1. 面向接口代理的高性能RPC调用。
  2. 智能容错和负载均衡。
  3. 服务自动注册和发现。
  4. 高度可扩展能力。
  5. 运行期流量调度。
  6. 可视化的服务治理与运维。

「准备」Dubbo 概览 - 图1

简单来说就是: Dubbo 不光可以帮助我们调用远程服务,还提供了一些其他开箱即用的功能比如智能负载均衡。

Dubbo 目前已经有接近 34.4 k 的 Star 。

2020 年度 OSC 中国开源项目 评选活动中,Dubbo 位列开发框架和基础组件类项目的第7名。想比几年前来说,热度和排名有所下降。

「准备」Dubbo 概览 - 图2

Dubbo 是由阿里开源,后来加入了 Apache 。正式由于 Dubbo 的出现,才使得越来越多的公司开始使用以及接受分布式架构。

为什么要用 Dubbo?

随着互联网的发展,网站的规模越来越大,用户数量越来越多。单一应用架构 、垂直应用架构无法满足我们的需求,这个时候分布式服务架构就诞生了。

分布式服务架构下,系统被拆分成不同的服务比如短信服务、安全服务,每个服务独立提供系统的某个核心服务。

我们可以使用 Java RMI(Java Remote Method Invocation)、Hessian这种支持远程调用的框架来简单地暴露和引用远程服务。但是!当服务越来越多之后,服务调用关系越来越复杂。当应用访问压力越来越大后,负载均衡以及服务监控的需求也迫在眉睫。我们可以用 F5 这类硬件来做负载均衡,但这样增加了成本,并且存在单点故障的风险。

不过,Dubbo 的出现让上述问题得到了解决。Dubbo 帮助我们解决了什么问题呢?

  1. 负载均衡 : 同一个服务部署在不同的机器时该调用那一台机器上的服务。
  2. 服务调用链路生成 : 随着系统的发展,服务越来越多,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。Dubbo 可以为我们解决服务之间互相是如何调用的。
  3. 服务访问压力以及时长统计、资源调度和治理 :基于访问压力实时管理集群容量,提高集群利用率。
  4. ……

「准备」Dubbo 概览 - 图3

另外,Dubbo 除了能够应用在分布式系统中,也可以应用在现在比较火的微服务系统中。不过,由于 Spring Cloud 在微服务中应用更加广泛,所以,我觉得一般我们提 Dubbo 的话,大部分是分布式系统的情况。

Dubbo 的架构设计

官方文档中的框架设计章节 已经介绍的非常详细了,我这里把两个比较重要的点再提一下。

核心角色

「准备」Dubbo 概览 - 图4

上述节点简单介绍以及他们之间的关系:

  • Container: 服务运行容器,负责加载、运行服务提供者。必须。
  • Provider: 暴露服务的服务提供方,会向注册中心注册自己提供的服务。必须。
  • Consumer: 调用远程服务的服务消费方,会向注册中心订阅自己所需的服务。必须。
  • Registry: 服务注册与发现的注册中心。注册中心会返回服务提供者地址列表给消费者。非必须。
  • Monitor: 统计服务的调用次数和调用时间的监控中心。服务消费者和提供者会定时发送统计数据到监控中心。 非必须。

一些用于自测的小问题(面试中可能会遇到):

  • 注册中心的作用? 注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互。
  • 监控中心的作用? 监控中心负责统计各服务调用次数,调用时间等。
  • 服务提供者宕机后,注册中心会做什么? 注册中心会立即推送事件通知消费者。
  • 注册中心和监控中心都宕机的话,服务都会挂掉吗? 不会。两者都宕机也不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表。注册中心和监控中心都是可选的,服务消费者可以直连服务提供者。

整体设计

下图是 Dubbo 的整体设计,从下至上分为十层,各层均为单向依赖。

左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为双方都用到的接口。

「准备」Dubbo 概览 - 图5

  • config 配置层:Dubbo相关的配置。支持代码配置,同时也支持基于 Spring 来做配置,以 ServiceConfig, ReferenceConfig 为中心
  • proxy 服务代理层:调用远程方法像调用本地的方法一样简单的一个关键,真实调用过程依赖代理类,以 ServiceProxy 为中心。
  • registry 注册中心层:封装服务地址的注册与发现。
  • cluster 路由层:封装多个提供者的路由及负载均衡,并桥接注册中心,以 Invoker 为中心。
  • monitor 监控层:RPC 调用次数和调用时间监控,以 Statistics 为中心。
  • protocol 远程调用层:封装 RPC 调用,以 Invocation, Result 为中心。
  • exchange 信息交换层:封装请求响应模式,同步转异步,以 Request, Response 为中心。
  • transport 网络传输层:抽象 mina 和 netty 为统一接口,以 Message 为中心。
  • serialize 数据序列化层 :对需要在网络传输的数据进行序列化。

基本设计原则

微内核架构

Dubbo 采用微内核(Microkernel) + 插件(Plugin) 模式,简单来说就是微内核架构。微内核只负责组装插件。

何为微内核架构呢? 《软件架构模式》 这本书是这样介绍的:

微内核架构模式(有时被称为插件架构模式)是实现基于产品应用程序的一种自然模式。基于产品的应用程序是已经打包好并且拥有不同版本,可作为第三方插件下载的。然后,很多公司也在开发、发布自己内部商业应用像有版本号、说明及可加载插件式的应用软件(这也是这种模式的特征)。微内核系统可让用户添加额外的应用如插件,到核心应用,继而提供了可扩展性和功能分离的用法。

微内核架构包含两类组件:核心系统(core system)插件模块(plug-in modules)

「准备」Dubbo 概览 - 图6

核心系统提供系统所需核心能力,插件模块可以扩展系统的功能。因此, 基于微内核架构的系统,非常易于扩展功能。

我们常见的一些IDE,都可以看作是基于微内核架构设计的。绝大多数 IDE比如IDEA、VSCode都提供了插件来丰富自己的功能。

正是因为Dubbo基于微内核架构,才使得我们可以随心所欲替换Dubbo的功能点。比如你觉得Dubbo 的序列化模块实现的不满足自己要求,没关系啊!你自己实现一个序列化模块就好了啊!

通常情况下,微核心都会采用 Factory、IoC、OSGi 等方式管理插件生命周期。Dubbo 不想依赖 Spring 等 IoC 容器,也不想自已造一个小的 IoC 容器(过度设计),因此采用了一种最简单的 Factory 方式管理插件 :JDK 标准的 SPI 扩展机制java.util.ServiceLoader)。

URL 传递配置信息

采用 URL 作为配置信息的统一格式,所有扩展点都通过传递 URL 携带配置信息。有什么好处呢? 形成规范,提升代码可读性,降低代码理解成本。