Nacos配置中心设计原理分析

 更新时间:2023年10月20日 08:24:06   作者:刘牌  
今天分享一下Nacos配置变更的相关知识点,现在使用Java生态如果使用微服务,如果部署在K8s上,那么可能会使用ConfigMap来存储配置文件,如果没有使用K8s,那么基本上都使用Nacos来做配置中心,所以有必要了解一下Nacos的配置的知识点,本文只是对其中的部分实现原理进行分析

一、怎么判断配置发生了变化

我们在使用Nacos的时候,在Console对配置进行更改后,不用重启服务,只要配置发生变化就能生效,那么Nacos是怎么判断配置发生了变化呢?

Nacos的配置中支持多中格式,比如yml,properties,xml,json等,当然,使用yml格式的应该占大部分!

不过可以肯定的是,无论使用的是那种格式,数据都是键值对的形式,所以我们有一种实现方式,就是将配置转换为一个Map保存下来,当通过控制台或者API对配置进行变更的时候,我们将变更的数据和保存下来的Map中的值进行一一比对,如果有发生变化的那么就更新变化的那个key的value值。

不过上面这种方案的话开销有点大,因为需要去解析配置文件,然后去对比每一个key。

Nacos的实现方式是通过对配置进行MD5加密,当配置发生变更,那么就对变更后的配置进行MD5加密,然后和本地的MD5进行比对,如果相同则代表配置没发生变更,MD5值不同则代表发生了变更,则需要推送变更的配置到服务里面。

虽然使用进行MD5加密有一定的开销,但是也是在能接受的范围内。

核心代码如下,当监听器收到配置变更后,会判断和本地的MD5是否一样,不一样则推送变更的配置。

二、怎么触发变更

在Nacos启动的时候,会在后台启动一个线程去比对配置信息变更情况,不过并不是使用死循环不断去获取,废话不多说,直接上核心代码。

Nacos中巧妙的使用了队列的poll来实现配置变更的实时拉取,图中圈出来的listenExecutebell,bell的意思是铃声,listenExecutebell是一个队列,使用了它的poll的超时方法,也就是说如果没有从listenExecutebell中获取到元素,那么就会阻塞,Nacos中阻塞50s,当获取到元素,立马往下执行。

为什么要这样做呢!

我们想一下,如果不使用这种方式,而是使用轮询的方式去处理,比如1s或者5s去获取一次,那么如果配置一直都没有变更,一直发起请求,这将会增加服务的压力,还有因为是轮询的方式,数据也不能保证能够实时。

Nacos1.X采用的是轮询分方式,后面进行了更改,比如我们从控制台或者通过API更改了配置信息,那么当客户端收到服务端配置变更的通知后,就会去调用notifyListenConfig()方法。

notifyListenConfig()方法就是往listenExecutebell队列中添加元素,当listenExecutebell中有元素时,就会去执行executeConfigListen()方法,这个方法就是去执行配置比对的相关操作。

所以总结下来,当配置信息发生变化的时候,就会主动去触发本地配置更新操作,不仅保证了实时,也不会像轮询那样占用资源。

三、服务故障数据怎么保证

因为配置信息属于需要很频繁访问的数据,所以是存储在内存中的,不过存储在内存中数据当机器发生故障的时候会丢失,那么Nacos是怎么来解决这个问题的呢?

首先如果我们要保证Nacos的高可用,高可靠,数据持久化是一定要做的,Nacos支持数据库持久化,我们可以使用Mysql来存储配置信息。

当服务出现故障重启后,Nacos会从数据库中获取数据,然后保存到内存中,如下,使用@PostConstruct标注init()方法,那么在启动时会执行这个方法。

Nacos的配置除了保存在内存,数据库中,还会保存在本地文件里,所以Nacos故障重启后,也会清理掉本地文件,然后重新生成,这样才能保证数据正确。

四、数据一致性

如果是Nacos单节点,就不存在数据一致性问题,但是当Nacos是集群部署时,就要考虑各节点数据一致问题了,所以就得引入共识机制。

Nacos使用的共识算法是JRaft和Distro,JRaft是强一致性算法,而Distro是最终一致性算法。

对于Nacos的共识机制,可以去官方文档上进行详细查看,这里不进行展开叙述了。

以上就是Nacos配置中心设计原理分析的详细内容,更多关于Nacos配置中心的资料请关注脚本之家其它相关文章!

相关文章

  • java多线程CountDownLatch与线程池ThreadPoolExecutor/ExecutorService案例

    java多线程CountDownLatch与线程池ThreadPoolExecutor/ExecutorService案

    这篇文章主要介绍了java多线程CountDownLatch与线程池ThreadPoolExecutor/ExecutorService案例,
    2021-02-02
  • 手把手教你搭建第一个Spring Batch项目的步骤

    手把手教你搭建第一个Spring Batch项目的步骤

    这篇文章主要介绍了手把手教你搭建第一个Spring Batch项目的步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • Java中线程Thread的三种方式和对比

    Java中线程Thread的三种方式和对比

    这篇文章主要介绍了Java中线程Thread的三种方式和对比,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • 深入浅出分析Java抽象类和接口【功能,定义,用法,区别】

    深入浅出分析Java抽象类和接口【功能,定义,用法,区别】

    这篇文章主要介绍了Java抽象类和接口,结合实例形式深入浅出的分析了java抽象类与接口的功能功能,定义,用法及区别,需要的朋友可以参考下
    2017-08-08
  • SpringBoot中RabbitMQ集群的搭建详解

    SpringBoot中RabbitMQ集群的搭建详解

    单个的 RabbitMQ 肯定无法实现高可用,要想高可用,还得上集群。这篇文章主要介绍了SpringBoot中RabbitMQ集群的两种模式的搭建:普通集群搭建和镜像集群搭建,需要的朋友可以参考一下
    2021-12-12
  • Spring IOC原理详解

    Spring IOC原理详解

    这篇文章主要介绍了Spring IOC原理详解,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • Servlet 过滤器详细介绍

    Servlet 过滤器详细介绍

    这篇文章介绍了Servlet 过滤器,有需要的朋友可以参考一下
    2013-10-10
  • Java之Spring Bean 作用域和生命周期

    Java之Spring Bean 作用域和生命周期

    这篇文章主要介绍了Java Bean的作用域和生命周期,Bean 的作用域是指 Bean 在 Spring 整个框架中的某种行为模式,所谓的⽣命周期指的是⼀个对象从诞⽣到销毁的整个⽣命过程,我们把这个过程就叫做⼀个对象的⽣命周期,感兴趣的同学可以参考阅读
    2023-04-04
  • Java本地缓存工具之LoadingCache的使用详解

    Java本地缓存工具之LoadingCache的使用详解

    缓存,在我们日常开发中是必不可少的一种解决性能问题的方法。简单的说,cache 就是为了提升系统性能而开辟的一块内存空间。本文将为大家介绍一个Java本地缓存的工具——LoadingCache,感兴趣的可以了解一下
    2021-12-12
  • Java多线程 实例解析

    Java多线程 实例解析

    这篇文章主要介绍了Java多线程 实例解析,需要的朋友可以参考下
    2017-04-04

最新评论