分布式配置中心调研

1. 调研背景

由于公司目前存在三套与配置相关的组件,其中两套是自研的,一套是 Spring Cloud Config。
综合来看,它们都存在如下问题:

  • 无版本控制
  • 无回滚功能
  • 无流程治理
  • 无客户端配置信息监控
  • 无灰度发布功能
  • 权限粒度太粗
  • 存在高可用问题

导致大家在提意(tu)见(cao)的时候,纷纷将矛头对准了我们的配置中心。
再加上公司层面上对权限的重视,我决定找一个能解决上述问题,并将技术栈做到统一的分布式配置中心。

2. 调研对象

业界常用的配置中心有以下几个:

  • Apollo(携程,活跃)
  • Nacos(阿里,活跃)
  • Spring Cloud Config(Pivotal,活跃,以下简称 SCC)
  • Qconfig(去哪儿,最后更新于 2019 年)
  • Diamond(淘宝 2011,最后更新于 2017 年)
  • Disconf(百度个人 2015,最后更新于 2016 年)

由于后三个社区已经不活跃了,所以将其排除在外。

3. 调研内容

3.1. 概况

概况ApolloNacosSCC
定位Apollo(阿波罗)是携程框架部门研发的分布式配置中心。Nacos 致力于帮助您发现、配置和管理微服务,服务(Service)是一等公民。Spring Cloud Config provides server-side and client-side support for externalized configuration in a distributed system.
开发语言JavaJavaJava
官网https://ctripcorp.github.io/apollo/https://nacos.io/zh-cn/https://cloud.spring.io/spring-cloud-config
最新版本1.7.1(2020.8.16)1.4.1(2021.1.15)3.0.1(2021.1.9)
社区活跃*高(☆23.6k,GT 23)中(☆16.1k,GT 10)低(☆1.6k,GT 2)
依赖JDK 1.8+,MySQL 5.6.5+JDK 1.8+JDK,Git or MySQL or ConfigMap,MQ
SDKJava、Go、Python、NodeJSJava、Go、Python、NodeJSJava
文档完善,中文尚可,中文尚可,英文
配置界面一个界面管理不同环境、不同集群配置不同环境、不同集群
数据存储MySQLMySQLGit 或 MySQL 或 ConfigMap
推拉模型长轮询长轮询MQ
配置生效实时(1s)实时(1s)重启生效,或手动 refresh 生效
数据类型properties、json、yaml、xml、txtproperties、json、yaml、xml、txt、htmlproperties、json、yaml
存储限制配置项 key 最大长度限制默认 128
配置项 value 最大长度限制默认 20000
一个 namespace 限制了 200 个配置,未找到长度限制与存储有关

社区活跃:
能反映社区活跃情况的指标有很多,这里仅从 GitHub star 数和 Google 趋势来看,能反映出部分情况了。☆ 代表 GitHub star 数,GT 代表各项在 Google Trends 里过去 12 个月在中国区域的热度。
Github 更详细的信息对比可参考下图:

3.2. 功能

功能点ApolloNacosSCC
配置界面一个界面管理不同环境、不同集群配置不同环境、不同集群,不同界面
配置生效时间实时实时重启或手动
版本管理支持(更改历史+发布历史)支持(保留 30 天)不支持(或依赖 git)
回滚支持支持不支持(或依赖 git)
灰度发布支持支持不支持
权限管理支持修改、发布权限分离,namespace 分为 public 和 private,OpenAPI 也支持权限弱鉴权体系,粒度只能到命名空间的读写,OpenAPI 支持 token无(或自研或基于 git)
审核审计支持无(或自研或基于 git)
继承模式支持不支持支持
配置加密提供了 case不支持支持
跨环境同步配置支持不支持不支持
跨环境比较配合支持不支持不支持
实例配置监控可以方便的看到当前哪些客户端在使用哪些配置支持不支持
监听配置变化事件支持支持基于扩展点开发
客户端支持原生提供 Java 和 .NET,社区有其他语言的原生提供 Java,社区有其他语言的可以认为仅有 Java
SpringBoot 集成支持支持支持
Open API获取App的环境,集群信息
获取App信息
获取集群接口
创建集群接口
获取集群下所有Namespace信息接口
获取某个Namespace信息接口
创建Namespace
获取某个Namespace当前编辑人接口
读取配置接口
新增配置接口
修改配置接口
删除配置接口
发布配置接口
获取某个Namespace当前生效的已发布配置接口
回滚已发布配置接口
获取配置
监听配置
发布配置
删除配置
查询历史版本
查询历史版本详情
查询配置上一版本信息
获取配置
统一登录支持 SSO、LDAP 等不支持不支持
其他支持接入邮件服务自带服务注册中心

从功能上来看,特别是在权限管理上,Apollo >> Nacos >> SCC

3.3. 性能

Apollo 性能测试

Nacos 服务配置性能测试报告

Spring Cloud Config:根据 backend 的不同,速度不同。比如若使用 git 存储就比较慢,需要从 git clone repository,然后从文件系统读取。

整体上来看:Apollo 和 Nacos 的性能基本相当,SCC 的性能受后端存储和 MQ 的影响。

3.4. 可用性(可靠性)

Apollo 和 Nacos 均有本地缓存,SCC 无本地缓存但它的更新一般都得手动触发。

Apollo:长轮询(实时获取)+定时主动拉取(5min,fallback)+本地缓存(兜底)

Nacos:长轮询(实时获取)+本地缓存(兜底)

SCC:手动触发

所以可用性方面,Apollo > Nacos > SCC

Apollo 详细的可用性情况:

场景影响降级原因
某台 config service 下线无影响Config service 无状态,客户端重连其它 config service
所有 config service 下线客户端无法读取最新配置,Portal无影响客户端重启时,可以读取本地缓存配置文件
某台 admin service 下线无影响Admin service 无状态,Portal 重连其它 admin service
所有 admin service 下线客户端无影响,portal无法更新配置
某台 portal 下线无影响Portal 域名通过 slb 绑定多台服务器,重试后指向可用的服务器
全部 portal 下线客户端无影响,portal无法更新配置
某个数据中心下线无影响多数据中心部署,数据完全同步,Meta Server/Portal 域名通过 slb 自动切换到其它存活的数据中心

Apollo 客户端的实现原理:

  1. 客户端和服务端保持了一个长连接,从而能第一时间获得配置更新的推送。
  2. 客户端还会定时从 Apollo 配置中心服务端拉取应用的最新配置。
    • 这是一个 fallback 机制,为了防止推送机制失效导致配置不更新
    • 客户端定时拉取会上报本地版本,所以一般情况下,对于定时拉取的操作,服务端都会返回 304 - Not Modified
    • 定时频率默认为每5分钟拉取一次,客户端也可以通过在运行时指定 System Property: apollo.refreshInterval 来覆盖,单位为分钟。
  3. 客户端从 Apollo 配置中心服务端获取到应用的最新配置后,会保存在内存中
  4. 客户端会把从服务端获取到的配置在本地文件系统缓存一份
    • 在遇到服务不可用,或网络不通的时候,依然能从本地恢复配置
  5. 应用程序从 Apollo 客户端获取最新的配置、订阅配置更新通知

3.5. 扩展性

Apollo、Nacos 都有 Open API,但是 Apollo 的 Open API 不论从功能上还是安全性上,都是比 Nacos 强的。

SCC 只有获取配置的接口,无更多能力。

另外 Apollo 支持接入多种登录系统,并有官方指南。Nacos 文档上没找到相关说明,但改源码肯定也能实现。SCC 无该能力。

所以从扩展性上,Apollo >> Nacos > SCC

3.6. 易用性

在界面的使用上,

  • Nacos 和 SCC 均是只支持多环境独立部署。
  • Apollo 除了支持独立部署,还支持一套 Portal (可以认为是 AdminUI)可以管理多个环境,但是每个环境都需要独立部署一套 Config Service、Admin Service 和 ApolloConfigDB,也就是说管理界面是只有一个,但是配置数据&服务是物理隔离的。

另外在配置对比上,

  • Nacos 只能在发布的时候与上一个版本进行对比
  • Apollo 支持不同环境、不同版本上的对比

在客户端的使用上,

  • Apollo 和 Nacos 均支持 API 方式和 Spring 整合方式,且均提供监听配置变化事件的 API。
  • SCC 仅支持和 Spring 整合的方式,未提供监听回调 API。

所以在易用性方面,Apollo > Nacos >> SCC

3.7. 外部依赖

Apollo

  • MySQL

  • 在 1.7.0 之前依赖 Eureka,在 1.7.0 版本增加了基于 Kubernetes 原生服务发现的部署模式,不再必须依赖 Eureka,对环境的要求如下:

    • Kubernetes 1.10+
    • Helm 3

Nacos:

  • MySQL

SCC:

  • Git 或 MySQL 或 ConfigMap
  • MQ

在环境 Kubernetes 1.10+ 的情况下,对外部的依赖性 Apollo ≈ Nacos > SCC

3.8. 部署

Nacos 和 SCC 的集群部署比较简单,Apollo 的集群部署较为复杂一些。

但部署是一次性的事,仅做参考,不应作为关键指标。

3.9. 迁移复杂度

基于现有的系统,现有配置的迁移复杂度是 Apollo ≈ Nacos > SCC

但我们更多的考虑不是适合现在的情况,而是配置中心应该是什么样的,以及怎样才更适合未来的发展。

所以也仅做参考,不作为关键指标。

4. 调研结论

综合来看,Apollo、Nacos、SCC 三者比较各项得分如下:

对比项ApolloNacosSpring Cloud Config
功能531
性能44需单独讨论
可用性(可靠性)543
扩展性532
易用性431
外部依赖442
简单综合得分27219+

虽说简单相加的得分有点“简单粗暴”,但也能反映出问题了。(其实如果加权的话,Apollo 也会是遥遥领先的状态)

综上,Apollo 更适合作为部门或者公司级的配置中心。

(最终我们选择的也是 Apollo)

附:游戏 Excel 配置接入 Apollo

在做游戏的时候,经常会有许多游戏内的配置项,比如概率等。
策划或运营同学们已经习惯了使用 Excel 来配置(主要是可以使用 Excel 公式,他们操作起来会比较方便)。
所以针对于该类 Excel 配置,如何在不改变非技术同学的使用习惯的前提下,既提升开发效率又保障数据安全呢?
其实加一个 bridge 就可以解决了。

流程大致如下:


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!