简介: 我今天介绍的 Nacos 高可用,是 Nacos 为了提升系统稳定性而采取的一系列手段。Nacos 的高可用不仅仅存在于服务端,同时也存在于客户端,以及一些与可用性相关的功能特性中,这些点组装起来,共同构成了 Nacos 的高可用。

前言

服务注册发现是一个经久不衰的话题,Dubbo 早期开源时默认的注册中心 ZooKeeper 最早进入人们的视线,并且在很长一段时间里,人们将注册中心和 ZooKeeper 划上了等号,可能 ZooKeeper 的设计者都没有想到这款产品对微服务领域造成了如此深厚的影响,直到 Spring Cloud 开始流行,其自带的 Eureka 进入了人们的视野,人们这才意识到原来注册中心还可以有其他的选择。再到后来,热衷于开源的阿里把目光也聚焦在了注册中心这个领域, Nacos 横空出世。

Kirito 在做注册中心选型时的思考:曾经我没得选,现在我只想选择一个好的注册中心,它最好是开源的,这样开放透明,有自我的掌控力。不仅要开源,它还要有活跃的社区,以确保特性演进能够满足日益增长的业务需求,出现问题也能即使修复,功能还要很强大。除了满足注册服务、推送服务外,还要有完善的微服务体系中所需的功能。最重要的,它还要稳定,最好有大厂的实际使用场景背书,证明这是一个经得起实战考验的产品。当然,云原生特性,安全特性也是很重要的······

似乎 Kirito 对注册中心的要求实在是太高了,但这些五花八门的注册中心呈现在用户眼前,总是免不了一番比较。正如上面所言,功能特性、成熟度、可用性、用户体验度、云原生特性、安全都是可以拿出来做比较的话题。今天这篇文章重点介绍的是 Nacos 在可用性上的体现,希望借助于这篇文章,能够让你对 Nacos 有一个更加深刻的认识。

高可用介绍

当我们在聊高可用时,我们在聊什么?

  • 系统可用性达到 99.99%
  • 在分布式系统中,部分节点宕机,依旧不影响系统整体运行
  • 服务端集群化部署多个节点

这些都可以认为是高可用,而我今天介绍的 Nacos 高可用,则是 Nacos 为了提升系统稳定性而采取的一系列手段。Nacos 的高可用不仅仅存在于服务端,同时也存在于客户端,以及一些与可用性相关的功能特性中,这些点组装起来,共同构成了 Nacos 的高可用。

客户端重试

先统一一下语义,在微服务架构中一般会有三个角色:Consumer、Provider 和 Registry,在今天注册中心的主题中,Registry 是 nacos-server,而 Consumer 和 Provider 都是 nacos-client。

在生产环境,我们往往需要搭建 Nacos 集群,在 Dubbo 也需要显式地配置上集群地址:

<dubbo:registry protocol="nacos" address="192.168.0.1:8848,192.168.0.2:8848,192.168.0.3:8848"/>

当其中一台机器宕机时,为了不影响整体运行,客户端会存在重试机制。

逻辑非常简单,拿到地址列表,在请求成功之前逐个尝试,直到成功为止。

该可用性保证存在于 nacos-client 端。

一致性协议 distro

首先给各位读者打个强心剂,不用看到”一致性协议“这几个字就被劝退,本节不会探讨一致性协议的实现过程,而是重点介绍其与高可用相关的特性。有的文章介绍 Nacos 的一致性模型是 AP + CP,这么说很容易让人误解,其实 Nacos 并不是支持两种一致性模型,也并不是支持两种模型的切换,介绍一致性模型之前,需要先了解到 Nacos 中的两个概念:临时服务和持久化服务。

  • 临时服务(Ephemeral):临时服务健康检查失败后会从列表中删除,常用于服务注册发现场景。
  • 持久化服务(Persistent):持久化服务健康检查失败后会被标记成不健康,常用于 DNS 场景。

临时服务使用的是 Nacos 为服务注册发现场景定制化的私有协议 distro,其一致性模型是 AP;而持久化服务使用的是 raft 协议,其一致性模型是 CP。所以以后不要再说 Nacos 是 AP + CP 了,更建议加上服务节点状态或者使用场景的约束。

distro 协议与高可用有什么关系呢?上一节我们提到 nacos-server 节点宕机后,客户端会重试,但少了一个前提,即 nacos-server 少了一个节点后依旧可以正常工作。Nacos 这种有状态的应用和一般无状态的 Web 应用不同,并不是说只要存活一个节点就可以对外提供服务的,需要分 case 讨论,这与其一致性协议的设计有关。distro 协议的工作流程如下:

  • Nacos 启动时首先从其他远程节点同步全部数据。
  • Nacos 每个节点是平等的都可以处理写入请求,同时把新数据同步到其他节点。
  • 每个节点只负责部分数据,定时发送自己负责数据的校验值到其他节点来保持数据一致性。

如上图所示,每个节点负责一部分服务的写入,但每个节点都可以接收到写入请求,这时就存在两种情况:

  • 当该节点接收到属于该节点负责的服务时,直接写入。
  • 当该节点接收到不属于该节点负责的服务时,将在集群内部路由,转发给对应的节点,从而完成写入。

读取操作则不需要路由,因为集群中的各个节点会同步服务状态,每个节点都会有一份最新的服务数据。

而当节点发生宕机后,原本该节点负责的一部分服务的写入任务会转移到其他节点,从而保证 Nacos 集群整体的可用性。

一个比较复杂的情况是,节点没有宕机,但是出现了网络分区,即下图所示:

这个情况会损害可用性,客户端会表现为有时候服务存在有时候服务不存在。

综上,Nacos 的 distro 一致性协议可以保证在大多数情况下,集群中的机器宕机后依旧不损害整体的可用性。该可用性保证存在于 nacos-server 端。

本地缓存文件 Failover 机制

注册中心发生故障最坏的一个情况是整个 Server 端宕机,这时候 Nacos 依旧有高可用机制做兜底。

一道经典的 Dubbo 面试题:当 Dubbo 应用运行时,Nacos 注册中心宕机,会不会影响 RPC 调用。这个题目大多数应该都能回答出来,因为 Dubbo 内存里面是存了一份地址的,一方面这样的设计是为了性能,因为不可能每次 RPC 调用时都读取一次注册中心,另一面,注册中心宕机后内存会有一份数据,这也起到了可用性的保障(尽管可能 Dubbo 设计者并没有考虑这个因素)。

那如果,我在此基础上再抛出一个问题:Nacos 注册中心宕机,Dubbo 应用发生重启,会不会影响 RPC 调用。如果了解了 Nacos 的 Failover 机制,应当得到和上一题同样的回答:不会。

Nacos 存在本地文件缓存机制,nacos-client 在接收到 nacos-server 的服务推送之后,会在内存中保存一份,随后会落盘存储一份快照。snapshot 默认的存储路径为:{USER_HOME}/nacos/naming/ 中:

这份文件有两种价值,一是用来排查服务端是否正常推送了服务;二是当客户端加载服务时,如果无法从服务端拉取到数据,会默认从本地文件中加载。

前提是构建 NacosNaming 时传入了该参数:namingLoadCacheAtStart=true 
Dubbo 2.7.4 及以上版本支持该 Nacos 参数;开启该参数的方式:dubbo.registry.address=nacos://127.0.0.1:8848?namingLoadCacheAtStart=true

在生产环境,推荐开启该参数,以避免注册中心宕机后,导致服务不可用,在服务注册发现场景,可用性和一致性 trade off 时,我们大多数时候会优先考虑可用性。

细心的读者还注意到 
{USER_HOME}/nacos/naming/{namespace} 下除了缓存文件之外还有一个 failover 文件夹,里面存放着和 snapshot 一致的文件夹。这是 Nacos 的另一个 failover 机制,snapshot 是按照某个历史时刻的服务快照恢复恢复,而 failover 中的服务可以人为修改,以应对一些极端场景。

该可用性保证存在于 nacos-client 端。

心跳同步服务

心跳机制一般广泛存在于分布式通信领域,用于确认存活状态。一般心跳请求和普通请求的设计是有差异的,心跳请求一般被设计的足够精简,这样在定时探测时可以尽可能避免性能下降。而在 Nacos 中,出于可用性的考虑,一个心跳报文包含了全部的服务信息,这样相比仅仅发送探测信息降低了吞吐量,而提升了可用性,怎么理解呢?考虑以下的两种场景:

  • nacos-server 节点全部宕机,服务数据全部丢失。nacos-server 即使恢复运作,也无法恢复出服务,而心跳包含全部内容可以在心跳期间就恢复出服务,保证可用性。
  • nacos-server 出现网络分区。由于心跳可以创建服务,从而在极端网络故障下,依旧保证基础的可用性。

以下是对心跳同步服务的测试,使用阿里云 MSE 提供 Nacos 集群进行测试:

调用 OpenApi 依次删除各个服务:

curl -X "DELETE mse-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"

过 5s 后刷新,服务又再次被注册了上来,符合我们对心跳注册服务的预期。

集群部署模式高可用

最后给大家分享的 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 集群的部署和运维。

MSE Nacos 的高可用最佳实践

阿里云微服务引擎 MSE 提供了 Nacos 集群的托管能力,实现了集群部署模式的高可用。

  • 当创建多个节点的集群时,系统会默认分配在不同可用区。同时,这对于用户来说又是透明的,用户只需要关心 Nacos 的功能即可,MSE 替用户兜底可用性。
  • MSE 底层使用 K8s 运维模式部署 Nacos。历史上出现过用户误用 Nacos 导致部分节点宕机的问题,但借助于 K8s 的自运维模式,宕机节点迅速被拉起,以至于用户可能都没有意识到自己发生宕机。

下面模拟一个节点宕机的场景,来看看 K8s 如何实现自恢复。

一个三节点的 Nacos 集群:

执行kubectl delete pod mse-7654c960-1605278296312-reg-center-0-2 以模拟部分节点宕机的场景。

大概 2 分钟后,节点恢复,并且角色发生了转换,Leader 从杀死的 2 号节点转给 1 号节点。

总结

本文从多个角度出发,总结了一下 Nacos 是如何保障高可用的。高可用特性绝不是靠服务端多部署几个节点就可以获得的,而是要结合客户端使用方式、服务端部署模式、使用场景综合来考虑的一件事。

特别是在服务注册发现场景,Nacos 为可用性做了非常多的努力,而这些保障,ZooKeeper 是不一定有的。在做注册中心选型时,可用性保障上,Nacos 绝对是优秀的。

原文链接

本文为阿里云原创内容,未经允许不得转载。

一文详解 Nacos 高可用特性的更多相关文章

  1. 多图|一文详解Nacos参数!

    Nacos 中的参数有很多,如:命名空间.分组名.服务名.保护阈值.服务路由类型.临时实例等,那这些参数都是什么意思?又该如何设置?接下来我们一起来盘它. 1.命名空间 在 Nacos 中通过命名空间 ...

  2. Hadoop详解(09) - Hadoop新特性

    Hadoop详解(09) - Hadoop新特性 Hadoop2.x新特性 远程主机之间的文件复制 scp实现两个远程主机之间的文件复制 推 push:scp -r hello.txt root@ha ...

  3. Nacos高可用集群解决方案-Docker版本

    文章主旨 本文目的是配置高可用的Nacos集群 架构图 整体架构为:Nginx + 3 x Nacos +高可用MySQL 高可用MySQL使用主从复制结构的可以参考Docker搭建MySQL主从集群 ...

  4. Java精通并发-自旋对于synchronized关键字的底层意义与价值分析以及互斥锁属性详解与Monitor对象特性解说【纯理论】

    自旋对于synchronized关键字的底层意义与价值分析: 对于synchronized关键字的底层意义和价值分析,下面用纯理论的方式来对它进行阐述,自旋这个概念就会应运而生,还是很重要的,下面阐述 ...

  5. 一文详解Hexo+Github小白建站

    作者:玩世不恭的Coder时间:2020-03-08说明:本文为原创文章,未经允许不可转载,转载前请联系作者 一文详解Hexo+Github小白建站 前言 GitHub是一个面向开源及私有软件项目的托 ...

  6. 一文详解 Linux 系统常用监控工一文详解 Linux 系统常用监控工具(top,htop,iotop,iftop)具(top,htop,iotop,iftop)

    一文详解 Linux 系统常用监控工具(top,htop,iotop,iftop)     概 述 本文主要记录一下 Linux 系统上一些常用的系统监控工具,非常好用.正所谓磨刀不误砍柴工,花点时间 ...

  7. 从零入门 Serverless | 一文详解 Serverless 技术选型

    作者 | 李国强 阿里云资深产品专家 今天来讲,在 Serverless 这个大领域中,不只有函数计算这一种产品形态和应用类型,而是面向不同的用户群体和使用习惯,都有其各自适用的 Serverless ...

  8. 1.3w字,一文详解死锁!

    死锁(Dead Lock)指的是两个或两个以上的运算单元(进程.线程或协程),都在等待对方停止执行,以取得系统资源,但是没有一方提前退出,就称为死锁. 1.死锁演示 死锁的形成分为两个方面,一个是使用 ...

  9. 一文详解 WebSocket 网络协议

    WebSocket 协议运行在TCP协议之上,与Http协议同属于应用层网络数据传输协议.WebSocket相比于Http协议最大的特点是:允许服务端主动向客户端推送数据(从而解决Http 1.1协议 ...

  10. 一文详解 OpenGL ES 3.x 渲染管线

    OpenGL ES 构建的三维空间,其中的三维实体由许多的三角形拼接构成.如下图左侧所示的三维实体圆锥,其由许多三角形按照一定规律拼接构成.而组成圆锥的每一个三角形,其任意一个顶点由三维空间中 x.y ...

随机推荐

  1. Django使用Bootstrap的经典方法

    前面的话 Bootstrap是简单.灵活的用于搭建WEB页面的HTML.CSS.Javascript的工具集.Bootstrap基于HTML5和CSS3,具有漂亮的设计.友好的学习曲线.卓越的兼容性, ...

  2. Eclipse之各个版本的区别

    经常用到的是前五个版本: Eclipse IDE for Java EE Developers:是为J2EE开发的版本: Eclipse Classic:是Eclipse的经典版本,没有安装任何插件, ...

  3. gRPC入门学习之旅(二)

    gRPC入门学习之旅(一) gRPC是一个高性能.通用的开源远程过程调用(RPC)框架,基于底层HTTP/2协议标准和协议层Protobuf序列化协议开发,支持众多的开发语言,由Google开源. g ...

  4. STM32 HAL 使用串口IDLE中断+DMA实现收发

    STM32 HAL 使用串口IDLE中断+DMA实现收发 cubeMX配置 mx配置如下(省去系统时钟,烧录口,工程属性配置) 注意:这里关闭 Force DMA channels Interrupt ...

  5. django(ORM)

    一 单表(增.删.改.查) 1 测试脚本 ''' 只想测试django中的某一个py文件内容,那么可以不用书写前后端交互的形式 而是直接写一个测试脚本即可 ''' # 脚本代码无论是写在应用下的tes ...

  6. App磁盘沙盒工具实践

    目录介绍 01.磁盘沙盒的概述 1.1 项目背景说明 1.2 沙盒作用 1.3 设计目标 02.Android存储概念 2.1 存储划分介绍 2.2 机身内部存储 2.3 机身外部存储 2.4 SD卡 ...

  7. npm ERR! code ENOENT npm ERR! syscall open npm ERR! path C:\Users\shuzi\Desktop\保密文件项目\test-ui/package.json npm ERR! errno -4058

    打开一个新的项目,因为当前项目文件夹下没有npm,"dev": "npm run start:dev",所以所以没有展示对应的运行图,如下图: 打开一个新的前端 ...

  8. IValueConverter的基础用法

    1.我们在做工控项目的时候通常设置配方的上下限 这个时候要求OK数在上下限范围之内,否则NG 首先我们绑定一个简单的List用来展示数据,我这里用学生Age来展示 <ListView Items ...

  9. 记录--经常被cue大文件上传,忍不住试一下

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 大文件上传主要步骤: 获取文件对象,切分文件 根据文件切片,计算文件唯一hash值 上传文件切片,服务端保存起来 合并文件切片,前端发送合 ...

  10. Python 如何通过网易163邮箱自动发送邮件

    一.发送邮件的前提是必须开通发件服务器获取对应授权密码. 二.对应代码如下所示 import smtplib from email.mime.text import MIMEText from ema ...