作者: 严浩:同程艺龙高档开发,负责服务管理相关作业, Apache Dubbo Committer。
胥皓:同程艺龙高档开发,负责服务管理相关作业。

布景

在微服务开展初期,市场上还没有老练和盛行的 RPC 结构,咱们公司内部自研开发了一套名为 DSF (Distributed Service Framework) 的 RPC 结构,支撑起了公司事务的高速开展。但是跟着技能的快速迭代和人员的不断变更,开发者既要修正之前的 BUG 又要跟上技能的更新,开发保护本钱越来越高。另一方面,现在运用程序都在往云原生方向开展与规划,公司也在这方面做出探究。因而公司微服务结构的演进现已到了岔路口,是全新晋级原有的 SDK,还是挑选拥抱开源?

考虑到晋级现有的 SDK 在一段时间之后或许仍然会面对现在的问题,终究咱们挑选了拥抱开源。在一番调研之后咱们挑选了 Dubbo3 作为公司的下一代 RPC 结构,担任微服务管理体系的数据面。

目前 Dubbo3 在公司的落地开发作业现已完结,经过本文咱们对公司内部 Dubbo3 的实践及收益做了深化总结。

Dubbo 3 中心功用介绍

Dubbo 社区关于 Dubbo 3 的文档和材料越来越完善,以下是咱们从社区引证的一些内容。

Dubbo3 在同程旅行的实践

Dubbo 3 被社区寄予厚望,将其视为下一代云原生服务结构打造,Dubbo3 供给的中心特性列表,主要包括四部分。

  1. 全新服务发现模型。运用粒度服务发现,面向云原生规划,适配基础设施与异构体系;性能与集群伸缩性大幅提升。
  2. 下一代 RPC 协议 Triple。基于 HTTP/2 的 Triple 协议,兼容 gRPC;网关穿透性强、多语言友好、支撑 Reactive Stream。
  3. 一致流量管理模型。面向云原生流量管理,SDK、Mesh、VM、Container 等一致管理规矩;能够支撑更丰富的流量管理场景。
  4. 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 落地的计划需求满意以下三点要求:

  1. Dubbo3 要接入现有的控制中心,由控制中心完结服务注册发现和服务管理功用
  2. Dubbo3 能够和 DSF 能够彼此调用,满意此要求需求两个结构能够互相服务发现并且协议能够兼容
  3. 经过插件机制完结所有功用,不能修正 Dubbo 源码,用户能够自由地晋级 Dubbo3 SDK 的版别

服务注册发现兼容

既然需求将 Dubbo3 的运用级注册接入到控制中心,并且需求与 DSF 服务进行服务发现,就需求了解 Dubbo3 运用级发现的流程才能对其进行更好的拓展。

运用级服务发现中心原理

Dubbo3 在同程旅行的实践

咱们从 Dubbo 最经典的作业原理图说起。Dubbo 从规划之初就内置了服务地址发现的能力,Provider 注册地址到注册中心,Consumer 经过订阅实时获取注册中心的地址更新,在收到地址列表后,Consumer 基于特定的负载均衡策略建议对 Provider 的 RPC 调用。

在这个过程中:

  1. 每个 Provider 经过特定的 key 向注册中心注册本机可访问地址
  2. 注册中心经过这个 key 对 Provider 实例地址进行聚合
  3. Consumer 经过同样的 key 从注册中心订阅,以便及时收到聚合后的地址列表

能够看到接口级服务发现是以接口为维度进行服务注册的,并在注册数据上携带了服务的装备和元数据。这种办法简略易用并且能够轻松实现运用、接口、办法粒度的服务管理。但由此带来的注册数据的放大问题会给注册中心造成较大压力,还有便是与现在云原生的服务模型并不兼容,不能与 Kubernetes 兼容。

面对这些缺乏,在 Dubbo3 架构下社区认真思考了两个问题:

  1. 如安在保留易用性、功用性的一起,重新组织 URL 地址数据,防止冗余数据的出现,让 Dubbo 3 能支撑更大规模集群水平扩容?
  2. 如安在地址发现层面与其他的微服务体系如 Kubernetes、Spring Cloud 打通?

Dubbo3 在同程旅行的实践

终究,社区给出的计划也是十分奇妙和经典,将之前接口级服务的数据拆成两部分。归于实例模型的 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 个关键的过程:

  1. 经过元数据的 mapping 获取接口对应的服务名或许经过接口装备中的 providerBy 指定
  2. 经过服务名获取实例列表,实例以 ip、port 为维度,并且在实例信息中携带元数据的 revision
  3. 调用 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 服务的流程:

Dubbo3 在同程旅行的实践

完结服务发现的兼容之后,用户在调用 DSF 服务的时分仅需求在接口上经过 providerBy 指定接口对应的服务即可,运用本钱极低。

协议兼容与服务管理

协议兼容

完结服务发现的彼此兼容之后,离 Dubbo 与 DSF 服务的彼此调用的方针只剩终究一块拼图,在插件中实现 DSF 协议即可。

相比服务发现的各种数据兼容,协议的兼容比较清晰,只需求根据 Dubbo 协议扩展阐明进行自定义协议扩展完结 DSF 数据格局兼容即可。

Dubbo 协议扩展需求实现以下接口:

  • org.apache.dubbo.rpc.Exporter
  • org.apache.dubbo.rpc.Invoker
  • org.apache.dubbo.rpc.Protocol

Dubbo3 在同程旅行的实践

当用户调用 refer() 所返回的 Invoker 目标的 invoke() 办法时,协议需相应执行同 URL 远端 export() 传入的 Invoker 目标的 invoke() 办法。其间,refer() 返回的 Invoker 由协议实现,协议一般需求在此 Invoker 中发送长途恳求,export() 传入的 Invoker 由结构实现并传入,协议不需求关心。也便是说服务供给方在容器启动的时分就进行服务的暴露,而服务调用方需求经过协议进行Invoker的调用。咱们的扩展如下:

Dubbo3 在同程旅行的实践

终究完结的效果如下,用户只需求在 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 社区的昌盛。