分布式配置中心调研——携程 Apollo
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. 概况
概况 | Apollo | Nacos | SCC |
---|---|---|---|
定位 | Apollo(阿波罗)是携程框架部门研发的分布式配置中心。 | Nacos 致力于帮助您发现、配置和管理微服务,服务(Service)是一等公民。 | Spring Cloud Config provides server-side and client-side support for externalized configuration in a distributed system. |
开发语言 | Java | Java | Java |
官网 | 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 |
SDK | Java、Go、Python、NodeJS | Java、Go、Python、NodeJS | Java |
文档 | 完善,中文 | 尚可,中文 | 尚可,英文 |
配置界面 | 一个界面管理不同环境、不同集群配置 | 不同环境、不同集群 | 无 |
数据存储 | MySQL | MySQL | Git 或 MySQL 或 ConfigMap |
推拉模型 | 长轮询 | 长轮询 | MQ |
配置生效 | 实时(1s) | 实时(1s) | 重启生效,或手动 refresh 生效 |
数据类型 | properties、json、yaml、xml、txt | properties、json、yaml、xml、txt、html | properties、json、yaml |
存储限制 | 配置项 key 最大长度限制默认 128 配置项 value 最大长度限制默认 20000 |
一个 namespace 限制了 200 个配置,未找到长度限制 | 与存储有关 |
社区活跃:
能反映社区活跃情况的指标有很多,这里仅从 GitHub star 数和 Google 趋势来看,能反映出部分情况了。☆ 代表 GitHub star 数,GT 代表各项在 Google Trends 里过去 12 个月在中国区域的热度。
Github 更详细的信息对比可参考下图:
3.2. 功能
功能点 | Apollo | Nacos | SCC |
---|---|---|---|
配置界面 | 一个界面管理不同环境、不同集群配置 | 不同环境、不同集群,不同界面 | 无 |
配置生效时间 | 实时 | 实时 | 重启或手动 |
版本管理 | 支持(更改历史+发布历史) | 支持(保留 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. 性能
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 客户端的实现原理:
- 客户端和服务端保持了一个长连接,从而能第一时间获得配置更新的推送。
- 客户端还会定时从 Apollo 配置中心服务端拉取应用的最新配置。
- 这是一个 fallback 机制,为了防止推送机制失效导致配置不更新
- 客户端定时拉取会上报本地版本,所以一般情况下,对于定时拉取的操作,服务端都会返回 304 - Not Modified
- 定时频率默认为每5分钟拉取一次,客户端也可以通过在运行时指定 System Property:
apollo.refreshInterval
来覆盖,单位为分钟。
- 客户端从 Apollo 配置中心服务端获取到应用的最新配置后,会保存在内存中
- 客户端会把从服务端获取到的配置在本地文件系统缓存一份
- 在遇到服务不可用,或网络不通的时候,依然能从本地恢复配置
- 应用程序从 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 三者比较各项得分如下:
对比项 | Apollo | Nacos | Spring Cloud Config |
---|---|---|---|
功能 | 5 | 3 | 1 |
性能 | 4 | 4 | 需单独讨论 |
可用性(可靠性) | 5 | 4 | 3 |
扩展性 | 5 | 3 | 2 |
易用性 | 4 | 3 | 1 |
外部依赖 | 4 | 4 | 2 |
简单综合得分 | 27 | 21 | 9+ |
虽说简单相加的得分有点“简单粗暴”,但也能反映出问题了。(其实如果加权的话,Apollo 也会是遥遥领先的状态)
综上,Apollo 更适合作为部门或者公司级的配置中心。
(最终我们选择的也是 Apollo)
附:游戏 Excel 配置接入 Apollo
在做游戏的时候,经常会有许多游戏内的配置项,比如概率等。
策划或运营同学们已经习惯了使用 Excel 来配置(主要是可以使用 Excel 公式,他们操作起来会比较方便)。
所以针对于该类 Excel 配置,如何在不改变非技术同学的使用习惯的前提下,既提升开发效率又保障数据安全呢?
其实加一个 bridge 就可以解决了。
流程大致如下: