实践案例:同程艺龙Dubbo升级经验总结。感兴趣的朋友可以访问官网了解更多详情,或搜索并关注官方微信公众号,关注ApacheDubbo的最新动态。作者信息:严昊:同程艺龙高级开发人员,负责服务治理相关工作,ApacheDubboCommitter。徐浩:同程艺龙高级开发人员,负责服务治理相关工作。Dubbo3在同程旅行的实践背景微服务发展初期,市场上还没有成熟流行的RPC框架。我们公司内部开发了一套名为DSF(DistributedServiceFramework)的RPC框架,支撑了公司业务的快速发展。然而,随着技术的快速迭代和人员的不断更替,开发者不得不修复之前的bug,紧跟技术更新,开发和维护的成本越来越高。另一方面,现在应用正在朝着云原生的方向进行开发和设计,企业也在这方面进行探索。因此,公司微服务框架的演进走到了岔路口。是升级原有的SDK还是选择拥抱开源?考虑到升级已有的SDK在一段时间后可能仍会面临目前的问题,我们最终选择了拥抱开源。经过一番调研,我们选择了Dubbo3作为公司的下一代RPC框架,作为微服务治理体系的数据平面。目前在公司完成了Dubbo3的开发。通过这篇文章,我们对Dubbo3在公司内部的实践和收益做了一个深入的总结。Dubbo3核心功能介绍Dubbo社区关于Dubbo3的文档和资料越来越完善。以下是我们从社区引用的部分内容。Dubbo3被社区寄予厚望,被视为下一代云原生服务框架。Dubbo3提供的核心特性列表主要包括四个部分。一种新的服务发现模型。应用粒度服务发现,云原生设计,适应基础设施和异构系统;性能和集群可扩展性得到极大提升。下一代RPC协议Triple。基于HTTP/2Triple协议,兼容gRPC;网关穿透力强,多语言友好,支持ReactiveStream。统一的流量治理模型。对于云原生的流量治理,SDK、Mesh、VM、Container等统一的治理规则可以支持更丰富的流量治理场景。服务网格。在最新的3.1.0版本中,支持SidecarMesh和ProxylessMesh,提供更多的架构选择,降低迁移和落地成本。Dubbo3的核心功能(比如以ip和port为区分实例的应用级服务发现)和公司内部的服务模型是一致的,大大减少了我们的适配工作。另外,ServiceMesh中对SidecarMesh和ProxylessMesh的支持,也将降低后续企业探索Mesh方案的成本,包括在多语言体系下开发的Dubbo3也提供了对异构架构的支持。总的来说,Dubbo3非常适合公司的技术体系和后续的发展方向。此外,开发者对Dubbo的熟悉程度、社区活跃度高、文档完善也能为Dubbo3的推广使用带来不小的帮助。在了解了Dubbo3的核心功能和基本工作原理之后,我们开始了前期工作阶段。公司有微服务系统RPC框架DSF和控制中心,承担服务发现、路由、加载和卸载等功能,如果让用户直接切换到Dubbo3,使用一套完全隔离的微服务系统,将给用户带来高升级和成本。转移成本。所以我们选择将之前的DSF框架替换为Dubbo3作为数据平面,将Dubbo3接入到现在的微服务控制中心。同时要求Dubbo3支持原有DSF框架的私有协议,能够与DSF框架相互发现和调用,进一步降低用户升级成本。这样用户的编程习惯与Dubbo3的使用完全一致,服务治理(如加载卸载、同心路由、实例标签等)的使用与DSF一致。由于协议的兼容,新的Dubbo3应用和原有的DSF应用也可以实现相互发现和调用。为实现这一目标,需要扩展Dubbo3SDK的注册模块,支持从现有控制中心进行服务注册和发现,扩展自定义协议,调用DSF服务。借助Dubbo强大的插件机制,我们在不修改Dubbo框架任何代码的情况下,轻松实现了这一目标。用户只需引入3.0及以上版本的DubboSDK和我们开发的插件包即可。整体架构流程如下:Dubbo3实施方案需要满足以下三个需求:Dubbo3需要接入已有的控制中心,由控制中心完成服务注册发现和服务治理功能;Dubbo3和DSF可以相互调用来满足这个需求,需要两个框架能够相互发现,协议兼容;所有功能均通过插件机制完成,Dubbo源码不可修改,用户可自由升级Dubbo3SDK版本;服务注册发现兼容由于Dubbo3的应用级注册需要连接Controlcenter,需要用DSF服务进行服务发现,所以需要了解Dubbo3应用级发现流程,才能更好的进行扩展。应用级服务发现的核心原理我们先从最经典的Dubbo工作原理图说起。Dubbo从设计之初就内置了发现服务地址的能力。提供者向注册中心注册地址,消费者通过订阅从注册中心获取实时地址更新。消费者收到地址列表后,根据特定的负载均衡策略发起一个提供者。RPC调用。在这个过程中:每个Provider通过特定的密钥向注册中心注册本地可访问的地址;注册中心通过这个key聚合Provider实例地址;Consumer通过同一个key向注册中心订阅,从而及时收到聚合地址列表;可以看到接口级的服务发现是以接口作为服务注册的维度,注册数据中携带了服务的配置和元数据。这种方式简单易用,可以轻松实现应用、接口、方法等粒度的服务治理。但是由此带来的注册数据放大会给注册中心带来很大的压力,并且不兼容目前的云原生服务模型,无法兼容Kubernetes。面对这些不足,社区认真思考了Dubbo3架构下的两个问题:如何在保留易用性和功能性的情况下重组URL地址数据,避免冗余数据的出现,让Dubbo3能够支持更大规模的Cluster横向扩展?地址发现层面如何与其他微服务系统如Kubernetes、SpringCloud等进行对接?最后社区给出的解决方案也非常巧妙和经典,将之前接口级服务的数据拆分为两部分。属于实例模型的ip和端口注册到注册中心,而属于业务属性的RPC元数据和RPC服务配置由DubboProvider的MetadataServiceRPC服务统一提供或由元数据中心提供。在服务消费者和提供者之间建立了一种内置的RPC服务信息协商机制,也称为“服务自省”。全新的应用级服务发现模型,相比之前的接口级,单机内存降低50%,大大减轻了注册中心的压力。另一个问题是,切换到应用级服务发现后,消费者如何知道订阅的接口属于哪个服务?因为Dubbo的编程模型是基于接口的。Dubbo3提供了两种解决方案:一种是从元数据中心存储接口与应用名称的映射关系,另一种是通过Consumer在接口上通过providerBy配置手动指定服务提供者名称。如果兼容方案是DubboConsumer调用DubboProvider,我们只需要参考Zookeeper、Nacos等其他应用级服务发现插件一步步开发即可完成该功能。如果DSFClient要调用DubboProvider,我们把兼容逻辑放在控制中心,避免用户SDK的升级成本。剩下的兼容过程只是DubboConsumer调用DSFServer,因为要求尽量不要修改Dubbo框架的源码,所以只能在注册中心的插件中完成这里的兼容逻辑.上面在介绍应用级服务发现的核心原理时,提到了应用级服务发现的三个关键步骤:通过元数据映射获取接口对应的服务名或者通过接口配置中的providerBy指定;通过服务名获取实例列表,实例以ip和port为维度,在实例信息中携带元数据的修订;调用DubboProvider的MetaService获取实例的元数据信息,组装接口数据;Dubbo服务调用DSF服务兼容过程的第一步非常简单,因为DSF没有接口和服务名的映射数据,所以通过providerBy指定接口所属的DSF服务名。第二步,DSF服务的注册模型也是应用级的,实例的数据是完全兼容的。这部分也很简单。最关键的一步是如何获取DSF服务的元数据。显然,现有的DSF服务没有MetaService接口。上文提到,Dubbo3支持两种获取实例元数据的方式。默认是从DubboProvider的MetaService获取实例的元数据信息,同时也支持从元数据中心获取实例的元数据信息。只需要将实例的dubbo.metadata.storage-type属性设置为remote即可。DSF服务只是将API的合约数据发布到控制中心,用于服务测试和寻址兼容性。完全可以将DSF的合约数据转换成Dubbo的元数据格式来满足服务发现的过程。下面是DubboConsumer发现DSF服务的过程。服务发现兼容完成后,用户在调用DSF服务时只需在接口上通过providerBy指定接口对应的服务即可,使用成本极低。ProtocolCompatibilityandServiceGovernanceProtocolCompatibility在完成了服务发现的相互兼容之后,Dubbo和DSF服务相互调用的目标只剩下最后一块拼图了,就是在插件中实现DSF协议.相对于服务发现的各种数据的兼容性,协议的兼容性是比较明确的。只需要根据Dubbo协议扩展说明扩展自定义协议即可完成DSF数据格式的兼容。Dubbo协议扩展需要实现如下接口:org.apache.dubbo.rpc.Exporterorg.apache.dubbo.rpc.Invokerorg.apache.dubbo.rpc.Protocol当用户调用返回的Invoker对象的invoke()方法时通过refer(),协议需要相应地执行从URL远程export()传入的Invoker对象的invoke()方法。其中,refer()返回的Invoker是由协议实现的,协议通常需要在这个Invoker中发送远程请求,而export()传入的Invoker是由框架实现并传入的,协议不需要关心。也就是说,服务提供者在容器启动时暴露服务,服务调用者需要通过协议调用Invoker。我们的扩展如下:最终效果如下,用户只需要在pom中引入Dubbo3以上任意版本和开发的插件,在配置中指定注册中心地址和协议为dsf即可,其他用法方法与Dubbo3一致。
