当前位置: 首页 > 后端技术 > Java

分布式配置系统Apollo如何实时更新配置的

时间:2023-04-01 15:07:08 Java

分布式配置系统Apollo如何实时更新配置?什么,各种逻辑开关,一旦修改了这些配置,需要重启项目才能使修改生效。随着各种微服务的诞生,服务的拆分也越来越细。可能涉及到几千个或者上百个服务,服务基本上都是集群部署的。修改每个项目的配置然后重启显然是行不通的。的。于是分布式配置中心诞生了。现在有相当多的开源分布式配置中心。例如:有很多开源的分布式配置中心,spring-cloud/spring-cloud-config,taobao/diamond,Baidu/disconf,Ctrip/apollo,netflix/archaius,Qconf,XDiamond,nacos等,我们是不是好奇配置中心如何实时更新并通知客户端?这也是面试中经常被问到的问题。下面以apollo为例,分析一下它是如何实现的。为什么选择Apollo分析色谱柱?因为现在公司都在用它作为配置中心。Apollo虽然是携程开源的,但是携程内部并没有使用。Apollo简介要了解一个东西,首先要会用它。它的使用基本上很简单。虽然使用起来简单方便,但其设计还是相当复杂。看看它官网提供的架构图是不是挺复杂的。通过上面的架构图,我们可以看到模块ConfigService、AdminService、Client、Portal、MetaServer、Eureka。主要是前四个模块,MetaServer和Eureka。这两个模块只是Apollo自身需要的辅助模块。我们暂时不需要关注它。ConfigService提供配置获取接口提供配置推送接口服务于Apollo客户端通过MetaServer调用ConfigServicePortal配置管理接口通过SLB方式获取AdminService的服务列表使用客户端软加载SLB方式调用AdminServiceApoll更新配置配置是否更新?在看这个问题之前,我们先回顾一下每个周末去热门餐厅吃饭的过程是怎样的?首先一定要现场取号,或者手机上取号。然后就是排队刷手机等叫号。吃到一半会主动问要等多久,服务员会告诉你等一下,前面还有几桌。上面这个吃东西的例子是怎么知道列数的呢?有两种方式,一种是每隔一段时间问服务员,问服务员号有没有号,没有号就继续用电话,号号上了就直接进去吃饭,另一种是简单地坐在那里使用电话,反正我也不着急,等待通知。同一个配置中心的更新是如何通知到client列的?是服务端(configService)主动通知客户端(client),告诉它你的应用的配置被修改了。什么是原始值,什么是修改后的值?或者客户端(Client)多久向服务器询问我的配置是否被修改?如果是你,你会如何选择列?你可能会说,我必须两全其美!孩子会做出选择吗?客户端长链接获取配置更新通知,然后返回到我们使用apollo时应用中引入的Apollo客户端。当我们的应用程序启动时,每隔5s会有一个线程向服务器发起一个http请求,但是这个http请求是不会立即返回的。这是一个长链接。如果未更新配置,请求将被阻止并暂停。实现暂停的方式是通过Spring的DeferredResult。如果你对Spring的DeferredResult不是很了解,推荐看这篇文章《5种SpringMvc的异步处理方式你都了解吗?》挂了60s后,会向客户端返回HTTP状态码304。如果在阻塞过程中更新了服务器配置,则立即返回Http请求,并返回更改后的nameSpace信息,返回的http状态码为200,客户端获取状态码为200,立即取回根据名称空间从服务器获取最新配置。这里其实有一个问题,为什么在长链接中不直接返回更改后的结果,而是返回一个更改通知,客户端需要根据更改通知立即拉取新的配置呢?有兴趣的可以参考这个问题:https://github.com/apolloconf...这样推送消息是有状态的,不能幂等,会带来很多问题。目前push是通过http的单连接,所以问题可能不大,但就是设计上的问题,比如如果通过tcp长连接push。另外,longpolling和push也会有冲突。如果连续两次更改配置,可能会造成双写。另一点是保持逻辑简单。目前的push方法只负责简单的通知,不需要计算客户端应该配置成什么,因为计算逻辑相当复杂,需要考虑聚类、关联、灰度等。简而言之,就是在满足幂等性和实时性的基础上,保持设计简单。客户端的定时任务拉取所有的配置,客户端可以实时收到配置更新,这不是很完美吗。但是,如果客户端没有收到服务端的更新内容,比如服务异常或者空指针。这个时候如果我们的客户端配置不重启,是不是就永远不会更新了。没关系,Apollo也帮你想好了这个情况。既然你告诉我更新失败了,我就每隔一段时间主动拉取我所有的配置给客服端。相比之下,如果一致性直接结束,不一致就会更新客户端的缓存,本地文件也会异步更新。通过定时任务的补充,使配置达到最终一致性。客户端本地文件缓存配置主动轮询和定时任务全拉配置是否万无一失?只要涉及到分布式,就得考虑其他系统的宕机。比如某天挖掘机直接把Apollo部署的机房的光纤给剪掉了,让整个配置服务直接挂掉。这时候主动轮询和定时任务都没有起作用。如果无法拉取配置,则整个客户端应用程序也会受到影响。基本上,我们配置更改的频率是比较小的。即使我们的配置中心宕机了,我们还有一个本地文件系统,说白了,这个文件目录默认是/opt/data或者C:\opt\data,所以即使配置中心宕机了,对该应用程序相对较小。因为它还会读取本地文件来覆盖底线。小结至此我们应该知道Apollo客户端是如何感知服务器配置更新的了吧?主要是通过客户端应用向ApolloConfigServer端发起长连接,如果ApolloConfigServer端有配置变化,会通知应用端有配置修改,让客户端立即拉取全量配置,并将配置更新到本地缓存,同时也会异步更新本地文件缓存。客户端还有一个定时任务,默认每5分钟执行一次,拉取全量配置。拉回配置后,还会比较本地缓存是否与远程缓存一致。如果不是,本地进程缓存更新为远程,本地文件也异步更新。最后,由于自己的无知和知识的匮乏,难免有错误。如果您发现错误,请留言指出给我,我会改正。如果您觉得文章还不错,您的转发、分享、欣赏、点赞、评论就是对我最大的鼓励。感谢您的阅读,非常欢迎并感谢您的关注。站在巨人的肩膀上https://www.apolloconfig.com/...https://www.iocoder.cn/Apollo...