这是小卷对分布式系统架构学习的第7篇文章,前面已经讲了很多理论知识,今天结合具体的中间件来讲分布式配置中心
面试官:假设你是公司的基础架构部门,现在需要设计内部的配置中心中间件,你要怎么设计?
我:设计客户端和服务端,客户端集成到业务项目中,项目启动时从服务端pull配置加载到本地,并且定时check服务端和本地配置是否一致,服务端如有更新,再pull到本地
面试官:那如果有几万台服务器,都是这样定时去check,服务端压力岂不是很大,要怎么解决呢?
我:那改成用服务端push的方式???
面试官:......
面试官:那今天就到这里吧,你回去等通知吧......
不了解底层原理的小卷只好回家后苦心专研分布式配置中心的原理,一定要弄清楚底层逻辑,下次要吊打面试官。
先来简单理解为什么需要配置中心?
我们开发的服务都是单体架构时,配置文件就和代码放在一起,如springboot的application.yml文件,对配置的修改只需要修改这一个文件就行。到分布式服务中,一个服务会有多台机器,不可能每个机器都单独修改配置文件,然后重新部署的。
这就要用到配置中心了,以nacos为例,下图是配置修改时和服务器间的操作:
这里列举4种分布式配置中心的中间件,我们直接从一个中间件的原理来学习配置中心。
工作这么多年,应该得了解一些开源组件,大大小小的都行:
1、Apollo
2016年5月,携程开源的配置管理中心,具备规范的权限、流程治理等特性。
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。
Apollo文档:Apollo配置中心设计,工作原理比较简单:
解释下各个模块的功能:
官方有提供快速部署使用文档:Quick Start
具体操作步骤可以自行查看官方文档,这里我们主要通过简单使用Apollo来理解配置中心。部署完成后,登陆Apollo的管理界面,然后创建个应用,发布后再创建个配置,接着再次发布,如下图:
这里我是在本地启动的,访问http://localhost:8080/可以查看已注册的实例
然后创建一个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()));
}
}
});
}
}
最后测试验证,在管理界面增加一个配置,然后对配置修改发布,可以看到客户端已经接收到配置变更的事件了,并且打印出日志信息了
从上面简单使用中可以看到,配置发布后实时推送到客户端。下面我们简要看一下这块是怎么设计实现的
配置发布的大致过程:
从上图看,应该是用MQ的方式比较合适,但是Apollo没有用外部消息中间件,而是通过数据库来实现这个简单的消息队列的。具体如下:
我们查看数据库的ReleaseMessage
和ReleaseHistory
表,可以查看到当前消息和历史消息
这里能解释说明开头的面试题,客户端更新配置是Pull还是Push的方式?
具体实现方式如下:
notifications/v2
接口,也就是NotificationControllerV2接着讲讲Apollo客户端的工作原理:
apollo.refreshInterval
来覆盖,单位为分钟。之前在第一家公司工作过程中,遇到个问题是:对应用某个配置的变更如何通知到生产环境的所有机器?
当时的场景是前端发起HTTP请求,调用后端接口修改配置,因为负载均衡的缘故,请求只会打到1台机器上,只有1台机器的内存配置被更新,其他机器的内存配置还是旧的,当时小组一起讨论解决办法,可能认知有限,只想到MQ等等方式,没想到配置中心的原理
后来去了阿里之后,参与过写配置中心配置变更监听器,实现了全量机器的内存配置更新功能
现在回想起来,当时没解决的原因还是认知不够,现在学了配置中心的原理又想到了这件事,分享给大家学习参考~
相信通过学习Apollo配置中心的原理,你在面试过程中如果遇到开头的题目,应该也能说上一二了。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。