Nacos注册中心客户端容灾

目前Nacos客户端有一个FailoverReactor来进行容灾文件的管理,可以通过在指定磁盘文件里写入容灾数据来进行客户端使用数据的覆盖。FailoverReactor目前会拦截Nacos客户端查询接口调用,以getAllInstances接口为例,目前FailoverReactor的工作流程如下图:


这里主要涉及到两个组件:

  • FailoverReactor:容灾数据管理类,负责容灾开关和数据的加载和刷新;
  • ServiceInfoHoler:默认的服务数据管理类,持有一份内存服务数据缓存,负责处理Nacos服务端的推送的最新数据;

FailoverReactor和ServiceInfoHoler的交互机制如下:

这里和客户端容灾的相关逻辑主要是3个:

  1. FailoverReactor会定期读取磁盘容灾开关文件;
  2. 当容灾开关打开时,FailoverReactor会从磁盘里加载容灾数据文件,同时用户调用查询请求时就会优先使用容灾文件里的数据;
  3. FailoverReactor会定期从ServiceInfoHolder拿到最新的内存数据,保存到容灾磁盘数据文件里;

目前的方式有四个问题:

  1. 无法人工覆盖容灾数据,当前是定期将ServiceInfoHolder里的数据进行持久化作为容灾数据。即使手动修改了容灾数据磁盘文件内容,也会被覆盖为ServiceInfoHolder里的数据;
  2. 基于磁盘的容灾缓存有一些限制,比如服务的订阅者有多个机器实例时,如果需要打开容灾开关,需要运维批量修改机器的文件;
  3. subscribe接口不会使用FailoverReactor里的数据;
  4. 容灾数据的可观测性也需要优化。

实现方案

上面提到的问题1、3和4都比较好解决,下面会一一阐述。针对问题2,一般在生产环境中,我们会考虑使用中心化的数据存储来进行容灾数据的存储和管理。我们可以将FailoverReactor依赖的数据 来源抽象为一个SPI接口FailoverDataSource,这个接口默认实现还是本地磁盘,但是用户可以实现这个SPI接口来使用自定义的容灾数据源。

接口和数据结构定义

FailoverDataSource的定义为:

public interface FailoverDataSource {FailoverSwitch getSwitch();Map<String, FailoverData> getFailoverData();
}

各个方法的作用为:

  • FailoverSwitch getSwitch():获取当前的容灾开关;
  • Map<String, FailoverData> getFailoverData():获取当前的容灾数据,返回一个map,key是服务名,value为对应服务的容灾数据;

FailoverSwitch的定义建议如下:

public class FailoverSwitch {private boolean enabled;
}
  • enabled:容灾是否打开;

FailoverData的定义建议为:

public abstract class FailoverData {private DataType dataType;private Object data;protected FailoverData(Object data, DataType dataType) {this.data = data;this.dataType = dataType;}enum DataType {naming,config}
}
  • dataType:容灾数据类型,这里因为需要综合考虑配置模块的容灾,所以使用抽象类定义了naming和config两种容灾数据类型;
  • data:容灾数据,子类设置具体类型;

以naming模块为例,NamingFailoverData扩展FailoverData:

public class NamingFailoverData extends FailoverData {private NamingFailoverData(ServiceInfo serviceInfo) {super(serviceInfo, DataType.naming);}public static NamingFailoverData newNamingFailoverData(ServiceInfo serviceInfo) {return new NamingFailoverData(serviceInfo);}
}

NamingFailoverData里的容灾数据类型为ServiceInfo。

交互流程

FailoverReactor内部流程

FailoverReactor和FailoverDataSource、ServiceInfoHoler的交互机制优化为:

各个组件职责说明如下:

  • FailoverReactor:存储容灾缓存数据,管理容灾开关定时任务和容灾数据更新定时任务;
  • FailoverSwitchRefresher:定时(每5秒)从容灾数据源查询容灾开关,根据容灾开关的值进行相应操作:
    • 若容灾打开:从容灾数据源查询容灾数据FailoverDataSource,保存到FailoverReactor的内存容灾数据map里;
    • 若容灾关闭:清空FailoverReactor的内存容灾数据map;
  • FailoverDataSource:存储容灾数据,前文已经提及;
  • ServiceInfoHoler:默认情况下服务数据的管理,前文已经提及;

客户端查询请求流程

对于客户端的查询请求,其流程优化为:

这里的流程和之前的变化为:当从failoverReactor里拿不到容灾数据的时候,还是会去serviceInfoHolder里读取数据。这么做的目的是因为我们可能只配置部分服务进行容灾,其他的服务还是走serviceInfoHolder。

订阅接口事件通知流程

对于订阅接口,之前是不会受到容灾开关的影响,现在则也会在容灾开启时停止数据更新通知:

public ServiceInfo processServiceInfo(ServiceInfo serviceInfo) {...if (changed) {NAMING_LOGGER.info("current ips:({}) service: {} -> {}", serviceInfo.ipCount(), serviceInfo.getKey(),JacksonUtils.toJson(serviceInfo.getHosts()));// 判断容灾开关是否打开,打开时不发布事件:if (!failoverDataSource.getFailoverSwitch().isEnabled()) {NotifyCenter.publishEvent(new InstancesChangeEvent(notifierEventScope, serviceInfo.getName(), serviceInfo.getGroupName(),serviceInfo.getClusters(), serviceInfo.getHosts()));}DiskCache.write(serviceInfo, cacheDir);}return serviceInfo;}

同时,在容灾关闭时,我们需要根据容灾期间数据是否发生变化来决定要不要触发订阅事件通知,我们可以把这个逻辑驾到上面提到的FailoverSwitchRefresher里:

在这里当FailoverSwitchRefresher轮询发现容灾关闭时,在清空FailoverReactor的内存数据之前,会触发FailoverReactor和ServiceInfoHolder的数据比较,如果发现数据不一致,则会触发ServiceInfoHolder发布对应的服务变更事件。

可观测性

我们可以定义个MultiGauge来存储FailoverReactor里目前生效的容灾数据内容,统计粒度为每个服务当前有多少个实例:

MultiGauge failoverInstanceCounts = MultiGauge.builder("nacos_naming_client_failover_instances").register(Metrics.globalRegistry);Set<String> serviceNames = failoverDataSource.getSwitch().getServiceNames();
Map<String, FailoverData> failoverDataMap = failoverDataSource.getFailoverData();failoverInstanceCounts.register(serviceNames.stream().map(serviceName -> MultiGauge.Row.of(Tags.of("service_name", serviceName), ((ServiceInfo)failoverDataMap.get(serviceName)).ipCount())).collect(Collectors.toList()), true);

测试用例

以下场景需要进行测试:

  • 打开容灾开关后,对于包含在容灾的服务列表里的服务,Nacos服务端数据变化不影响客户端查询和订阅;
  • 关闭容灾开关后,对于所有服务客户端查询到最新数据;
  • 关闭容灾开关后,若订阅的服务数据在容灾期间有变化,会触发一次订阅通知;
  • 设置容灾的服务列表,不在服务列表里的不会使用容灾数据;
  • 使用自定义的容灾实现,可以被加载并运行;

原文出自:Nacos官网 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/212584.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【合集】SpringBoot——Spring,SpringBoot,SpringCloud相关的博客文章合集

前言 本篇博客是spring相关的博客文章合集&#xff0c;内容涵盖Spring&#xff0c;SpringBoot&#xff0c;SpringCloud相关的知识&#xff0c;包括了基础的内容&#xff0c;比如核心容器&#xff0c;springMVC&#xff0c;Data Access&#xff1b;也包括Spring进阶的相关知识&…

免费的网页数据抓取工具有哪些?【2024附下载链接】

在网络上&#xff0c;有许多网页数据抓取工具可供选择。本文将探讨其如何全网采集数据并支持指定网站抓取。我们将比较不同的数据采集工具&#xff0c;帮助您找到最适合您需求的工具。 网页数据抓取工具种类 在选择网页数据抓取工具之前&#xff0c;让我们先了解一下这些工具…

[ 蓝桥杯Web真题 ]-布局切换

目录 介绍 准备 目标 规定 思路 解法参考 介绍 经常用手机购物的同学或许见过这种功能&#xff0c;在浏览商品列表的时候&#xff0c;我们通过点击一个小小的按钮图标&#xff0c;就能快速将数据列表在大图&#xff08;通常是两列&#xff09;和列表两种布局间来回切换。…

电机:有刷直流电机的原理

一、什么是有刷直流电机 直流有刷电机&#xff08;Brushed DC Motor&#xff09;&#xff0c;定子是用永磁铁或者线圈做成&#xff0c;以形成固定磁场。在定子一端上有固定碳刷&#xff0c;或者铜刷&#xff0c;负责把外部电流引入转子线圈。而转子是由线圈构成&#xff0c;线…

邮件营销软件:10个创新邮件营销策略,提升投资回报率(一)

电子商务和电子邮件营销密不可分。尽管电子商务在蓬勃发展&#xff0c;而很多人对邮件营销颇有微词。但是在电子商务中&#xff0c;邮件营销的确是一种有效营销方式。在本文中&#xff0c;我们将讨论一下邮件营销在电子商务中的有效运用&#xff0c;帮助您的企业在今年尽可能地…

2023-12-05 Qt学习总结6

点击 <C 语言编程核心突破> 快速C语言入门 Qt学习总结 前言十八 QMessageBox消息对话框十九 Qt布局管理总结 前言 要解决问题: 学习qt最核心知识, 多一个都不学. 十八 QMessageBox消息对话框 QMessageBox消息对话框是Qt中的一个提供用户交互界面的对话框窗口。 它通常…

MyBatis 四大核心组件之 ParameterHandler 源码解析

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

【图片版】计算机组成原理考前复习题【第2章 运算方法和运算器-1】

目录 前言 考前复习题&#xff08;必记&#xff09; 结尾 前言 在计算机组成原理的学习过程中&#xff0c;我们深入探索了计算机系统概述这一重要领域。计算机系统作为现代科技的核心&#xff0c;是整个计算机科学的基石。我们将学到的知识与理论转化为了能够解决现实问题的…

Python+unittest+requests接口自动化测试框架搭建 完整的框架搭建过程

首先配置好开发环境&#xff0c;下载安装Python并下载安装pycharm&#xff0c;在pycharm中创建项目功能目录。如果不会的可以百度Google一下&#xff0c;该内容网上的讲解还是比较多比较全的&#xff01; 大家可以先简单了解下该项目的目录结构介绍&#xff0c;后面会针对每个文…

docker 可视化工具操作说明 portainer

官网地址 https://docs.portainer.io/start/install-ce/server/docker/linux 1.First, create the volume that Port docker volume create portainer_data2.下载并安装容器 docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restartalways -v /var/run/docker…

PWN动态调试

这篇文章就是来教大家学习怎么动态调试的&#xff0c;然后我还写了一篇关于动态调试的文章&#xff0c;不是buu上面的题&#xff0c;就是两道简单的栈溢出问题&#xff0c;那两道题挺有特点的。大家可以去看看。 每日3道PWN之课外2道&#xff08;第2.5天&#xff09;-CSDN博客 …

性能监控体系:InfluxDB Grafana Prometheus

InfluxDB 简介 什么是 InfluxDB &#xff1f; InfluxDB 是一个由 InfluxData 开发的&#xff0c;开源的时序型数据库。它由 Go 语言写成&#xff0c;着力于高性能地查询与存储时序型数据。 InfluxDB 被广泛应用于存储系统的监控数据、IoT 行业的实时数据等场景。 可配合 Te…

SSD基础架构与NAND IO并发问题探讨

在我们的日常生活中&#xff0c;我们经常会遇到一些“快如闪电”的事物&#xff1a;比如那场突如其来的雨、那个突然出现在你眼前的前任、还有就是今天我们要聊的——固态硬盘&#xff08;SSD&#xff09;。 如果你是一个技术宅&#xff0c;或者对速度有着近乎偏执的追求&…

【Qt开发流程】之容器类1:介绍及常用容器类和使用Java风格迭代器进行遍历

概述 Qt库提供了一组通用的基于模板的容器类。这些类可用于存储指定类型的项。例如&#xff0c;如果需要一个可调整大小的QString数组&#xff0c;可以使用QVector<QString>。 这些容器类被设计成比STL容器更轻、更安全、更易于使用。如果不熟悉STL&#xff0c;或者更喜…

低多边形3D建模石头材质纹理贴图

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 当谈到游戏角色的3D模型风格时&#xff0c;有几种不同的风格&#xf…

云计算在计算机领域的应用与发展

云计算在计算机领域的应用与发展 一、引言 随着科技的不断发展&#xff0c;计算机领域已经成为当今社会最为活跃和创新的领域之一。云计算作为一种新兴的计算模式&#xff0c;已经在计算机领域中得到了广泛的应用&#xff0c;并且正在不断地推动着计算机领域的发展。本文将探…

Ultimate VFX

Ultimate VFX 构建套件:

【利用二手车数据进行可视化分析】

利用二手车数据进行可视化分析 查看原始数据去除重复数据需求分析1.统计全国总共有多少量二手车&#xff0c;用KPI图进行展示2.统计安徽总共有多少量二手车&#xff0c;用KPI图进行展示3.统计合肥总共有多少量二手车&#xff0c;用KPI图进行展示4.取最贵的10辆二手车信息&#…

web,Apache简述

一.HTTP请求访问的完整过程 1.建立连接 2.接收请求 3.处理请求 4.访问资源 服务器获取请求报文中请求的资源web服务器&#xff0c;即存放了web资源的服务器&#xff0c;负责向请求者提供对方请求的静态资源&#xff0c;或动态运行后生成的资源 静态资源&#xff1a;不需要…

C语言 内联函数 + 递归函数

函数分类 内联函数 1&#xff09;内联函数在编译时将函数的代码直接插入到调用它的地方&#xff0c;而不是通过函数调用的方式执行&#xff0c;从而减少了函数调用的开销&#xff0c;提高了代码的执行速度 2&#xff09;使用 inline 关键字来声明 3&#xff09;将函数声明为内联…