美文网首页微服务中间件docker. k8s
Apollo配置中心原理简介

Apollo配置中心原理简介

作者: 缄默_8421 | 来源:发表于2019-08-26 17:40 被阅读0次

    配置中心发展背景
    随着程序功能的日益复杂,程序的配置日益增多:
    各种功能的开关、参数的配置、服务器的地址……
    对程序配置的期望值也越来越高:
    配置修改后实时生效,灰度发布,分环境、分集群管理配置,完善的权限、审核机制……
    在这样的大环境下,传统的通过配置文件、数据库等方式已经越来越无法满足开发人员对配置管理的需求。

    本篇主要围绕 Apollo分布式配置中心 这一主流组件展开讨论。


    一、Apollo 总体设计

    1.1 Apollo 总体设计图

    Apollo总体设计

    上图简要描述了Apollo的总体设计,自下而上看:

    • Config Service 提供配置的读取、推送等功能,服务对象是Apollo客户端
    • Admin Service 提供配置的修改、发布等功能,服务对象是Apollo Portal(管理界面)
    • Config Service 和 Admin Service 都是多实例、无状态部署,所以需要将自己注册到 Eureka 中并保持心跳
    • 在Eureka之上架了一层 Meta Server 用于封装 Eureka 的服务发现接口
    • Client 通过域名访问 Meta Server 获取 Config Service 服务列表(IP+Port),而后直接通过 IP+Port 访问服务,同时在 Client 侧会做 load balance、错误重试
    • Portal 通过域名访问 Meta Server 获取 Admin Service 服务列表(IP+Port),而后直接通过 IP+Port 访问服务,同时在 Portal 侧会做 load balance、错误重试
    • 为了简化部署,实际上会把 Config Service、Eureka 和 Meta Server 三个逻辑角色部署在同一个JVM进程中

    1.2 各模块简介

    Config Service

    • 提供配置获取接口
    • 提供配置更新推送接口(基于Http long polling)
    • 服务端使用Spring DeferredResult实现异步化,从而大大增加长连接数量
    • 目前使用的tomcat embed默认配置是最多10000个连接(可以调整),使用了4C8G的虚拟机实测可以支撑10000个连接,所以满足需求(一个应用实例只会发起一个长连接)。
    • 接口服务对象为Apollo客户端

    Admin Service

    • 提供配置管理接口
    • 提供配置修改、发布等接口
    • 接口服务对象为Portal

    Meta Server

    • Portal通过域名访问Meta Server获取Admin Service服务列表(IP+Port)
    • Client通过域名访问Meta Server获取Config Service服务列表(IP+Port)
    • Meta Server从Eureka获取Config Service和Admin Service的服务信息,相当于是一个Eureka Client
    • 增设一个Meta Server的角色主要是为了封装服务发现的细节,对Portal和Client而言,永远通过一个Http接口获取Admin Service和Config Service的服务信息,而不需要关心背后实际的服务注册和发现组件
    • Meta Server只是一个逻辑角色,在部署时和Config Service是在一个JVM进程中的,所以IP、端口和Config Service一致

    Eureka

    • 基于Eureka和Spring Cloud Netflix提供服务注册和发现
    • Config Service和Admin Service会向Eureka注册服务,并保持心跳
    • 为了简单起见,目前Eureka在部署时和Config Service是在一个JVM进程中的(通过Spring Cloud Netflix)

    Portal

    • 提供Web界面供用户管理配置
    • 通过Meta Server获取Admin Service服务列表(IP+Port),通过IP+Port访问服务
    • 在Portal侧做load balance、错误重试

    Client

    • Apollo提供的客户端程序,为应用提供配置获取、实时更新等功能
    • 通过Meta Server获取Config Service服务列表(IP+Port),通过IP+Port访问服务
    • 在Client侧做load balance、错误重试

    二、Apollo客户端设计

    Apollo客户端设计

    上图简要描述了Apollo客户端的实现原理:

    1. 客户端和服务端保持了一个长连接,从而能第一时间获得配置更新的推送。(通过Http Long Polling实现)
    2. 客户端还会定时从Apollo配置中心服务端拉取应用的最新配置。
    • 这是一个fallback机制,为了防止推送机制失效导致配置不更新
    • 客户端定时拉取会上报本地版本,所以一般情况下,对于定时拉取的操作,服务端都会返回304 - Not Modified
    • 定时频率默认为每5分钟拉取一次,客户端也可以通过在运行时指定System Property: apollo.refreshInterval来覆盖,单位为分钟。
    1. 客户端从Apollo配置中心服务端获取到应用的最新配置后,会保存在内存中
    2. 客户端会把从服务端获取到的配置在本地文件系统缓存一份
    • 在遇到服务不可用,或网络不通的时候,依然能从本地恢复配置
    1. 应用程序从Apollo客户端获取最新的配置、订阅配置更新通知

    三、配置更新推送实现

    3.1 配置发送后的实时推送设计

    配置发布后的实时推送设计

    上图简要描述了配置发布的大致过程:

    1. 用户在Portal操作配置发布
    2. Portal调用Admin Service的接口操作发布
    3. Admin Service发布配置后,发送ReleaseMessage给各个Config Service
    4. Config Service收到ReleaseMessage后,通知对应的客户端

    之前提到了Apollo客户端和服务端保持了一个长连接,从而能第一时间获得配置更新的推送。长连接实际上是通过Http Long Polling实现的,具体而言:

    • 客户端发起一个Http请求到服务端
    • 服务端会保持住这个连接60秒
    • 如果在60秒内有客户端关心的配置变化,被保持住的客户端请求会立即返回,并告知客户端有配置变化的namespace信息,客户端会据此拉取对应namespace的最新配置
    • 如果在60秒内没有客户端关心的配置变化,那么会返回Http状态码304给客户端
    • 客户端在收到服务端请求后会立即重新发起连接,回到第一步

    考虑到会有数万客户端向服务端发起长连,在服务端使用了async servlet(Spring DeferredResult)来服务Http Long Polling请求。

    注:DeferredResult可以允许容器线程快速释放以便接受更多的请求提升吞吐量,让真正的业务逻辑在其他的工作线程中完成。

    3.2 发送ReleaseMessage的实现方式

    Admin Service在配置发布后,需要通知所有的Config Service有配置发布,从而Config Service可以通知对应的客户端来拉取最新的配置。

    从概念上来看,这是一个典型的消息使用场景,Admin Service作为producer发出消息,各个Config Service作为consumer消费消息。通过一个消息组件(Message Queue)就能很好的实现Admin Service和Config Service的解耦。

    在实现上,考虑到Apollo的实际使用场景,以及为了尽可能减少外部依赖,Apollo没有采用外部的消息中间件,而是通过数据库实现了一个简单的消息队列。

    实现方式如下:

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

    示意图如下:

    发送ReleaseMessage的实现方式

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

    上一节中简要描述了NotificationControllerV2是如何得知有配置发布的,那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的最新配置。

    四、可用性考虑

    配置中心作为基础服务,可用性要求非常高,下面的表格描述了不同场景下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自动切换到其它存活的数据中心
    数据库宕机 客户端无影响,Portal无法更新配置 Config Service开启配置缓存后,对配置的读取不受数据库宕机影响

    以上内容参考自Apollo GitHub,更多详细内容请参照官方介绍。

    相关文章

      网友评论

        本文标题:Apollo配置中心原理简介

        本文链接:https://www.haomeiwen.com/subject/siudectx.html