vlambda博客
学习文章列表

面试被问nacos临时实例和持久化实例,你会吗?

前言

面试被问了nacos的临时实例和持久化实例,有点懵逼了,nacos官网看过几次了,没见过这2个东西啊。于是今天再次看了下官网,它是1.0.0版本新增的特性。


 先说结论 

Nacos 1.0.0 版本在 instance 级别上增加了一个ephemeral字段,该字段表示注册的实例是临时实例还是持久化实例。


如果是临时实例,则不会在Nacos服务端持久化存储,需要通过上报心跳的方式进行保活,如果一段时间内没有上报心跳,则会被Nacos服务端摘除。在被摘除后如果又开始上报心跳,则会重新将这个实例注册。


持久化实例则会持久化到Nacos服务端,此时即使注册实例的客户端进程不在,这个实例也不会从服务端删除,只会将健康状态设为不健康。


目前这个字段的默认值是true,意思就是默认是临时实例


我们可以改false,就是持久性实例了

spring.cloud.nacos.discovery.ephemeral=false

 为什么会设计成这2个不同的实例?

上面说了两种模式的不同和处理上的区别,那么Nacos为什么设计两种模式,它们是为了应对什么样的场景而存在呢?


对于临时实例,健康检查失败,则直接可以从列表中删除。这种特性就比较适合那些需要应对流量突增的场景,服务可以进行弹性扩容。当流量过去之后,服务停掉即可自动注销了。


对于持久化实例,健康检查失败,会被标记成不健康状态。它的好处是运维可以实时看到实例的健康状态,便于后续的警告、扩容等一系列措施。

除了上述场景之外,持久化实例还有另外一个场景用到,那就是保护阈值。


 保护阈值 

Nacos中可以针对持久化实例可以设置一个保护阈值,值为0-1之间的浮点类型。本质上,保护阈值是⼀个⽐例值(当前服务健康实例数/当前服务总实例数)。


客户端要从Nacos获取可⽤实例,实例有健康和不健康状态之分。Nacos在返回实例时,只会返回健康实例。


但在⾼并发、⼤流量场景会存在⼀定的问题。比如,服务A有100个实例,98个实例都处于不健康状态,如果Nacos只返回这两个健康实例的话。流量洪峰的到来可能会直接打垮这两个服务,进一步产生雪崩效应。

保护阈值存在的意义在于当服务A健康实例数/总实例数 < 保护阈值时,说明健康的实例不多了,保护阈值会被触发(状态true)。


Nacos会把该服务所有的实例信息(健康的+不健康的)全部提供给消费者,消费者可能访问到不健康的实例,请求失败,但这样也⽐造成雪崩要好。牺牲了⼀些请求,保证了整个系统的可⽤。


这里我们看到了不健康实例的另外一个作用:防止产生雪崩。

那么,如果所有的实例都是临时实例,当雪崩场景发生时,Nacos的阈值保护机制是不是就没有足够的(包含不健康实例)实例返回了?如果有一部分实例是持久化实例,即便它们已经挂掉,状态为不健康的,但当触发阈值保护时,还是可以起到分流的作用。


 数据预热 

在老版本的 Nacos 中,只要 Server 启动成功就会开始对外提供服务,此时服务的数据并不一定完全加载完成,这样可能会导致客户端接收到的数据并不完整。

1.0.0 版本增加了数据预热的逻辑,对于持久化数据,则会等待所有数据从磁盘加载完成;对于临时实例这样的非持久化数据,则会等待从其他Server拉取到完整数据。所有数据都准备好之后,才会将 Server 状态置为 UP(Server 一切正常,读写请求都会被接受)。


 临时实例的问题:大面积删除实例 

对于临时节点的注册,当心跳超时后,Nacos会自动将该节点进行删除并且集群内同步!


当Nacos 本身网络故障时,可能大面积删除临时实例,极端情况下会导致注册列表全部清空

如果清空后的列表成功下发到 消费者的客户端,会造成严重故障