开发者学堂课程【2022阿里云云原生中间件开发者大会集锦:饿了么 Dubbo3 实践分享】学习笔记,与课程紧密连接,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/1053/detail/15291
饿了么 Dubb3实践分享
内容介绍:
一、背景介绍
二、Dubb3原理
三、饿了么具体领域升级
一、背景介绍
Dubb3的实践的一次分享。饿了么从去年11月份启动了整个 Dubb3的升级工作,在此之前,饿了么的服务框架使用 H2,而从 HEV2W3的总体升级过程。
目前已基本目前已基本完成,有将近2000个应用和10万个节点,目前是跑在Dubb3之上。
那通过这次分享,主要是想给大家同步饿了么在 double 三升级过程当中的一些经验总结,为什么升级到 Dubb3,和大部分升级的具体流程以及中间遇到的问题,尤其是我们重点关注的用途发现模型,如何从接口及迁移到新的 Dubb3的应用及地址发现模型,并最终实现预期的价格目标。
当然在此之前我们先对 Dubb3做一个总体的介绍,Dubb3是我们定义是下一代的原生微博框架,从设计原则上 ,Dubb3首先它是面向原生的,支持百万集群实例的可伸,强调对于周迅和市场化的调度。而在业务策略上,整个Dubb3是整个开源的,,在业务价值上,强调对于降低单机的资源消耗,提升整个全链路的资源利用率,以及云原生时代的服务治理的能力。
具体的DOUBLE3D选型,大家一定还会比较关心Dubb3提供了哪些新的功能,而如果你是Dubb用户的话,还关心Dubb的兼容性,那总结起来就是Dubb3的迁移成本以及它能够带来的核心价值。
下面这部分,左边这一部分就是关于Dubb3的一个兼容性的部分,Dubb3从其自身来说,他是从2.0架构演进而来了,因此他继承了整个开源的Dubb2,以及完整的特性以及优点。并且保持了对Dubb2的完全兼容,因此老用户几乎可以做到对于Dubb3的零成本的迁移。
这个是的Dubb3兼容性部分,而右边这一部分,是所Dubb3提供的一些核心的特性列表,我这里列出来主要有四个,第一个是我们今天要重点重点了解的卷新的发现模型,第二点是在Dubb3当中提供的基于HTTP2的下一代的ARP协议,Triple协议。第三部分是double会做的,其实和第四部分是统一在一体的,就是整个的Dubb3 Mesh解决方案。
那在整个Mesh解决方案当中,我会提供Sidecar Mesh和Proxyless Mesh的两种部署架构,同时会探索提供统一的流量治理模型,以及控制面的治理策略。那这张图更直观地反映了Dubb3产生的背景。
他与刚才我们提到的一些重要的历史产品之间的关系,Dubb3诞生的基础是Dubb2和HSF2两款产品,同时以云原生架构作为指导思想,做了一些大量的重构,并规划了一系列的功能特性,这个是Dubb3产生的基础。这些共同组成的Dubb3,也就是我们在给他仓库上和开源官网上看到的Dubb3。
在开源Dubb3产品之上,我们有基于Dubb3的一些企业产品以及公有云厂商的云产品,有大家比较关心的Dubb3的典型用户阿里巴巴,阿里巴巴在内部一直是运行在自研的HR框架之上,它建于HSF2和Dubb2的历史关系,两者之间有很多相似之处,但实际上已经演进成了两个不同的框架。
在实现了Dubb3对于HFS2和Dubb2的融合之后,阿里巴巴正在完全迁移到开源的Dubb3,用来取代HFS2。在此各位听众可能有一些疑问,完全用开源的Dubb3如何满足阿里自身特有的一些诉求?答案就是通过Dubb3开源的标准SD卡扩展。所以阿里内部现在还有一套H3HL3,与以往HFS2完全不同。已经是完全不同的两个框架,HL3完全就是基于标准的Dubb3的SPI生成的一个扩展库,也就是说它仅仅是一个拓展库,比如说注册中心的扩展,路由组件的扩展或者是监控组件的扩展,而其他配置的组装服务、暴露服务、发现机制解析等等这些核心流程都已经是完全跑在外面开源的Dubb3之上。那在这样的模式之下,阿里巴巴的内部实践的诉求。
都将会完全体现在开源的Dubb3上,阿里巴巴包括内部开发人员也是同时工作在Dubb3内部扩展之上,通过SCI扩展这样的模式同样也适用于公有云产品或者是其他的一些厂商的实践。
那升级到Dubb3具体有哪些收益?我这里总结了有三个方面简单描述一下,首先是在性能和资源利用率的提升方面,升级Dubb3利用预期能够实现对于单机资源的接近50%的一个资源利用率的下降,对于月大规模集群这个效果会越明显,同时,我之前提到Dubb3从架构上支持百万实力级别的集群的横向扩展。这个都是Dubb3在性能方面的一些优势,其次借助于Dubb3它提供的比如说新的协议,能够让Dubb3在业务架构升级上提供更多的帮助。比如说之前我们从前端的应用接触到后端的话,都会经过网关的带领,这个网关要做一些协议转换或者是类型映射之类的一些工作,往往的网关都会成为整个架构的瓶颈,在有了协议之后,那这个过程会变的更容易实现,同时也提供了一些流式通信模型的更丰富的通信场景的支持。
最后一点是关于整个Dubb3的云原生的解决方案,包括Dubb3怎么在K8S调度系统下被部署,包括Dubb3.1当中将要提供解决方案等都是属于这一部分。有了这一部分能力的知识能够让业务应用升级到迁移到云原生架构会变得更加容易。以上就是关于Dubb3的一些简单的介绍。
二、Dubb3原理
我们进入今天的重点,下面重点有两部分,一部分是对于整个Dubb3用机发现架构的一个原理的介绍,最后一部分会讲一下饿了么的具体领域升级过程。
先从Dubb3最经典的工作原理图说起,Dubb3从设计之初就内置了服务发现的能力,provide注册地址到注册中心,给他们通过订阅实时的地址更新。那么基于特定的负载均衡策略发起对provide的调用,
这张图上所示在这个过程当中,每个provide通过特定的key。Provide通过特定的配置项,注册中心、注册本金和访问的地址。注册中心通过这个key对provide进行地址聚合,通过同样的key从注册中心去订阅,以便实时收到计划后的地址列表。
对接口的地址发现的内部数据结构进行了一些展开分析,
首先看右下角的provide实例内部的数据,provide部署的应用通常会有多个double service与double服务。
每个service可能都会有其独有的配置,我们所讲的service的服务发布的过程其实就是基于这个服务配置生成地址URL的过程,生成的地址数据就如同中间的橙色部分,这个URL琐事,同样的其他服务也会生成地址。也就是说一个double的实力会生成多个service的URL。
然后我们看一下上面这一部分,注册中心的地址的数据的存储结构的中心,以service服务名作为数据划分的依据,将一个服务下的所有地址数据都作为子节点进行聚合,子节点的内容是实际可访问的IP地址,也就是我们double中的URL的,格式就是刚才我们说的中间的这一部分数据结构。这个是double接口及服务发现的内部的数据结构的一个概括的解析。
我们再看一下刚才提到的这个URL地址的一个详细的格式,我们把URL地址数据划分成几个部分来看,首先第一部分是地址相关的,也就是实例和可访问的地址主要是IP的,是消费端将基于这条数据来生成TCP链接,作为后续RB数据传输的载体。
那第二部分是RPC服务的元数据,这个这部分数据主要是用于定义和描述一次RPC请求,一方面它表明这条地址数据是与某条具体的RPC服务有关的,比如说它的接口名,它的版本号分组以及方法定义等等。那第三部分是RPC相关的配置数据,有一些配置适用于控制RPC调用的行为,还有一些配置可能是用于同步provide专进程实例的一些状态到消费端的典型的配置,就像这列的如超时时间,还有序列化编码的方式。那最后一部分是通常是业务自定义的一些元数据,这部分内容用于区分以上框架预定义的各项配置,给用户提供了更大的灵活性,用户可以对它进行任意扩展,把状态同步到消费端。
这个是地址格式的一个详细解析,那结合上面两页的对Dubb2接口及地址模型的分析,我们可以得出下面的这样几条结论,首先地址发现聚合的K在接口及服务发现模型当中,就是RPG励志的服务,也就是比如说我们在Java当中经常说的定义Dubb的服务的接口,那第二点注册中心同步的数据的不只是包含地址,同样还包含了各种元数据以及配置。
那第三点得益于前面的第一点和第二点,Double就可以实现支持各种不同力度的,比如说应用力度,RPC服务力度,甚至于方法力度的服务治理的能力。
因为Dubb在这个地址风筝过程当中,同步的数据是很丰富的,那这就是一直以来Dubb在医用服务治理功能性可扩展性会发现强于很多其他框架的一个核心的原因。
我们就知道一个事物总是有其两面性,Dubb2虽然是带来了易用性和强大的功能,但是在实践过程当中,我们也逐渐发现他在整个架构的水平可扩展性。
带来的一些限制,那这个问题在普通的微服务咨询下是通常是感知不到的,而当集群的规模逐渐增长,当即训练的应用和机器数量达到一定量的时候,整个集群的组建就会发现遇到开始遇到一些规模瓶颈,那这个是在总结包括像阿里巴巴或者是工商银行等这些典型用户生产环境的使用得到的一些经验,主要有以下两个突出的问题,
就如同左边的这个架构图当中标为橙色的这两部分,首先是注册中心集群的容量会更容易达到上限,由于我们所有的url地址数据都被发送到注册中心,注册中心的存储容量会达到上限,推送效率也会下降,而在消费端这一侧,Dubb2的常驻的内存通常已经占用整个业务进程的超过40%,那每次地址推送带来的动态的CPU的资源消耗,或者是资源的波动也是非常明显的,甚至影响正常的业务调用。那我们分析一下,这里是把蓝色这一部分拆开来看,通过一个事例来尝试分析一下为什么会有这个问题,然后假设我们这里有一个普通的应用,该应用内部有十个service,也就是Dubb3的服务应用被部署在一百个机器实力之上,在这个应用在进行中产生的数据量会是什么样的,其他就是我们之前分析的有十个service有部署在一百个机器上,那它产生的数据量就是十乘以一百,有一千条url的数据,我们可以看到整个数据呢是被从两个维度进行放大,从地址的角度,我们本来有一百个机器实力,就是一百条唯一的地址数据被放大了十倍,那从服务的角度来说,因为我服务的元数据在一个应用内,不论你不知道多少机器,可能很大程度上都是唯一的那十条,这唯一的元素被放大了100倍,这个是对于为什么会有这个问题的一个原因的分析。
面对这个问题,在Dubb3架构下,我们就不得不深入的思考如何应对,如何在保留易用性和功能性的同时,我们能不能尝试重新组织URL地址数据。
让Dubb3能够支撑更大规模集群水平的扩容,那第二点是如何在地址发现上面,因为Dubb2的接口地址发现模型是相对来说是自己独有的,如何在地址发现层面与其他的微服务体系,比如说operated或者spring cloud这些进行打通。
这个是Dubb3设计研究发现的两个主要考虑的问题。
那在分析Dubb3发现的具体实现之前,我们先来回过头来继续看一下之前的接口提的一个URL的地址格式,地址链路上,我们之前说到接口及的聚合的元素是我们之前提到的K是RPC服务,那我们在应急方面当中,设计的思路是把这个K聚合的可以由服务调整为应用,这也是为什么应急发现的名称是这叫做应急方向的一个原因,另外我们通过注册对注册中心的数据的大幅的精简,像这里之前提到的RPG元数据,RPC服务配置一些自定义的一些2B的元数据,我们都在整个地址推送的流程当中给他精简掉了,只保留了最核心的iPod,通过只保留这份这部分数据的,我们对整个应用激发线路传输的地址的数据量进行了大幅度的精简。
这里就是升级之后应急,服务发现的一些内部数据结构。就这里就进行了一些详细的分析,我们可以发现和之前的接口及地址发现模型的一些不同,主要是图中的橙色部分。
首先在provide实力这一刻,相比之前每个rpcservice都注册一条的数据,现在一个provide部署的机器实力只会注册一条地址到注册中心,而在注册中心这一侧。
地址开始以一种名为力度进行聚合应用节点。节点下是经过精简过后的一些provide的实力,我们可以看到这个新生成的这个URL是已经只包含了iPod,应急发现的上述调整的同时实现了地址单条数据大小和地址总数量的下降,但同时也带来了一些新的挑战,我们之前Dubbo2强调的易用性和功能性的基础基本上就损失掉了,因为原数据的传输被精简掉了,
那如何精细的控制单个服务的行为就变得无法实现。针对这个问题,Dubbo3的解法是引入一个内置的元数据服务,叫做manager service。在引入这个元数据服务以后,我们以前由中心化的注册中心来同步元数据从provide到consumer同步,过去的这个行为,就变成了一个点对点拉扯的行为,就是消费端在收到。纯粹的IP和Mac地址通知以后呢,他会通过这个manager service去找相应的provide之上进行点对点的源数据的一些读取,在这个模式下,原数据传输传输的数据量就不再是一个问题,因此我们甚至于可以在原数据服务或者元数据的内容之上扩展出更多的参数,结合刚才我们说的注册中心测的精简以及元素。
数据服务以后,它的一个基本的工作原理在这里重点是看consumer测的地址订阅行为。消费端从现在在新的Dubbo3实现当中,是要分两步来完成整个地址的读取以及主张工作。首先是从注册中心收到之前提的精简后的IP port这样的一个地址,随后通过调用service元数据。读取到对端的元素信息。在收到这两份数据之后,消费端会完成地址数据的聚合的这样一个过程,最终在运行还原出来之前类似Dubbo2的这样的一个URL的地址格式,因此可以从运行态的最终结果而言,应急地址模型同时兼顾了传输层面的性能与运行层面的功能性。以上就是应用发现模型的整个的设计背景、工作原理部分。
三、饿了么具体领域升级
接下来我们看一下饿了么升级的Dubbo3,尤其是已经发现了一个完整的过程,在这里是饿了么的一个基本的部署的架构图。
在升级之前,Dubbo3微服务框架采用的都是HR2跨单元的RPC调用是通过这中间的这样的一个proxy的一个中心化部署的一个代理来完成中转的。那在这个过程当中,Proxy所承载的机器数和流量就会看到有迅速的增长,和我们应急服务发现以及地址发现模型相关的问题,比较突出的一点就是proxy需要订阅两侧的所有的地质数据。因此在整个存储和数据聚合方面,他的资源消耗和稳定性都受到了严重的挑战,因此我们设想通过double升级Dubbo3,结合整个架构升级来实现业务侧的两个目标,来解决掉这个proxy的。包括通过proxy集中式的流量调度,以及profit所面临的地址存储和推送一些压力。我们希望达到的主要的两个目标?首先第一点是将整个地址模型切换到应急发现这样一个例子模型,从而大幅度减轻中心化节点和消费端节点的资源消耗压力。那第二点是应急发现架构下的全局共享的注册中心来取代proxy需要订阅所有的就做双订阅,订阅两侧不同的做到中心的这样的一个模型,实现跨单元的节点的通信的直连,不论是针对Dubbo2和HR2是我们我们之前提到Dubbo3都做了全面的API兼容,因此升级了Dubbo3对饿了么这一侧来说是可以做到零改造升级的,并且每个应用都可以进行独立的升级,不需要关心他的上下游应用的一个升级状态,因此Dubbo3升级之后,不论是从地址发现模型还是协议的默认行为,都是保持了与2.0版本的兼容,用户可以在任意时间点对任意的应用按需切换Dubbo3的行为,
我们看右边这个图的状态,我们这里是模拟展示了饿了么集群。在Dubbo3升级过程当中的一个中间状态,其中灰色标记代表的是没有升级的H2的老用,橙色和绿色标记是代表了已经升级到Dubbo3的应用。那同时橙色这一部分的应用及其调用链路,它代表的与绿色的区别是它代表的是已经升级升级完Dubbo3,并且已经切换到新的应急发现地址模型的这样的一些应用一些电路。那这里的升级过程主要是为了说明两点,一个是Dubbo3框架升级,他在API和默认行为方面是完全兼容的,另外一点是对于集训类的应用,以及它升级的Dubbo3以后的地址行为的切换的这样的一个行为是完全独立的。
那接下来我们来就来详细分析一下这里这个橙色节点的这个应用,以及调用调用链路,他在网页就会发现模型迁移的,迁移的时候是具体怎么断。首先来看provide端的,一个行为provide就是服务提供者在升级Dubbo3以后,会默认保持双注册的行为,同时也就是同时注册接口及地址和应用及地址到注册中心,那这一方面是保持了兼容性,另一方面对未来消费端迁移做好了准备,那双紫色的开关就是这里所列出来的开关。那对于保持双注册行为以后,大家可能担心的对于注册中心带来的额外压力?
实际上在应急专业模型下,这个并不是一个问题,因为大家回想我们之前分析的应急发现当中的地址U2是如何精简的,根据我们推算,每多出一条应急发现的URL地址,大概只会带来0.1%不到到1%的这样一个开销。那这里是Dubbo3升级了消费端,消费端以后的一个迁移行为与提供端是非常类似的,要实现平滑迁移消费端的地址模型是不可避免要做一个双立约的过程,那这个流程上就不再赘述。消费者的商业行为可以通过规则和开关进行动态的调整,控制消费端消费的某个服务,某个应用来独立的迁移到应用的地址模型。那除此之外,Dubbo3还内置了自动的一个决策机制。那才发现应用及地址可用的情况下,就可以完成自动的接口机地址盗用基地址的切换,并且这个行为在Dubbo3当中现在是默认开启的。
Dubbo3应急挖掘模型之后,Dubbo3成功地实现了去profit的一个总体的架构目标。饿了么整体部署架构比较复杂,但是对我们对饿了么Dubbo3升级过程的讲解,我们在这里讲的还是比较简单直接,因为服务行业的过程本身像Dubbo的基本工作原理就是比较简单的,它其它核心就是围绕提供者、消费者、注册中心这三个节点的数据同步,那么我们这里从饿了么的升级过程当中,包括这一个PPT的整个的讲解,我觉得需要关注重点有那么三点,第一个是这里对于应用发现它的整体的工作原理的一个总体介绍,第二点Dubbo3的它的一个基本的升级过程,Dubbo3可以实现透明的兼容升级,并且能够按需的来切换地址模型的行为。
那第三点是Dubbo3已经在通过在饿了么的升级,其实饿了么为代表的阿里巴巴内部真正意义上的实现了对于HEV2的替换,并且迁移到新的应用就地址发现了这样的一个模型。