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,只是图这里没有表示出来。

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

  • 相关阅读:
    dotnet 控制台读写 Sqlite 提示 no such table 找不到文件
    dotnet 控制台读写 Sqlite 提示 no such table 找不到文件
    dotnet 控制台 Hangfire 后台定时任务
    dotnet 控制台 Hangfire 后台定时任务
    dotnet 获取指定进程的输入命令行
    dotnet 获取指定进程的输入命令行
    PHP sqrt() 函数
    PHP sinh() 函数
    PHP sin() 函数
    PHP round() 函数
  • 原文地址:https://www.cnblogs.com/lewis09/p/10822020.html
Copyright © 2011-2022 走看看