如何设计一个分布式配置中心?

简介: 这篇文章介绍了分布式配置中心的概念、实现原理及其在实际应用中的重要性。首先通过一个面试场景引出配置中心的设计问题,接着详细解释了为什么需要分布式配置中心,尤其是在分布式系统中统一管理配置文件的必要性。文章重点分析了Apollo这一开源配置管理中心的工作原理,包括其基础模型、架构模块以及配置发布后实时生效的设计。此外,还介绍了客户端与服务端之间的交互机制,如长轮询(Http Long Polling)和定时拉取配置的fallback机制。最后,结合实际工作经验,分享了配置中心在解决多台服务器配置同步问题上的优势,帮助读者更好地理解其应用场景和价值。

这是小卷对分布式系统架构学习的第7篇文章,前面已经讲了很多理论知识,今天结合具体的中间件来讲分布式配置中心

1.面试官提问

面试官:假设你是公司的基础架构部门,现在需要设计内部的配置中心中间件,你要怎么设计?

我:设计客户端和服务端,客户端集成到业务项目中,项目启动时从服务端pull配置加载到本地,并且定时check服务端和本地配置是否一致,服务端如有更新,再pull到本地

面试官:那如果有几万台服务器,都是这样定时去check,服务端压力岂不是很大,要怎么解决呢?

我:那改成用服务端push的方式???

面试官:......

面试官:那今天就到这里吧,你回去等通知吧......

2.为什么需要分布式配置中心

不了解底层原理的小卷只好回家后苦心专研分布式配置中心的原理,一定要弄清楚底层逻辑,下次要吊打面试官。

先来简单理解为什么需要配置中心?

我们开发的服务都是单体架构时,配置文件就和代码放在一起,如springboot的application.yml文件,对配置的修改只需要修改这一个文件就行。到分布式服务中,一个服务会有多台机器,不可能每个机器都单独修改配置文件,然后重新部署的。

这就要用到配置中心了,以nacos为例,下图是配置修改时和服务器间的操作:

配置中心1.png

3.开源框架

这里列举4种分布式配置中心的中间件,我们直接从一个中间件的原理来学习配置中心。

工作这么多年,应该得了解一些开源组件,大大小小的都行:

1、Apollo

2016年5月,携程开源的配置管理中心,具备规范的权限、流程治理等特性。

GitHub地址:https://github.com/apolloconfig/apollo

2、spring cloud config

2014年9月开源,Spring Cloud 生态组件,可以和Spring Cloud体系无缝整合。

3、Nacos

2018年6月,阿里开源的配置中心,也可以做DNS和RPC的服务发现。

4、Diamond

Diamond 出自淘宝,开源地址 【https://github.com/takeseem/diamond】 ,阿里集团内部的配置中心仍然用的diamond,只是开源版本不再维护

面试时可能会问到为什么选择Apollo作为配置中心?不用其他的配置中心呢?

很多人用的时候就是看别人也这么用,或者大家都这么用,就选择了这个中间件。这里如果遇到了的话,就可以提到开源社区的活跃性,因为Apollo 的社区生态活跃,且使用的公司特别多,常见的坑基本都被踩完了,所以选用Apollo。

4. Apollo工作原理

4.1基础模型

Apollo文档:Apollo配置中心设计,工作原理比较简单:

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

配置中心2.png

4.2架构模块

配置中心3.png

解释下各个模块的功能:

  • Config Service提供配置的读取、推送等功能,服务对象是Apollo客户端
  • Admin Service提供配置的修改、发布功能,服务对象是Apollo Portal(管理界面)
  • Config Service和Admin Service都需要注册到Eureka并保持心跳;
  • Meta Server是对Eureka做了一层封装,封装的是服务发现接口;
  • Client通过域名访问Meta Server获取Config Service服务列表,即获取IP+端口,然后通过IP+端口访问服务,同时Client端自己做负载均衡,错误重试;
  • Portal访问Meta Server获取Admin Service服务列表,也是获取IP+端口,然后访问服务,Portal侧也做负载均衡;

5. 使用Apollo

官方有提供快速部署使用文档:Quick Start

具体操作步骤可以自行查看官方文档,这里我们主要通过简单使用Apollo来理解配置中心。部署完成后,登陆Apollo的管理界面,然后创建个应用,发布后再创建个配置,接着再次发布,如下图:

配置中心4.png

这里我是在本地启动的,访问http://localhost:8080/可以查看已注册的实例

配置中心5.png

然后创建一个Springboot应用连接到Apollo配置中心,这里不写那么具体了,可以自行参考官方的Java客户端使用指南

Mac电脑需先在本地的/opt/settings/server.properties文件中配置环境env=DEV,然后在application.properties文件中配置Apollo相关的内容如下:

# 接入Apollo配置
app.id=multi_function
apollo.meta=http://localhost:8080
# Apollo本地缓存路径
apollo.cache-dir=/Users/longbig/log
# 指定Apollo配置文件的环境
env=DEV
# 配置访问秘钥
apollo.accesskey.secret=4c61a00512ad4cc09ef8a0e1ee672d89
apollo.bootstrap.enabled=true

为了测试客户端接收到配置中心配置变更的事件,我们参考官方文档的代码写个监听器的代码如下:

@Configuration
@Slf4j
public class ApolloConfig {
   
    @Bean
    public void init() {
   
        Config config = ConfigService.getAppConfig();
        config.addChangeListener(new ConfigChangeListener() {
   
            @Override
            public void onChange(ConfigChangeEvent changeEvent) {
   
                log.info("Changes for namespace " + changeEvent.getNamespace());
                for (String key : changeEvent.changedKeys()) {
   
                    ConfigChange change = changeEvent.getChange(key);
                    log.info(String.format("Found change - key: %s, oldValue: %s, newValue: %s, changeType: %s", change.getPropertyName(), change.getOldValue(), change.getNewValue(), change.getChangeType()));
                }
            }
        });
    }
}

最后测试验证,在管理界面增加一个配置,然后对配置修改发布,可以看到客户端已经接收到配置变更的事件了,并且打印出日志信息了

配置中心6.png

配置中心7.png

6. 配置发布后实时生效设计

从上面简单使用中可以看到,配置发布后实时推送到客户端。下面我们简要看一下这块是怎么设计实现的

配置中心8.png

配置发布的大致过程:

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

6.1发送ReleaseMessage的实现方式

从上图看,应该是用MQ的方式比较合适,但是Apollo没有用外部消息中间件,而是通过数据库来实现这个简单的消息队列的。具体如下:

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

配置中心9.png

我们查看数据库的ReleaseMessageReleaseHistory表,可以查看到当前消息和历史消息

配置中心10.png

配置中心11.png

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

这里能解释说明开头的面试题,客户端更新配置是Pull还是Push的方式?

具体实现方式如下:

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

7. 客户端的工作原理

配置中心12.png

接着讲讲Apollo客户端的工作原理:

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

8.题外话

之前在第一家公司工作过程中,遇到个问题是:对应用某个配置的变更如何通知到生产环境的所有机器?

当时的场景是前端发起HTTP请求,调用后端接口修改配置,因为负载均衡的缘故,请求只会打到1台机器上,只有1台机器的内存配置被更新,其他机器的内存配置还是旧的,当时小组一起讨论解决办法,可能认知有限,只想到MQ等等方式,没想到配置中心的原理

后来去了阿里之后,参与过写配置中心配置变更监听器,实现了全量机器的内存配置更新功能

现在回想起来,当时没解决的原因还是认知不够,现在学了配置中心的原理又想到了这件事,分享给大家学习参考~

相信通过学习Apollo配置中心的原理,你在面试过程中如果遇到开头的题目,应该也能说上一二了。

相关文章
|
2月前
|
数据库
如何在Seata框架中配置分布式事务的隔离级别?
总的来说,配置分布式事务的隔离级别是实现分布式事务管理的重要环节之一,需要认真对待和仔细调整,以满足业务的需求和性能要求。你还可以进一步深入研究和实践 Seata 框架的配置和使用,以更好地应对各种分布式事务场景的挑战。
49 6
|
3月前
|
分布式计算 Hadoop
Hadoop-27 ZooKeeper集群 集群配置启动 3台云服务器 myid集群 zoo.cfg多节点配置 分布式协调框架 Leader Follower Observer
Hadoop-27 ZooKeeper集群 集群配置启动 3台云服务器 myid集群 zoo.cfg多节点配置 分布式协调框架 Leader Follower Observer
64 1
|
3月前
|
存储 SQL 消息中间件
Hadoop-26 ZooKeeper集群 3台云服务器 基础概念简介与环境的配置使用 架构组成 分布式协调框架 Leader Follower Observer
Hadoop-26 ZooKeeper集群 3台云服务器 基础概念简介与环境的配置使用 架构组成 分布式协调框架 Leader Follower Observer
58 0
|
5月前
|
UED 存储 数据管理
深度解析 Uno Platform 离线状态处理技巧:从网络检测到本地存储同步,全方位提升跨平台应用在无网环境下的用户体验与数据管理策略
【8月更文挑战第31天】处理离线状态下的用户体验是现代应用开发的关键。本文通过在线笔记应用案例,介绍如何使用 Uno Platform 优雅地应对离线状态。首先,利用 `NetworkInformation` 类检测网络状态;其次,使用 SQLite 实现离线存储;然后,在网络恢复时同步数据;最后,通过 UI 反馈提升用户体验。
120 0
|
5月前
|
机器学习/深度学习 TensorFlow 数据处理
分布式训练在TensorFlow中的全面应用指南:掌握多机多卡配置与实践技巧,让大规模数据集训练变得轻而易举,大幅提升模型训练效率与性能
【8月更文挑战第31天】本文详细介绍了如何在Tensorflow中实现多机多卡的分布式训练,涵盖环境配置、模型定义、数据处理及训练执行等关键环节。通过具体示例代码,展示了使用`MultiWorkerMirroredStrategy`进行分布式训练的过程,帮助读者更好地应对大规模数据集与复杂模型带来的挑战,提升训练效率。
127 0
|
5月前
|
Java 测试技术 Spring
分布式之配置中心
分布式之配置中心
62 1
|
7月前
|
机器学习/深度学习 人工智能 自然语言处理
人工智能平台PAI产品使用合集之如何配置cluster系统自动生成分布式参数
阿里云人工智能平台PAI是一个功能强大、易于使用的AI开发平台,旨在降低AI开发门槛,加速创新,助力企业和开发者高效构建、部署和管理人工智能应用。其中包含了一系列相互协同的产品与服务,共同构成一个完整的人工智能开发与应用生态系统。以下是对PAI产品使用合集的概述,涵盖数据处理、模型开发、训练加速、模型部署及管理等多个环节。
|
8月前
|
Cloud Native Java 开发工具
云原生 阿里云分布式文件系统 对象存储OSS 服务配置
【1月更文挑战第8天】云原生 阿里云分布式文件系统 对象存储OSS 服务配置
|
7月前
|
网络安全 数据安全/隐私保护
分布式系统详解--框架(Hadoop-Ssh免密登陆配置)
分布式系统详解--框架(Hadoop-Ssh免密登陆配置)
75 0
|
8月前
|
安全
考虑极端天气线路脆弱性的配电网分布式电源和储能优化配置模型
考虑极端天气线路脆弱性的配电网分布式电源和储能优化配置模型