共计 4989 个字符,预计需要花费 13 分钟才能阅读完成。
作者:
严浩:同程艺龙高级开发,负责服务治理相干工作,Apache Dubbo Committer。
胥皓:同程艺龙高级开发,负责服务治理相干工作。
背景
在微服务倒退初期,市场上还没有成熟和风行的 RPC 框架,咱们公司外部自研开发了一套名为 DSF (Distributed Service Framework) 的 RPC 框架,撑持起了公司业务的高速倒退。然而随着技术的疾速迭代和人员的一直变更,开发者既要修复之前的 BUG 又要跟上技术的更新,开发保护老本越来越高。另一方面,当初应用程序都在往云原生方向倒退与设计,公司也在这方面做出摸索。因而公司微服务框架的演进曾经到了岔路口,是全新降级原有的 SDK,还是抉择拥抱开源?
思考到降级现有的 SDK 在一段时间之后可能仍然会面临当初的问题,最初咱们抉择了拥抱开源。在一番调研之后咱们抉择了 Dubbo3 作为公司的下一代 RPC 框架,负责微服务治理体系的数据面。
目前 Dubbo3 在公司的落地开发工作曾经实现,通过本文咱们对公司外部 Dubbo3 的实际及收益做了深刻总结。
Dubbo 3 外围性能介绍
Dubbo 社区对于 Dubbo 3 的文档和材料越来越欠缺,以下是咱们从社区援用的一些内容。
Dubbo 3 被社区寄予厚望,将其视为下一代云原生服务框架打造,Dubbo3 提供的外围个性列表,次要包含四局部。
- 全新服务发现模型。利用粒度服务发现,面向云原生设计,适配基础设施与异构零碎;性能与集群伸缩性大幅晋升。
- 下一代 RPC 协定 Triple。基于 HTTP/2 的 Triple 协定,兼容 gRPC;网关穿透性强、多语言敌对、反对 Reactive Stream。
- 对立流量治理模型。面向云原生流量治理,SDK、Mesh、VM、Container 等对立治理规定;可能反对更丰盛的流量治理场景。
- Service Mesh。在最新的 3.1.0 的版本中反对 Sidecar Mesh 与 Proxyless Mesh,提供更多架构抉择,升高迁徙、落地老本。
Dubbo 3 的外围性能点(如利用级服务发现以 ip、port 为辨别实例)和公司外部的服务模型统一,极大地缩小了咱们的适配工作。还有在 Service Mesh 中对 Sidecar Mesh 与 Proxyless Mesh 的反对也将缩小后续公司对 Mesh 计划的摸索老本,包含 Dubbo3 在多语言体系的倒退也为异构架构提供了撑持。
总的来说,Dubbo 3 十分符合公司的技术体系和后续的倒退方向。此外,Dubbo 在开发者中的相熟度、社区的高活跃度和欠缺的文档建设也都能为推动 Dubbo3 的应用带来不少的帮忙。
计划调研
在理解了 Dubbo3 的外围性能和根本工作原理之后咱们开始前期工作阶段。
公司外部存在微服务体系 RPC 框架 DSF 和承当服务发现、路由、高低负载等性能的控制中心,如果让用户间接切换到 Dubbo3 应用齐全隔离的一套微服务体系会对用户带来高额的降级和切换老本。所以咱们抉择用 Dubbo3 替换之前的 DSF 框架作为数据面,将 Dubbo3 接入以后的微服务控制中心。同时要求 Dubbo3 反对原有 DSF 框架的公有协定,与 DSF 框架可能互相发现和调用,进一步升高用户降级老本。
这样用户在编程习惯上和 Dubbo3 的应用齐全保持一致,在服务治理上(如高低负载、同核心路由、实例标签等性能)的应用与 DSF 保持一致。因为协定兼容,新的 Dubbo3 利用和原有 DSF 利用之间也能实现相互发现和调用。
要实现这个指标,须要去拓展 Dubbo3 SDK 的注册模块反对从现有的控制中心进行服务注册与发现、扩大自定义协定与 DSF 服务互相调用。借助于 Dubbo 弱小的插件机制,咱们在没有批改 Dubbo 框架任何代码的根底上轻松地实现了这个指标,用户只须要引入 Dubbo 3.0 以上版本的 SDK 和咱们开发的插件包即可。
整体的架构流程如下:
Dubbo3 落地的计划须要满足以下三点要求:
- Dubbo3 要接入现有的控制中心,由控制中心实现服务注册发现和服务治理性能
- Dubbo3 可能和 DSF 可能互相调用,满足此要求须要两个框架可能相互服务发现并且协定可能兼容
- 通过插件机制实现所有性能,不能批改 Dubbo 源码,用户能够自在地降级 Dubbo3 SDK 的版本
服务注册发现兼容
既然须要将 Dubbo3 的利用级注册接入到控制中心,而且须要与 DSF 服务进行服务发现,就须要理解 Dubbo3 利用级发现的流程能力对其进行更好的拓展。
利用级服务发现外围原理
咱们从 Dubbo 最经典的工作原理图说起。Dubbo 从设计之初就内置了服务地址发现的能力,Provider 注册地址到注册核心,Consumer 通过订阅实时获取注册核心的地址更新,在收到地址列表后,Consumer 基于特定的负载平衡策略发动对 Provider 的 RPC 调用。
在这个过程中:
- 每个 Provider 通过特定的 key 向注册核心注册本机可拜访地址
- 注册核心通过这个 key 对 Provider 实例地址进行聚合
- Consumer 通过同样的 key 从注册核心订阅,以便及时收到聚合后的地址列表
能够看到接口级服务发现是以接口为维度进行服务注册的,并在注册数据上携带了服务的配置和元数据。这种形式简略易用而且能够轻松实现利用、接口、办法粒度的服务治理。但由此带来的注册数据的放大问题会给注册核心造成较大压力,还有就是与当初云原生的服务模型并不兼容,不能与 Kubernetes 兼容。
面对这些有余,在 Dubbo3 架构下社区认真思考了两个问题:
- 如何在保留易用性、功能性的同时,从新组织 URL 地址数据,防止冗余数据的呈现,让 Dubbo 3 能撑持更大规模集群程度扩容?
- 如何在地址发现层面与其余的微服务体系如 Kubernetes、Spring Cloud 买通?
最终,社区给出的计划也是十分奇妙和经典,将之前接口级服务的数据拆成两局部。属于实例模型的 ip 和 port 注册到注册核心,而属于业务属性的 RPC 元数据和 RPC 服务配置对立由 Dubbo Provider 的 MetadataService RPC 服务提供或者由元数据中心提供。在服务生产端和提供端之间建设了一条内置的 RPC 服务信息协商机制,也称为 ” 服务自省 ”。全新的利用级服务发现模型,相比之前接口级别单机内存降落 50% 且极大的缩小了注册核心的压力。
还有一个问题是换成了利用级服务发现之后,Consumer 是如何晓得订阅的接口是属于哪一个服务的?因为 Dubbo 的编程模型是以接口为维度的。Dubbo3 提供了两种解决方案:一是从元数据中心存储接口和利用名的映射关系,二是通过 Consumer 在接口上通过 providerBy 配置手动指定服务提供方的名称。
兼容计划
如果是 Dubbo Consumer 调用 Dubbo Provider,咱们只须要循序渐进参考其余利用级别服务发现的插件比方 Zookeeper、Nacos 开发就能够实现此性能。如果 DSF Client 要调用 Dubbo Provider 咱们是将兼容逻辑放在了控制中心,防止用户 SDK 的降级老本。剩下的兼容流程只有 Dubbo Consumer 调用 DSF Server 了,因为要求尽量不要批改 Dubbo 框架的源码,所以这里的兼容逻辑咱们只能在注册核心的插件中实现。
下面介绍利用级服务发现的外围原理的时候提到利用级服务发现有 3 个要害的步骤:
- 通过元数据的 mapping 获取接口对应的服务名或者通过接口配置中的 providerBy 指定
- 通过服务名获取实例列表,实例以 ip、port 为维度,并且在实例信息中携带元数据的 revision
- 调用 Dubbo Provider 的 MetaService 获取实例的元数据信息,组装接口数据
Dubbo 服务调用 DSF 服务兼容流程的第一步非常简单,因为 DSF 并没有接口与服务名的 mapping 数据,所以通过 providerBy 指定接口所属的 DSF 服务名。第二步因为 DSF 服务的注册模型也是利用级的,实例的数据齐全能够兼容这一部分也很简略。最要害的一步在于如何获取 DSF 服务的元数据,很显然现有的 DSF 服务并不具备 MetaService 的接口。
下面提到 Dubbo3 反对两种形式获取实例的元数据。默认就是从 Dubbo Provider 的 MetaService 获取实例的元数据信息,也反对从元数据中心获取实例的元数据信息,只须要将实例的 dubbo.metadata.storage-type 属性设置为 remote 即可。而 DSF 服务正好公布了 API 的契约数据到控制中心用作服务测试和寻址兼容,齐全能够将 DSF 的契约数据转换为 Dubbo 的元数据的格局,满足服务发现的流程。
以下为 Dubbo Consumer 发现 DSF 服务的流程:
实现服务发现的兼容之后,用户在调用 DSF 服务的时候仅须要在接口上通过 providerBy 指定接口对应的服务即可,应用老本极低。
协定兼容与服务治理
协定兼容
实现服务发现的互相兼容之后,离 Dubbo 与 DSF 服务的互相调用的指标只剩最初一块拼图,在插件中实现 DSF 协定即可。
相比服务发现的各种数据兼容,协定的兼容比拟清晰,只须要依据 Dubbo 协定扩大阐明进行自定义协定扩大实现 DSF 数据格式兼容即可。
Dubbo 协定扩大须要实现以下接口:
- org.apache.dubbo.rpc.Exporter
- org.apache.dubbo.rpc.Invoker
- org.apache.dubbo.rpc.Protocol
当用户调用 refer() 所返回的 Invoker 对象的 invoke() 办法时,协定需相应执行同 URL 远端 export() 传入的 Invoker 对象的 invoke() 办法。其中,refer() 返回的 Invoker 由协定实现,协定通常须要在此 Invoker 中发送近程申请,export() 传入的 Invoker 由框架实现并传入,协定不须要关怀。也就是说服务提供方在容器启动的时候就进行服务的裸露,而服务调用方须要通过协定进行 Invoker 的调用。咱们的扩大如下:
最初实现的成果如下,用户只须要在 pom 中引入 Dubbo3 以上的任意版本和开发的插件,配置上指定注册核心地址和协定为 dsf 即可,其余应用形式和 Dubbo3 保持一致。
<properties>
<dubbo.version>3.0.11</dubbo.version>
<dubbo-dsf.version>1.0.0</dubbo-dsf.version>
</properties>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>com.ly.dsf</groupId>
<artifactId>dubbo-dsf-extensions-all</artifactId>
<version>${dubbo-dsf.version}</version>
</dependency>
配置文件:
# 注册地址为控制中心
dubbo.registry.address=dsf://{address}
# 协定指定 dsf
dubbo.protocol.name=dsf
dubbo.consumer.protocol=dsf
服务治理
Dubbo3 有十分弱小的流量治理的性能,同时咱们外部的控制中心也有服务治理的性能,局部性能也有重合。
对于这部分的取舍,咱们打算控制中心原有的性能对 Dubbo3 服务仍然反对,如服务发现、同核心寻址、高低负载、服务测试等操作和之前保持一致。而 Dubbo 特有的服务治理性能如动静配置、Mesh 路由,咱们将新增性能对其反对,保障 Dubbo3 性能的残缺。
总结
Dubbo 3 是一个优良的微服务框架,提供的 SPI 以及 Extension 机制可能十分不便的让用户去扩大实现想要性能。而且 Dubbo3 也更适应目前云原生的架构,Dubbo 3.1.x 版本反对 Sidecar 和 Proxyless 的 Mesh 计划,而且社区也在筹备开源 Java Agent 形式的 Proxyless,这样就能较好的将微服务架框的 Framework 与数据面解耦,升高微服务框架的保护老本和降级老本。咱们也会和社区一起摸索,共建 Dubbo 社区的凋敝。