zoukankan      html  css  js  c++  java
  • 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

    发布配置

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

    这里也就是全文的重点

    服务端实时推送如何设计

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

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

     

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

    抛出几个问题:
    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,只是图这里没有表示出来。

    我们这里只聊聊实现原理,具体的操作可以参考官方灰度发布指南。如果有任何问题可以留言一起讨论。

  • 相关阅读:
    js中如何在不影响既有事件监听的前提下新增监听器
    史上最走心webpack4.0中级教程——配置之外你应该知道的事
    webpack4.0各个击破(10)—— Integration篇
    webpack4.0各个击破(9)—— karma篇
    webpack4.0各个击破(8)—— tapable篇
    webpack4.0各个击破(7)—— plugin篇
    MYSQL的安装
    数据库的分类
    python接口调用把执行结果追加到测试用例中
    python分布式接口,参数化实战二
  • 原文地址:https://www.cnblogs.com/lewis09/p/10822020.html
Copyright © 2011-2022 走看看