分布式-Apollo配置中心高可用
Apollo配置中心,有Portal、Admin Service、Config Service三个服务,其中Admin Service、Config Service是多实例的,且客户端发现这些节点(IP+Port)清单是通过Eureka获取的
高可用架构
如下,IDC1和IDC2俩个机房
- 每个机房内部署Portal、Admin Service、Config Service,单机房内,Portal访问同机房Admin Service进行查询、修改、发布操作,服务实例从同机房Config Service获取配置
- 数据库Portal DB、Config DB俩个库,数据库部署双机房高可用架构
Admin Service和Config Service是多节点的,Portal和业务服务实例是通过Meta Server(Eureka)获取Admin Service、Config Service节点列表的,Meta Server是封装的Eureka,底层使用开源的Eureka
- Config Service和Admin Service向Eureka注册服务,并保持心跳
- 一般情况下,为简单起见,目前Eureka在部署时和Config Service是在一个JVM进程中的
Meta Server
- Portal通过域名访问Meta Server获取Admin Service服务列表(IP+Port)
- 业务服务实例通过域名访问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一致
Admin Service
- 提供配置管理接口
- 提供配置修改、发布等接口
- 接口服务对象为Portal
Config Service
- 提供配置更新推送接口(基于Http long polling)
- 服务端使用Spring DeferredResult实现异步化,从而大大增加长连接数量
- 目前使用的tomcat embed默认配置是最多10000个连接(可以调整),使用了4C8G的虚拟机实测可以支撑10000个连接,所以满足需求(一个应用实例只会发起一个长连接)。
- 接口服务对象为Apollo客户端
配置发布
- 用户在Portal操作配置发布
- Portal调用Admin Service的接口操作发布
- Admin Service发布配置后,发送ReleaseMessage给各个Config Service
- Config Service收到ReleaseMessage后,通知对应的客户端
在实现上,考虑到Apollo的实际使用场景,以及为了尽可能减少外部依赖,我们没有采用外部的消息中间件,而是通过数据库实现了一个简单的消息队列。
实现方式如下:
- Admin Service在配置发布后会往ReleaseMessage表插入一条消息记录,消息内容就是配置发布的AppId+Cluster+Namespace,参见DatabaseMessageSender
- Config Service有一个线程会每秒扫描一次ReleaseMessage表,看看是否有新的消息记录,参见ReleaseMessageScanner
- Config Service如果发现有新的消息记录,那么就会通知到所有的消息监听器(ReleaseMessageListener),如NotificationControllerV2,消息监听器的注册过程参见ConfigServiceAutoConfiguration
- NotificationControllerV2得到配置发布的AppId+Cluster+Namespace后,会通知对应的客户端
Config Service通知客户端的实现方式:
- 客户端会发起一个Http请求到Config Service的
notifications/v2
接口,也就是NotificationControllerV2,参见RemoteConfigLongPollService - NotificationControllerV2不会立即返回结果,而是通过Spring DeferredResult把请求挂起
- 如果在60秒内没有该客户端关心的配置发布,那么会返回Http状态码304给客户端
- 如果有该客户端关心的配置发布,NotificationControllerV2会调用DeferredResult的setResult方法,传入有配置变化的namespace信息,同时该请求会立即返回。客户端从返回的结果中获取到配置变化的namespace后,会立即请求Config Service获取该namespace的最新配置。
如何实现高可用的
- Apollo服务无状态多节点、可降级
- 依赖的数据库高可用
场景 | 影响 | 降级 | 原因 |
---|---|---|---|
某台Config Service下线 | 无影响 | Config Service无状态,客户端重连其它Config Service | |
所有Config Service下线 | 客户端无法读取最新配置,Portal无影响 | 客户端重启时,可以读取本地缓存配置文件。如果是新扩容的机器,可以从其它机器上获取已缓存的配置文件,具体信息可以参考Java客户端使用指南 - 1.2.3 本地缓存路径 | |
某台Admin Service下线 | 无影响 | Admin Service无状态,Portal重连其它Admin Service | |
所有Admin Service下线 | 客户端无影响,Portal无法更新配置 | ||
某台Portal下线 | 无影响 | Portal域名通过SLB绑定多台服务器,重试后指向可用的服务器 | |
全部Portal下线 | 客户端无影响,Portal无法更新配置 | ||
某个数据中心下线 | 无影响 | 多数据中心部署,数据完全同步,Meta Server/Portal域名通过SLB自动切换到其它存活的数据中心 | |
数据库宕机 | 客户端无影响,Portal无法更新配置 | Config Service开启配置缓存后,对配置的读取不受数据库宕机影响 |
配置中心的考虑点
- 功能:配置中心需要具备丰富的功能,如支持多种配置方式、权限管理、版本控制等。
- 性能:配置中心需要能够快速地响应应用程序的请求,提供高效的性能。
- 可用性:配置中心需要具备高可用性,保证在系统出现问题时能够快速恢复。
- 易用性:配置中心需要具备易用性,方便用户进行操作和管理。
- 生态支持:配置中心需要具备良好的生态支持,方便与其他组件进行集成和交互。
Apollo拥有完整的功能全面、性能优秀,但是部署较为复杂,需要多个模块同时工作,可以选择Apollo作为配置中心;如果项目需要在大规模场景下使用,且要求部署简单、性能优秀和功能丰富,可以选择Nacos作为配置中心。