Dubbo的背景介绍
Apache Dubbo 是一款微服务开发框架(是一款高性能、轻量级的开源 Java 服务框架),它提供了 RPC通信 与 微服务治理 两大关键能力。这意味着,使用 Dubbo 开发的微服务,将具备相互之间的远程发现与通信能力, 同时利用 Dubbo 提供的丰富服务治理能力,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。同时 Dubbo 是高度可扩展的,用户几乎可以在任意功能点去定制自己的实现,以改变框架的默认行为来满足自己的业务需求。
Dubbo的功能特性
面向接口代理的高性能RPC调用;
服务自动注册与发现;
智能负载均衡策略;
高度可扩展能力;
运行期流量调度;
可视化的服务治理与运维;
Dubbo的框架结构
Dubbo的发展历程
2011/10/27: 阿里巴巴巴宣布 Dubbo 开源。
2012/10/23: 发布最后一个版本 2.5.3 并停止维护更新。
2017/07/31: 起死回生,官方宣布开启重新更新,并会得到重点维护,参考:Dubbo 宣布重新开始维护。
2017/09/07: 发布起死回生的第一个版本:dubbo-2.5.4。
-
2018/01/08:
Dubbo 团队透露 Dubbo 3.0 宣布正式开工,参考:重大利好,Dubbo 3.0要来了。
发布了 dubbo-2.6.0 版本,主要合并了由当当网开源的 dubbox 项目分支。PS:dubbo停止维护期间,当当网基于 dubbo 开源了dubbox。
2018/01/22: Dubbo Spring Boot 版正式发布:dubbo-spring-boot-starter v1.0.0 公测版。
2018/02/09: Dubbo 通过投票正式进入 Apache 基金会孵化器,更新了 Apache 官方域名,也不再仅限于 Java 语言。
2019/05/20: Apache 软件基金会宣布 Dubbo 正式毕业,成为 Apache 的顶级项目。
Dubbo3.0诞生归来
Dubbo3 基于 Dubbo2 演进而来,在保持原有核心功能特性的同时, Dubbo3 在易用性、超大规模微服务实践、云原生基础设施适配等几大方向上进行了全面升级。 以下文档都将基于 Dubbo3 展开。
Dubbo3.0扩展延伸
[图片上传失败...(image-695585-1628904275366)]
从功能上看,Dubbo3.完成后的功能将涵盖从开发人员直接接触的 API 层到底层传输的完整链路。
-
API层将包括基于IDL的完整数据交换格式打通,这会带来两方面的好处:
一是统一的 IDL 模型可以生成统一的 client stub 和 server stub,这些 stub 能直接进行非反射调用,会在性能上有很大的提升;
二是对异步和 streaming 的原生支持能够给用户更多的选项,根据不同的业务场景选择更方便的用法。
-
第二层是对于注册中心、元数据中心和配置中心的扩展。
- 注册中心和配置中心基本支持了所有业界主流的实现,元数据中心是 Dubbo 2.7 新抽象出的组件,负责元数据的存取。这里的元数据包括服务的调用配置,如超时时间,序列化方式,协议等,以及对服务方法签名的抽象,方便 Dubbo 实现跨框架和跨语言调用。
集群层是Dubbo的一个主要亮点,除了支持各种重试策略外,Dubbo 也提供了各种场景下的负载均衡器,比如随机和权重。值得一提的是,Dubbo3.0 将带来 pull-based 的自适应负载均衡,这将显著提升分布式集群的性能和效率。
再下一层是协议层,协议层是 RPC 框架的内核部分,一般分为应用层协议和传输层协议。应用层协议 Dubbo3.0 支持 GRPC / Redis / REST 等主流协议以及 Dubbo 原生的 Dubbo2.0 协议。
传输层支持 HTTP / HTTP2 和一些自定义的协议如 RSOCKET。序列化方面,Dubbo 除了支持 hessian 、Java 外,还支持 protobuf,这对于性能和跨语言都有着巨大的意义。
Maven 依赖
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>3.0.0</version>
</dependency>
Dubbo3 是在云原生背景下诞生的,使用Dubbo构建的微服务遵循云原生思想,能更好的复用底层云原生基础设施、贴合云原生微服务架构。
Dubbo 3.0.0 几乎兼容 2.7.x 所有行为。 因为,Dubbo3 是基于 Dubbo2 演进而来,在保持原有核心功能特性的同时, Dubbo3 在易用性、超大规模微服务实践、云原生基础设施适配等几大方向上进行了全面升级。
Dubbo3官方文档
Dubbo3核心功能
-
应用级服务发现机制;
- 同时 Dubbo 3.0.0 改变以前的接口级服务注册而是采用应用级服务注册,什么意思呢?比如在3.0.0版本前所有的服务都是以接口形式的元数据进行注册如下元数据:
dubbo://192.168.101.8:20880/com.example.demo.async.api.BookFacade?anyhost=true&application=demo-provider&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=com.example.demo.async.api.BookFacade&metadata-type=remote&methods=queryByName,queryAll&pid=53639&release=3.0.0&side=provider×tamp=1624889509797
- 可以看到如果我们以接口级进行服务注册会存在大量的重复数据,这样就会导致注册中心数据与接口数量成正比,接口越多注册的元数据就越多。而如果我们以应用级服务注册会是怎样的?下面是应用级服务注册的共享元数据:
{ "name": "demo-provider", "id": "192.168.101.8:20880", "address": "192.168.101.8", "port": 20880, "sslPort": null, "payload": { "@class": "org.apache.dubbo.registry.zookeeper.ZookeeperInstance", "id": null, "name": "demo-provider", "metadata": { "anyhost": "true", "application": "demo-provider", "deprecated": "false", "dubbo": "2.0.2", "dubbo.endpoints": "[{\"port\":20880,\"protocol\":\"dubbo\"}]", "dubbo.metadata-service.url-params": "{\"version\":\"1.0.0\",\"dubbo\":\"2.0.2\",\"release\":\"3.0.0\",\"port\":\"20880\",\"protocol\":\"dubbo\"}", "dubbo.metadata.revision": "525892dddd25ea459ee539d0734b2f1a", "dubbo.metadata.storage-type": "remote", "dynamic": "true", "generic": "false", "interface": "com.example.demo.async.api.BookFacade",//多个服务接口只保存一个 "metadata-type": "remote", "methods": "queryByName,queryAll", "pid": "63941", "release": "3.0.0", "side": "provider", "timestamp": "1624891074206" } }, "registrationTimeUTC": 1624891075236, "serviceType": "DYNAMIC", "uriSpec": null }
从这些共享元数据可以看出应用级注册减少了大量重复的元数据,能最大幅度的减轻注册中心的存储、推送压力,进而减少 Dubbo 消费端的地址计算压力。集群规模也开始变得可预测、可评估(与 RPC 接口数量无关,只与实例部署规模相关)。
-
Dubbo3之前注册发现都是接口级别的。也就是同一个应用发布的多个服务会在注册中心注册多份数据,这些数据彼此独立,方便进行服务化改造和接口迁移。为什么要提出应用级注册发现呢?
-
主要有两个原因:
一是现有生态系统的互通,包括 Spring cloud 和 K8s 都是基于实例,也就是应用级别进行的注册发现,Dubbo 要成为连接异构系统最好用的 RPC 框架就需要支持实例粒度;
二是从规模上看,更大规模的增长会带来元数据的极速膨胀,这会给注册中心和客户端带来更大的内存占用。按照现有数据分析,如果升级到应用级注册发现,以平均发布 50 个服务的应用为例,将减少 60% 的内存占用和注册中心数据。以发布超过 10k 接口的平台型应用为例,这些数据可降低 90%。
-
如何保证平滑迁移,用户基于接口的配置怎么映射到应用上去。
-
抽象出了元数据中心来管理接口到应用的映射以及应用级的元数据。
- 在部署态,Dubbo 框架会自动上报这个关系到元数据中心。
- 运行态用户侧的配置和服务治理则通过这份映射关系重新将应用粒度映射到接口粒度。涉及到最核心的部分——选址也是分为两部分,应用级选址和接口级选址同时存在,方便进行服务治理。应用级注册发现带来的优化是十分显著的。
下一代RPC协议:Triple:Triple 协议是 Dubbo3 的主力协议,完整兼容 gRPC over HTTP/2,并在协议层面扩展了负载均衡和流量控制相关机制。
全新的路由规则;
显著提升性能;
-
Kubernetes 服务集成:
Dubbo3主要在云服务能力上做了新的能力提升。为什么这么说呢?因为作者之前在工作中集成 Kubernetes 时候服务注册中心这个组件能力就非常的尴尬,因为 Kubernetes 本身就提供了服务注册与发现能力,但是不能和 Dubbo 完美整合起来。
Dubbo3之前我们的实现方式可能就是在Kubernetes部署一个 zookeeper 服务集群来进行服务注册与发现。但这样的实现方式在云服务应用来说并不是太合适,这种服务注册和发现能力交给基础服务组件来实现比较合适。
- 一是需要对齐 K8s 的生命周期,能够让 Dubbo 服务原生的在 K8s 体系内注册和发现;
- 二是对 Mesh 的支持。上面在协议那里我们已经讲到,新协议通过使用 HTTP2 进行 header / payload 分离解决了网关需要解析完整协议的问题。另外一个问题则是服务注册发现和治理,注册发现需要 Dubbo 能够在 Mesh 的 xDS 体系内作为数据面打通。治理则需要将原有的规则逐步迁移至基于 YAML 的剔除 IP 依赖的规则。最终的形态将是原生的 Dubbo 服务能够和基于 thin SDK 的 Dubbo + Mesh 完美互通和进行服务治理。
Dubbo3.0原生微服务
承接上面对K8s整合之后,Dubbo3.0 -下一代云原生微服务。
一个新架构或新技术的出现一定会伴随特定的发展趋势。
目前我们可以看到的几个趋势是 K8s 成为资源调度的事实标准、Mesh 化成为主流以及规模上的急速增长。这些趋势的存在对 Dubbo 提出了更高的要求:
- 首先,用户如何在 K8s 上更方便的部署和调用 Dubbo 服务是必须要解决的问题,要解决这个问题,统一的协议和数据交换格式是必须前提;
- 其次,Mesh 化的流行带来了多元化问题,即原生 Dubbo 和 Mesh 化 Dubbo 如何共存,多语言的场景如何支持;
- 第三点,规模的增长会给整个 Dubbo 架构带来更大的挑战,无论是注册中心等组件,还是客户端,都会有更多的数据和调用量。如何在保持稳定的前提下,提供更高效的服务是 Dubbo 演进的重中之重。
- 这些云原生时代带来的挑战,促成了 Dubbo 的下一代定义。新协议、K8s 基础架构支持、多语言支持和规模化支持四个子项目共同组成了 Dubbo3.0 。下面我们将走进 Dubbo3.0,看看具体有哪些新特性。
Dubbo3扩展分离
Dubbo 核心不再提供第三方 SDK 扩展,需要通过 dubbo-spi-extensions 项目来支持。
Dubbo3多样化注册
Zookeeper 作为注册中心、元数据报告、配置中心;
Nacos 作为注册中心、元数据报告、配置中心;
Kubernetes 作为注册中心;
Redis 作为元数据报告;
Apollo 作为配置中心;
Hessian2 和 jdk 作为默认序列化器;
Triple 协议支持 Protobuf;
Dubbo3的升级提醒
基于 Spring 的相关配置列表可能会发生变更,请留言官方升级文档;
为了高度兼容性,Dubbo 3 早期版本会默认开启多重注册,多重订阅;
Dubbo3.0柔性增强
柔性增强要解决的问题有两个:
- 一是在节点异常的情况下,分布式服务能够保持稳定,不出现雪崩等问题;
- 二是对于大规模的应用,能够以最佳态运行,提供较高的吞吐量和性能。
从方法上看,Dubbo3.0 的柔性增强会以面向失败设计为理念,提供包括精准容量评估、自适应限流、自适应负载均衡的支持,自底向上的分步构建大规模可靠应用。从单一服务的视角看,服务是压不垮的,稳定的。
从分布式视角看,复杂的拓扑不会带来性能的下降,分布式负载均衡能够以最优的方式动态分配流量,保证异构系统能够根据运行时的准确服务容量合理分配请求,从而达到性能最优。
Dubbo3代表下一代RPC协议
Dubbo2.x的协议报文头
大家可以看到,这是 Dubbo2.0 的协议。从功能上看, Dubbo2.0 提供了 RPC 的核心语义,包括协议头、标志位、请求 ID 以及请求/响应数据。在云原生时代,2.0 协议主要面临两个挑战:
一是生态不互通,用户很难直接理解二进制的协议;
二是对 Mesh 等网关型组件不够友好,需要完整的解析协议才能获取到所需要的调用元数据,如一些 RPC 上下文,从性能到易用性方面都会面临挑战。
Dubbo3的协议报文头
首先,协议需要解决跨语言互通的问题,传统的多语言多 SDK 模式和 Mesh 化跨语言模式都需要一种更通用易扩展的数据传输格式;
其次,协议应该提供更完善的请求模型,除了 Request/Response 模型,还应该支持 Streaming 和 Bidirectional;
再次,在性能上,新的协议应该保留 request Id 机制,以避免 HOL 带来的性能损耗;
最后,新协议应该易扩展,包括但不限于 Tracing/ Monitoring 等支持,也应该能被各层设备识别,降低用户理解难度。
基于这些需求,HTTP2/protobuf 的组合是最符合的。提到这两个,大家可能很容易想到 GRPC 协议。那新一代的协议和 GRPC 的关系是什么呢?
首先,Dubbo 新协议是基于 GRPC 扩展的协议,这也保证了在生态系统上新协议和 GRPC 是能够互通和共享的;
其次,在这个基础上,Dubbo 新协议将更原生地支持 Dubbo 的服务治理,提供更大的灵活性;
在序列化方面,由于目前大多数应用方还没有使用 Protobuf ,所以新协议会在序列化方面给予足够的支持,平滑的适配现有序列化,方便迁移到 Protobuf;
在请求模型上,新协议将原生支持 Reactive,这也是 GRPC 协议所不具备的。