一文聊透 Dubbo 元数据中心
前言
如果让你在本地构建一个 Dubbo 应用,你会需要额外搭建哪些中间件呢?如果没猜错的话,你的第一反应应该是注册中心,类 Dubbo 的大多数服务治理框架都有注册中心的概念。你可以部署一个 Zookeeper,或者一个 Nacos,看你的喜好。但在 Apache Dubbo 的 2.7 版本后,额外引入了两个中间件:元数据中心和配置中心。
在今年年初 Dubbo 2.7 刚发布时,我就写了一篇文章 《Dubbo 2.7 三大新特性详解》,介绍了包含元数据中心改造在内的三大新特性,但一些细节介绍没有详细呈现出来,在这篇文章中,我将会以 Dubbo 为例,跟大家一起探讨一下服务治理框架中元数据中心的意义与集成细节。
元数据中心介绍
服务治理中的元数据(Metadata)指的是服务分组、服务版本、服务名、方法列表、方法参数列表、超时时间等,这些信息将会存储在元数据中心之中。与元数据平起平坐的一个概念是服务的注册信息,即:服务分组、服务版本、服务名、地址列表等,这些信息将会存储在注册中心中。稍微一对比可以发现,元数据中心和注册中心存储了一部分共同的服务信息,例如服务名。两者也有差异性,元数据中心还会存储方法列表即参数列表,注册中心存储了服务地址。上述的概述,体现出了元数据中心和注册中心在服务治理过程中,担任着不同的角色。为了有一个直观的对比,我整理出了下面的表格:
元数据 | 注册信息 | |
---|---|---|
职责 | 描述服务,定义服务的基本属性 | 存储地址列表 |
变化频繁度 | 基本不变 | 随着服务上下线而不断变更 |
数据量 | 大 | 小 |
数据交互/存储模型 | 消费者/提供者上报,控制台查询 | PubSub 模型,提供者上报,消费者订阅 |
主要使用场景 | 服务测试、服务 MOCK | 服务调用 |
可用性要求 | 元数据中心可用性要求不高,不影响主流程 | 注册中心可用性要求高,影响到服务调用的主流程 |
下面我会对每个对比点进行单独分析,以加深对元数据中心的理解。
职责
在 Dubbo 2.7 版本之前,并没有元数据中心的概念,那时候注册信息和元数据都耦合在一起。Dubbo Provider 的服务配置有接近 30 个配置项,排除一部分注册中心服务治理需要的参数,很大一部分配置项仅仅是 Provider 自己使用,不需要透传给消费者;Dubbo Consumer 也有 20 多个配置项。在注册中心之中,服务消费者列表中只需要关注 application,version,group,ip,dubbo 版本等少量配置。这部分数据不需要进入注册中心,而只需要以 key-value 形式持久化存储在元数据中心即可。从职责来看,将不同职责的数据存储在对应的组件中,会使得逻辑更加清晰。
变化频繁度
注册信息和元数据耦合在一起会导致注册中心数据量的膨胀,进而增大注册中心的网络开销,直接造成了服务地址推送慢等负面影响。服务上下线会随时发生,变化的其实是注册信息,元数据是相对不变的。
数据量
由于元数据包含了服务的方法列表以及参数列表,这部分数据会导致元数据要比注册信息大很多。注册信息被设计得精简会直接直接影响到服务推送的 SLA。
数据交互/存储模型
注册中心采用的是 PubSub 模型,这属于大家的共识,所以注册中心组件的选型一般都会要求其有 notify 的机制。而元数据中心并没有 notify 的诉求,一般只需要组件能够提供 key-value 的存储结构即可。
主要使用场景
在服务治理中,注册中心充当了通讯录的职责,在复杂的分布式场景下,让消费者能找到提供者。而元数据中心存储的元数据,主要适用于服务测试、服务 MOCK 等场景,这些场景都对方法列表、参数列表有所诉求。在下面的小节中,我也会对使用场景进行更加详细的介绍。
可用性要求
注册中心宕机或者网络不通会直接影响到服务的可用性,它影响了服务调用的主路径。但一般而言,元数据中心出现问题,不会影响到服务调用,它提供的能力是可被降级的。这也阐释了一点,为什么很多用户在 Dubbo 2.7 中没有配置元数据中心,也没有影响到正常的使用。元数据中心在服务治理中扮演的是锦上添花的一个角色。在组件选型时,我们一般也会对注册中心的可用性要求比较高,元数据中心则可以放宽要求。
元数据中心的价值
小孩子才分对错,成年人只看利弊。额外引入一个元数据中心,必然带来运维成本、理解成本、迁移成本等问题,那么它具备怎样的价值,来说服大家选择它呢?上面我们介绍元数据中心时已经提到了服务测试、服务 MOCK 等场景,这一节我们重点探讨一下元数据中心的价值。
降低地址推送的时延
由于注册中心采用的是 PubSub 模型,数据量的大小会直接影响到服务地址推送时间,不知道你有没有遇到过 No provider available
的报错呢?明明提供者已经启动了,但由于注册中心推送慢会导致很多问题,一方面会影响到服务的可用性,一方面也会增加排查问题的难度。
在一次杭州 Dubbo Meetup 中,网易考拉分享了他们对 Zookeeper 的改造,根源就是
推送量大 -> 存储数据量大 -> 网络传输量大 -> 延迟严重
这一实际案例佐证了元数据改造并不是凭空产生的需求,而是切实解决了一个痛点。
服务测试 & 服务 MOCK
在 Dubbo 2.7 之前,虽然注册中心耦合存储了不少本应属于元数据的数据,但也漏掉了一部分元数据,例如服务的方法列表,参数列表。这些是服务测试和服务 MOCK 必备的数据,想要使用这些能力,就必须引入元数据中心。例如开源的 Dubbo Admin 就实现了服务测试功能,用户可以在控制台上对已经发布的服务提供者进行功能测试。可能你之前有过这样的疑惑:为什么只有 Dubbo 2.7 才支持了服务测试呢?啊哈,原因就是 Dubbo 2.7 才有了元数据中心的概念。当然,服务 MOCK 也是如此。
其他场景
可以这么理解,任何依赖元数据的功能,都需要元数据中心的支持。其他场景还包括了网关应用获取元数据来进行泛化调用、服务自动化测试等等。再描述一个可能的场景,抛砖引玉。在一次南京 Dubbo Meetup 上,dubbo.js 的作者提及的一个场景,希望根据元数据自动生成 NodeJs 代码,以简化前端的开发量,也是元数据的作用之一。这里就需要发挥各位的想象力了
Dubbo 配置元数据中心
目前 Dubbo 最新的版本为 2.7.4,目前支持的几种元数据中心可以从源码中得知(官方文档尚未更新):
支持 consul、etcd、nacos、redis、zookeeper 这五种组件。
配置方式如下:
1 | nacos://127.0.0.1:8848 = |
元数据存储格式剖析
前面我们介绍了元数据中心的由来以及价值,还是飘在天上的概念,这一节将会让概念落地。元数据是以怎么样一个格式存储的呢?
以 DemoService 服务为例:
1 | <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" executes="4500" retries="7" owner="kirito"/> |
首先观察在 Dubbo 2.6.x 中,注册中心如何存储这个服务的信息:
1 | dubbo://30.5.120.185:20880/com.alibaba.dubbo.demo.DemoService? |
例如 bean.name
和 owner
这些属性,肯定是没必要注册上来的。
接着,我们在 Dubbo 2.7 中使用最佳实践,为 registry 配置 simplified=true:
1 | <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" executes="4500" retries="7" owner="kirito"/> |
之后再观察注册中心的数据,已经变得相当精简了:
1 | dubbo://30.5.120.185:20880/org.apache.dubbo.demo.api.DemoService? |
被精简省略的数据不代表没有用了,而是转移到了元数据中心之中,我们观察一下此时元数据中心中的数据:
最佳实践
元数据中心是服务治理中的一个关键组件,但对于大多数用户来说还是一个比较新的概念,我整理了一些我认为的最佳实践,分享给大家。
- 从 Dubbo 2.6 迁移到 Dubbo 2.7 时,可以采取三步走的策略来平滑迁移元数据。第一步:Dubbo 2.6 + 注册中心,第二步:Dubbo 2.7 + 注册中心 + 元数据中心,第三步:Dubbo 2.7 + 注册中心(simplified=true) + 元数据中心。在未来 Dubbo 的升级版本中,registry 的 simplified 默认值将会变成 true,目前是 false,预留给用户一个升级的时间。
- 应用在启动时,会发布一次元数据,在此之后会有定时器,一天同步一次元数据,以上报那些运行时生成的 Bean,目前用户不可以配置元数据上报的周期,但可以通过
-Dcycle.report
关闭这一定时器。 - 元数据中心推荐选型:Nacos 和 Redis。
Dubbo 2.7 还有很多有意思的特性,如果你对 Dubbo 有什么感兴趣的问题,欢迎在文末或者后台进行留言,后面我会继续更新 Dubbo 系列的文章。
一文聊透 Dubbo 元数据中心