分布式配置中心 - 携程 Apollo(阿波罗)

看到 InfoQ 的一篇文章:GitHub 9K Star!Apollo作者手把手教你微服务配置中心之道

关于为什么需要配置中心,请参见:Spring Cloud 学习笔记 - No.3 分布式配置 Config

携程 Apollo(阿波罗)Github 主页:https://github.com/ctripcorp/apollo

Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。

Apollo 的基础模型

  1. 用户在配置中心对配置进行修改并发布
  2. 配置中心通知 Apollo 客户端有配置更新
  3. Apollo 客户端从配置中心拉取最新的配置、更新本地配置并通知到应用

服务端高可用

  • 首先最下面是一个 DB,我们的配置是放在 DB 里的,然后在 DB 之上有两个服务:Config Service 和 Admin Service;
  • Config Service 提供配置的读取、推送等功能,服务对象是 Apollo 客户端;
  • Admin Service 提供配置的修改、发布等功能,服务对象是 Apollo Portal(管理界面);
  • Config Service 和 Admin Service 都是多实例、无状态部署,所以需要将自己注册到 Eureka 中并保持心跳;
  • 在 Eureka 之上我们架了一层 Meta Server 用于封装 Eureka 的服务发现接口,主要是为了让客户端和 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. 客户端和服务端保持了一个长连接,从而能第一时间获得配置更新的推送。(通过 Http Long Polling 实现);
  2. 客户端还会定时从 Apollo 配置中心服务端拉取应用的最新配置;这是一个 fallback 机制,为了防止推送机制失效导致配置不更新;
    客户端定时拉取会上报本地版本,所以一般情况下,对于定时拉取的操作,服务端都会返回 304 - Not Modified。
  3. 客户端从 Apollo 配置中心服务端获取到应用的最新配置后,会保存在内存中,所以我们的应用程序来获取配置的时候其实始终是从内存中获取的;
  4. 客户端还会把从服务端获取到的配置在本地文件系统缓存一份;
    这主要是为了容灾,假设应用程序重启的时候,恰好远端服务全挂了,或者网络有故障,应用程序依然能从本地恢复配置。

通过这种推拉结合的机制,以及内存和本地文件双缓存的方式,有效地保证了客户端的可用性。

发送 ReleaseMessage 的实现方式

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

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

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

实现方式如下:

  1. Admin Service 在配置发布后会往 ReleaseMessage 表插入一条消息记录,消息内容就是配置发布的 AppId+Cluster+Namespace
  2. Config Service 有一个线程会每秒扫描一次 ReleaseMessage 表,看看是否有新的消息记录
  3. Config Service 如果发现有新的消息记录,解析得到配置发布的 AppId+Cluster+Namespace 后,通知到对应的客户端

分布式配置中心如何让微服务更『智能』?

发布开关
有些新功能依赖于其它系统的新接口,而其它系统的发布周期未必和自己的系统一致,可以加个发布开关,默认把该功能关闭,等依赖系统上线后再打开;
有些新功能有较大风险,可以加个发布开关,上线后一旦有问题可以迅速关闭。

实验开关
实验开关通常用于对比测试或功能测试,比如:A/B 测试和QA 测试。

运维开关
运维开关通常用于提升系统稳定性,比如:

  • 大促前可以把一些非关键功能关闭来提升系统容量;
  • 当系统出现问题时可以关闭非关键功能来保证核心功能正常工作。

限流
黑白名单
一般的做法是在 RPC 框架层添加校验逻辑,结合配置中心的动态推送能力来实现动态调整黑白名单配置。

数据库迁移
动态日志级别
动态网关路由
动态数据源

关于 Apollo 的使用

服务端基于Spring Boot和Spring Cloud开发,打包后可以直接运行,不需要额外安装Tomcat等应用容器。
Java客户端不依赖任何框架,能够运行于所有Java运行时环境,同时对Spring/Spring Boot环境也有较好的支持。

本地快速部署请参见Quick Start

演示环境(Demo):

关于 Spring 如何集成 Apollo,请参见:Java客户端使用指南#32-spring整合方式

推荐阅读更多精彩内容