Apollo源码解析看一文就够
对于配置中心我们先抛出问号三连,什么是配置中心?为什么要用配置中心?配置中心怎么用?
笔者说说自己理解的配置中心,个人观点的十六字
消息存储 消息推送 环境隔离 灰度发布
今天我们先来看Apollo配置中心怎么用,小伙伴可能会说,这不是很简单嘛,no,我们同时要来揭开配置保存的实现原理。
apollo配置都是通过表来保存,那么我们来一步一步揭开模型关系。
看笔者这篇文章的同时,或者你已经熟悉Apollo基本的操作,比如创建集群、创建Namespace、创建灰度发布等。如果不熟悉,可以参考小编上篇文章自己构建Apollo调试环境,参考官方 Apollo使用指南。
创建项目
为了小伙伴能看的清楚,笔者特意把表数据全部清理了,包括原始项目,项目id是100004458
那么我们先创建一个项目,这个项目可以匹配我们自己的服务,比如platform-base-service
这里解答两个问题,应用负责人是在管理员工具-用户管理中配置,对应表是ApolloPortalDB.Users
部门是可选项,配置的是ApolloPortalDB.ServerConfig中 organizations对应value,可以看到笔者这里配置的造火箭的部门和拧螺丝的部门
当然可以在系统工具--管理员参数 配置key=organizations和value=[{"orgId":"TEST1","orgName":"造火箭部门"},{"orgId":"TEST2","orgName":"拧螺丝部门"}]
这里我们也可以扩展一点,
到此我们项目已经创建完成。
环境列表
这个看过笔者写的Apollo源码搭建调试看一文就够,应该知道,笔者特意强调了只配置dev环境,也就是ApolloPortalDB.ServerConfig中Key=apollo.portal.envs和Value=dev
这里再强调一次ApolloPortalDB所有环境只需要部署一个即可,而ApolloConfigDB需要在每个环境部署一套,如dev、fat、uat和pro分别部署4套ApolloConfigDB。
每个环境下ApolloConfigDB 配置独立。这里也是我们说到的配置中心需要实现的环境隔离。
如果需要配置多环境,按照工程源码下../apollo/scripts/apollo-on-kubernetes/db下对应环境创建自己的ApolloConfigDB数据度,然后配置apollo.portal.envs,当然也可以自定义环境。
添加集群 Cluster
集群使用场景,类似异地多活,同一个项目不用城市获取的配置项是不同的。
- 通过添加集群,可以使同一份程序在不同的集群(如不同的数据中心)使用不同的配置
- 如果不同集群使用一样的配置,则没有必要创建集群
表结构比较简单,ApolloConfigDB.Cluster表中
添加NameSpaces
Apollo在创建项目的时候,都会默认创建一个“application”的Namespace。
对于概念不够理解,可以看看官方提供的解释 Apollo核心概念之“Namespace”。
我们来看看表数据流向,创建App也是同种方式,数据都是从portal Service到Admin Service。
下面我们简单看下ApolloConfigDB中数据模型关系。
总结如下:
1、创建App后,会自动创建默认的Namespace,默认的Cluster,即同时App、Cluster、AppNamespace、Namespace数据。
2、创建Cluster后,Namespace就是关联AppNamespace和Cluster,即为每个 AppNamespace 创建 不同集群的Namespace。
借用官方作者的话,如果把appnamespace比作class的话,namespace就可以比作是实例化的对象,它在不同的环境,不同的集群都有实例。
这里笔者也有一个疑惑,创建namespace会创建所有环境、所有集群,具体后面可以跟踪下 https://github.com/ctripcorp/apollo/issues/2188
新增配置
这个Item ,配置项,是 Namespace 下最小颗粒度的单位。在 Namespace 分成五种类型:properties yml yaml json xml
数据存储在ApolloConfigDB.Item
发布配置
这里也是我们说到的配置中心需要实现的消息推送。
这里也就是全文的重点
服务端实时推送如何设计
Config Service 通知客户端的实现方式
抛出几个问题:
1、客户端收到通知消息后,从返回的结果中获取到配置变化的 namespace 后,会立即请求 Config Service 获取该 namespace 的最新配置,问题就是为什么不在通知消息中带过去message,而需要重新获取?
2、假设一个公共 Namespace 有10W台机器使用,该公共 Namespace 发布时直接下发配置更新消息的话,就会导致这 10W 台机器同时来请求配置,对Config Service的压力也会特别大如何处理?
实例列表
实例( Instance ),实际就是 Apollo 的客户端
我们启动服务 SpringBootSampleApplication,即启动了一个Apollo客户端,可以查询到实例列表。
对应我们的数据库即ApolloConfigDB.Instance
灰度发布
这里也是我们说到的配置中心需要实现的灰度发布。
我们可以理解灰度和分支等价,
- 创建 Namespace 灰度时:
- 会创建子 Cluster ,指向父 Cluster 。
- 会创建子 Namespace ,关联子 Namespace 。实际上,子 Namespace 和 父 Namespace 无任何数据字段上的关联。
- 向子 Namespace 添加 Item 时,该 Item 指向子 Namespace 。虽然,代码实现和父 Namespace 是一模一样的。
灰度发布模型
灰度 Namespace 发布 Release 。灰度 Namespace 会自动继承 父 Namespace 已经发布的配置。若有相同的配置项,使用 子 Namespace 的。配置处理的逻辑上,和关联 Namespace 是一致的。
灰度全量发布
数据库对应模型
前面我们已经讲了每个流程操作的数据库和关系,这里我们总结下。
创建项目、集群、namespace数据关系模型
添加配置项数据关系
发布配置数据关系
上面操作都设计到日志审计表ApolloConfigDB.Audit,只是图这里没有表示出来。
我们这里只聊聊实现原理,具体的操作可以参考官方灰度发布指南。如果有任何问题可以留言一起讨论。