当前位置: 首页 > 科技观察

Nacos高可用特性详解

时间:2023-03-14 12:04:04 科技观察

本文转载自微信公众号《桐人的技术分享》,作者kiritomoe。转载本文请联系桐人的技术分享公众号。前言服务注册发现是一个经久不衰的话题。Zookeeper,早期Dubbo开源时的默认注册中心,最先进入人们的视线,很长一段时间,人们将注册中心等同于Zookeeper。可能Zookeeper的设计者并没有想到这款产品会对微服务领域产生如此深远的影响。直到SpringCloud开始流行,自带的Eureka进入人们的视野,人们才意识到注册中心还有其他的选择。后来,热衷于开源的阿里也将目光投向了注册中心领域,Nacos由此诞生。注册中心桐人在选择注册中心时的想法:以前没得选,现在只想选个好的注册中心。最好是开源的,做到公开透明,有自制力;不仅要开源,还需要有一个活跃的社区来保证特性的演进能够满足不断增长的业务需求,即使出现问题也可以修复;最好的……它的功能一定很强大。除了满足注册服务和推送服务,还必须具备一个完整的微服务系统所需要的功能;最重要的是,一定要稳定,最好有大厂实际使用场景的背书,证明这是一款经得起实战考验的产品;当然,云原生的特性,安全特性也很重要……看来桐人对注册中心的要求太高了,但是这些形形色色的注册中心呈现在用户面前,总免不了要比较一下。上面提到,功能特性、成熟度、易用性、用户体验、云原生特性、安全性都是可以比较的话题。今天的文章重点介绍Nacos的易用性。希望这篇文章能让大家对Nacos有更深入的了解。高可用性简介当我们谈论高可用性时,我们在谈论什么?系统可用性达到99.99%。在分布式系统中,即使部分节点宕机,也不影响整个系统的运行。就是高可用,今天我介绍的Nacos高可用,就是一些Nacos为了提高系统稳定性而采取的一系列手段。Nacos的高可用不仅仅存在于服务端,也存在于客户端,以及一些与可用性相关的特性。这些点集合起来就形成了Nacos的高可用。我们先统一客户端重试的语义。微服务架构中一般有三种角色:Consumer、Provider、Registry。在今天的registry主题中,Registry是nacos-server,而Consumer和Provider都是nacos-client。在生产环境中,我们经常需要搭建Nacos集群,在Dubbo中也需要显式配置集群地址:当其中一台机器宕机时,为了不影响整体运行,客户端会有重试机制轮询服务器。逻辑很简单。获取地址列表,在请求成功前逐一尝试,直到成功。这种可用性保证存在于nacos-client端。Consistencyprotocoldistro首先给读者打一针强心剂,不用看到“一致性协议”几个字就被说服了。本节将不讨论一致性协议的实现过程,而是将重点放在其余的高可用性相关特性上。有文章介绍Nacos的一致性模型是AP+CP。这很容易被误解。事实上,Nacos并不支持两种一致性模型,也不支持两种模型之间的切换。在介绍一致性模型之前,需要先了解Nacos中的两个概念:临时服务和持久化服务。临时服务(Ephemeral):临时服务在健康检查失败后将从列表中删除。常用于服务注册发现场景。持久化服务(Persistent):如果持久化服务的健康检查失败,会被标记为unhealthy,常用于DNS场景。临时服务使用distro,Nacos为服务注册和发现场景定制的私有协议,其一致性模型为AP;而持久化服务使用raft协议,其一致性模型为CP。所以以后不要说Nacos是AP+CP,更推荐加入服务节点状态或者使用场景的约束。发行版协议和高可用性之间有什么关系?上一节我们提到nacos-server节点宕机后,客户端会重试,但是这里缺少一个前提,就是nacos-server节点宕机后仍然可以正常工作。Nacos等有状态应用不同于一般的无状态Web应用。并不是说只要有一个节点存活,就可以对外提供服务。需要分案讨论,这与其一致性协议的设计有关。Distro协议的工作流程如下:Nacos启动时,首先从其他远程节点同步所有数据。Nacos节点是平等的,可以处理写入请求,同时将新数据同步到其他节点。每个节点只负责部分数据并定期发送。我负责将数据验证值发送给其他节点,以维护集群的正常状态。如上图所示,每个节点都服务一部分读写服务,但是每个节点都可以接收到读写请求。此时有两种读写情况:当节点收到属于该节点的服务时,直接读写。当节点收到一个不是本节点负责的服务时,会在集群内部进行路由,转发给相应的节点完成读写。当一个节点宕机时,该节点原本负责的一部分服务的读写任务会转移到其他节点上,从而保证Nacos集群的整体可用性。部分节点宕机更复杂的情况是节点没有宕机,但是存在网络分区,如下图:网络分区会破坏可用性,客户端会显示有时服务存在和有时服务不存在。综上所述,Nacos的distro一致性协议可以保证在大多数情况下,集群内的机器宕机后整体可用性不会受损。这种可用性保证存在于nacos-server端。本地缓存文件故障转移机制注册中心最坏的情况是整个服务器宕机。这时候Nacos还有一个高可用机制作为掩护。一道经典的Dubbo面试题:Dubbo应用运行时,如果Nacos注册中心宕机,会不会影响RPC调用。这个问题大部分应该可以回答,因为Dubbo在内存中存储了一个地址。这种设计一方面是为了性能,因为不可能每次调用RPC的时候都去读注册中心。另一方面,这也保证了可用性(虽然Dubbo的设计者可能没有考虑到这个因素)。那么,如果我基于此再问一个Dubbo面试题:Nacos注册中心宕机,Dubbo应用重启,会不会影响RPC调用。如果你了解Nacos的Failover机制,你应该会得到和上一个问题一样的答案:没有。Nacos有本地文件缓存机制。nacos-client收到nacos-server的服务推送后,会在内存中保存一份,然后在磁盘上存储一个快照。快照默认存放路径为:Nacos快照文件目录在{USER_HOME}/nacos/naming/这个文件有两个值,一个是检查服务端是否正常推送服务;另一种是客户端加载服务时,如果无法从服务端拉取数据,则默认从本地文件加载。前提是在构建NacosNaming时传入这个参数:namingLoadCacheAtStart=trueDubbo2.7.4及以上版本支持这个Nacos参数;启用该参数的方式为:dubbo.registry.address=nacos://127.0.0.1:8848?namingLoadCacheAtStart=true生产环境建议启用该参数,避免注册中心上线后服务不可用和不稳定向下。在服务注册发现场景中,当可用性和一致性权衡时,我们大多数时候会优先考虑可用性。细心的读者还注意到,除了缓存文件外,{USER_HOME}/nacos/naming/{namespace}下还有一个failover文件夹,里面存放的是和snapshot一样的文件夹。这是Nacos的另一种故障转移机制。快照根据某个历史时刻的服务快照进行恢复,故障转移中的服务可以手动修改以应对一些极端场景。这种可用性保证存在于nacos-client端。心跳同步服务心跳机制普遍存在于分布式通信领域,用于确认生存状态。一般心跳请求和普通请求在设计上是有区别的。心跳请求一般都设计得足够简洁,这样在定时检测的时候尽量避免性能下降。在Nacos中,为了易用性,一个心跳消息包含了所有的服务信息,相比只发送探测信息,降低了吞吐量,提高了易用性。怎么理解呢?考虑以下两种场景:nacos-服务器节点全部宕机,服务数据全部丢失。即使nacos-server恢复运行,也无法恢复服务,但是心跳包含所有内容,可以在心跳期间恢复服务,保证可用性。nacos-server有一个网络分区。由于心跳可以创建服务,因此在极端网络故障下仍然可以保证基本可用性。下面是心跳同步服务的测试,使用阿里云MSE提供的Nacos集群测试调用OpenApi:curl-X"DELETEmse-xxx-p.nacos-ans.mse.aliyuncs.com:8848/nacos/v1/ns/service?serviceName=providers:com.alibaba.edas.boot.EchoService:1.0.0:DUBBO&groupName=DEFAULT_GROUP"依次删除每个服务,5秒后刷新,服务重新注册,满足我们对心跳注册服务的期望。集群部署方式高可用最后要跟大家分享的Nacos高可用特性来自于它的部署架构。节点数我们知道Nacos在生产集群中一定不能单机运行,那么第一个问题就是:我应该部署多少台机器?前面我们提到Nacos有两种一致性协议:distro和raft。Distro协议不会出现脑裂问题,所以理论上节点数大于等于2;raft协议的投票机制推荐为2n+1个节点。整体来说,3个节点的选择是最少的,其次考虑吞吐量和更高的可用性,可以选择5个、7个甚至9个节点的集群。在多个可用区部署集群的Nacos节点,尽可能考虑两个因素:每个节点之间的网络延迟不能很高,否则会影响数据同步。每个节点所在的机房和可用区尽量分散,避免单点故障以阿里云的ECS为例,选择同一Region的不同可用区是一个很好的实践。部署方式主要分为两种模式:K8s部署和ECS部署。ECS部署的好处就是简单。购买三台机器即可搭建集群。如果熟悉Nacos集群部署,难度不大,但无法解决运维问题。如果Nacos节点出现OOM或者磁盘问题,很难快速移除,无法实现自主运维。K8s部署的优势在于其强大的云原生运维能力,可以实现节点宕机后的自我恢复,保证Nacos的平稳运行。如前所述,Nacos不同于无状态的Web应用程序。它是一个有状态的应用程序。因此,在K8s中部署时,往往会使用StatefulSet、Operator等组件来实现Nacos集群的部署和运维。MSENacos高可用最佳实践阿里云MSE(微服务引擎)提供Nacos集群的托管能力,实现集群部署方式的高可用。创建多节点集群时,系统会默认将它们分配到不同的可用区。同时,这对用户来说是透明的。用户只需要关心Nacos的功能,MSE会覆盖用户的易用性。MSE底层采用K8s运维方式部署Nacos。历史上曾出现过用户误用Nacos导致部分节点宕机的问题。但是借助K8s的自运维模式,将宕机的节点快速拉起,让用户可能意识不到自己宕机了。下面模拟一个节点宕机场景,看看K8s是如何实现自恢复的。三节点Nacos集群:正常状态下执行kubectldeletepodmse-7654c960-1605278296312-reg-center-0-2,模拟部分节点宕机的场景。恢复后约2分钟,节点恢复,角色发生变化。leader从被杀死的2号节点转移到1号节点。Afterrecovery,theleaderwasre-elected.可用。高可用的特性绝不是在服务端多部署几个节点就能获得的,而是要结合客户端的使用方式、服务端的部署方式、使用场景来综合考虑。尤其是服务注册发现场景,Nacos在可用性方面做了很多努力,而Zookeeper不一定有这些保障。在选择注册中心时,Nacos在易用性保障方面绝对优秀。