Apollo源码解析看一文就够 Apollo源码搭建调试看一文就够

对于配置中心咱们先抛出问号三连,什么是配置中心?为何要用配置中心?配置中心怎么用?html

笔者说说本身理解的配置中心,我的观点的十六字java

消息存储  消息推送  环境隔离  灰度发布git

今天咱们先来看Apollo配置中心怎么用,小伙伴可能会说,这不是很简单嘛,no,咱们同时要来揭开配置保存的实现原理。github

apollo配置都是经过表来保存,那么咱们来一步一步揭开模型关系。web

看笔者这篇文章的同时,或者你已经熟悉Apollo基本的操做,好比建立集群、建立Namespace、建立灰度发布等。若是不熟悉,能够参考小编上篇文章本身构建Apollo调试环境,参考官方 Apollo使用指南spring

 

建立项目

为了小伙伴能看的清楚,笔者特地把表数据所有清理了,包括原始项目,项目id是100004458数据库

那么咱们先建立一个项目,这个项目能够匹配咱们本身的服务,好比platform-base-servicejson

这里解答两个问题,应用负责人是在管理员工具-用户管理中配置,对应表是ApolloPortalDB.Usersapi

                          部门是可选项,配置的是ApolloPortalDB.ServerConfig中 organizations对应value,能够看到笔者这里配置的造火箭的部门和拧螺丝的部门app

固然能够在系统工具--管理员参数 配置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中数据模型关系。

总结以下:

一、建立App后,会自动建立默认的Namespace,默认的Cluster,即同时App、Cluster、AppNamespace、Namespace数据。
二、建立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

发布配置

这里也是咱们说到的配置中心须要实现的消息推送

这里也就是全文的重点

服务端实时推送如何设计

 

重点来看看 ReleaseMessage实现方式
一、Admin Service在配置发布后会往ReleaseMessage表插入一条消息记录,消息内容就是配置发布的AppId+Cluster+Namespace,参见 DatabaseMessageSender
二、Apollo.ReleaseMessageScanner线程会每秒扫描一次ReleaseMessage表,看看是否有新的消息记录,参见 ReleaseMessageScanner
三、Config Service若是发现有新的消息记录,那么就会通知到全部的消息监听器( ReleaseMessageListener),如 NotificationControllerV2,消息监听器的注册过程参见 ConfigServiceAutoConfiguration
四、NotificationControllerV2获得配置发布的AppId+Cluster+Namespace后,会通知对应的客户端

Config Service 通知客户端的实现方式

 

上面有提到其实就是NotificationControllerV2在得知有配置发布后通知客户端,实现以下
一、客户端会发起一个Http请求到Config Service的notifications/v2接口,也就是 NotificationControllerV2,参见 RemoteConfigLongPollService
二、NotificationControllerV2不会当即返回结果,而是经过 Spring DeferredResult把请求挂起
三、若是在60秒内没有该客户端关心的配置发布,那么会返回Http状态码304给客户端
四、若是有该客户端关心的配置发布,NotificationControllerV2会调用DeferredResult的 setResult方法,传入有配置变化的namespace信息,同时该请求会当即返回。客户端从返回的结果中获取到配置变化的namespace后,会当即请求Config Service获取该namespace的最新配置。

抛出几个问题:
一、客户端收到通知消息后,从返回的结果中获取到配置变化的 namespace 后,会当即请求 Config Service 获取该 namespace 的最新配置,问题就是为何不在通知消息中带过去message,而须要从新获取?

二、假设一个公共 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,只是图这里没有表示出来。

 

咱们这里只聊聊实现原理,具体的操做能够参考官方灰度发布指南。若是有任何问题能够留言一块儿讨论。

相关文章
相关标签/搜索