【深入理解SpringCloud微服务】深入理解nacos配置中心(三)——服务端启动与获取配置源码分析

【深入理解SpringCloud微服务】深入理解nacos配置中心(三)——服务端启动与获取配置源码分析

  • 原理回顾
    • 服务端启动
    • 获取配置
  • 源码分析
    • 服务端启动
      • ExternalDumpService#init()
      • ConfigCacheService#dump()
    • 获取配置

原理回顾

服务端启动

我们在《宏观理解nacos配置中心原理》的文章说到了,服务端启动的原理。

在这里插入图片描述

会调用DumpService查询MySQL,然后把查询到的配置信息dump到磁盘成为一个个的配置文件,每个DataId对应一个配置文件。

获取配置

然后服务端接收到获取配置文件的请求时,从磁盘中查询对应文件返回,而不是去查询数据库。

在这里插入图片描述

源码分析

服务端启动

ExternalDumpService#init()

我们以nacos配置的数据库是MySQL的情况为例子,DumpService的实现类就是ExternalDumpService。

nacos配置中心其实就是一个SpringBoot应用,它的启动就是SpringBoot启动。然后由于ExternalDumpService的init()方法被@PostConstruct注解修饰,因此在初始化ExternalDumpService时init()方法会被调用。

    @PostConstruct@Overrideprotected void init() throws Throwable {dumpOperate(processor, dumpAllProcessor, dumpAllBetaProcessor, dumpAllTagProcessor);}

在这里插入图片描述

    protected void dumpOperate(DumpProcessor processor, DumpAllProcessor dumpAllProcessor,DumpAllBetaProcessor dumpAllBetaProcessor, DumpAllTagProcessor dumpAllTagProcessor) throws NacosException {...dumpConfigInfo(dumpAllProcessor);...}
   private void dumpConfigInfo(DumpAllProcessor dumpAllProcessor) throws IOException {...dumpAllProcessor.process(new DumpAllTask());...}

在这里插入图片描述

经过一轮调用,进入到DumpAllProcessor#process方法。

    @Overridepublic boolean process(NacosTask task) {// 查询最大的id值long currentMaxId = persistService.findConfigMaxId();long lastMaxId = 0;while (lastMaxId < currentMaxId) {// 分页查询MySQLPage<ConfigInfoWrapper> page = persistService.findAllConfigInfoFragment(lastMaxId, PAGE_SIZE);if (page != null && page.getPageItems() != null && !page.getPageItems().isEmpty()) {for (ConfigInfoWrapper cf : page.getPageItems()) {long id = cf.getId();lastMaxId = Math.max(id, lastMaxId);...// 调用ConfigCacheService把查询到的每一条记录dump到磁盘成一个配置文件ConfigCacheService.dump(cf.getDataId(), cf.getGroup(), cf.getTenant(), cf.getContent(),cf.getLastModified(), cf.getType(), cf.getEncryptedDataKey());...}...}...}return true;}

在这里插入图片描述

ConfigCacheService#dump()

    public static boolean dump(String dataId, String group, String tenant, String content, long lastModifiedTs,String type, String encryptedDataKey) {// 根据dataId, group, tenant三元组算出一个groupKey(其实就是拼接)String groupKey = GroupKey2.getKey(dataId, group, tenant);...try {// 根据配置文件内容算出一个md5值final String md5 = MD5Utils.md5Hex(content, Constants.ENCODE);...// 把配置文件内容dump到磁盘成为一个配置文件DiskUtil.saveToDisk(dataId, group, tenant, content);}// 更新缓存中的md5值updateMd5(groupKey, md5, lastModifiedTs, encryptedDataKey);return true;} ...}

ConfigCacheService的dump方法首先根据配置文件内容算出一个md5值,然后把配置文件内容dump到磁盘成为一个配置文件,最后更新缓存中的md5值。

在这里插入图片描述

    public static void updateMd5(String groupKey, String md5, long lastModifiedTs, String encryptedDataKey) {// 从一个ConcurrentHashMap<String, CacheItem>中根据groupKey获取CacheItemCacheItem cache = makeSure(groupKey, encryptedDataKey, false);// 如果CacheItem等于空,或者CacheItem中的md5值与刚算出的md5值不匹配,则进入分支if (cache.md5 == null || !cache.md5.equals(md5)) {// 更新CacheItem的md5值cache.md5 = md5;cache.lastModifiedTs = lastModifiedTs;// 发布一个LocalDataChangeEvent事件,异步通知客户端NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey));}}

ConfigCacheService的updateMd5方法首先从从一个ConcurrentHashMap<String, CacheItem>中根据groupKey获取CacheItem,然后判断如果CacheItem等于空或者CacheItem中的md5值与刚算出的md5值不匹配则进入分支,由于是刚启动,因此CacheItem肯定等于空,所以会进入if分支。然后if分支中更新CacheItem的md5值,并发布一个发布一个LocalDataChangeEvent事件异步通知客户端。

在这里插入图片描述

这里NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey))发布的事件不是Spring的事件监听机制,而是nacos自己封装的事件监听机制。

获取配置

由于已经查询MySQL然后dump到磁盘成配置文件了,因此当接收到获取配置的RPC请求时,就不需要再去查询MySQL,而是读取磁盘的配置文件即可。

我们可以根据客户端发送GRPC远程调用时创建的request对象的类型,找到服务端处理该请求的Handler。我们在上一篇文章《客户端启动源码分析》中说到request请求对象的类型是ConfigQueryRequest。

通过ConfigQueryRequest,就可以找到处理获取配置请求的方法在ConfigQueryRequestHandler的handle方法。

    public ConfigQueryResponse handle(ConfigQueryRequest request, RequestMeta meta) throws NacosException {try {return getContext(request, meta, request.isNotify());} catch (...) {...}}

ConfigQueryRequestHandler的handle方法调用getContext方法。

在这里插入图片描述

    private ConfigQueryResponse getContext(ConfigQueryRequest configQueryRequest, RequestMeta meta, boolean notify)throws UnsupportedEncodingException {...// 从磁盘根据dataId, group, tenant三元组读取配置文件file = DiskUtil.targetFile(dataId, group, tenant);...// 读取配置文件中的内容,设置到response对象中content = readFileContent(file);response.setContent(content);...return response;}

在这里插入图片描述


http://www.ppmy.cn/devtools/108842.html

相关文章

3.比 HTTP 更安全的 HTTPS(工作原理理解、非对称加密理解、证书理解)

所谓的协议 协议只是一种规则&#xff0c;你不按规则来就无法和目标方进行你的工作 协议说白了只是人定的规则&#xff0c;任何人都可以定协议 我们不需要太了解细节&#xff0c;这些制定和完善协议的人去做的&#xff0c;我们只需要知道协议的一个大概 HTTPS 协议 1、概述…

PPPoE配置学习笔记

企业内网和运营商网络如上图所示&#xff0c;中间交换机模拟运营商传输设备。公网IP段&#xff1a;12.1.1.0/24。内网IP段&#xff1a;192.168.1.0/24。PPPoE拨号采用CHAP认证&#xff0c;用户名&#xff1a;admin 密码&#xff1a;admin123 实验要求&#xff1a; 将R1设置为…

探究零工市场小程序如何改变传统兼职模式

近年来&#xff0c;零工市场小程序正逐渐改变传统的兼职模式&#xff0c;为求职者和雇主提供了一个更为高效、便捷的平台。本文将深入探讨零工市场小程序如何影响传统兼职模式&#xff0c;以及它带来的优势和挑战。 一、背景与挑战 传统的兼职市场往往存在信息不对称的问题&am…

SQL COUNT() 函数深入解析

SQL COUNT() 函数深入解析 SQL&#xff08;Structured Query Language&#xff09;是一种用于管理关系数据库管理系统&#xff08;RDBMS&#xff09;的标准编程语言。在SQL中&#xff0c;COUNT() 函数是一个常用的聚合函数&#xff0c;用于计算数据表中的行数或特定列的值数量…

PMP–冲刺–十大领域易考点三大项目流程敏捷中的角色职责与3个工件高频考点考试技巧–名词解析版

文章目录 技巧PMBOK易考点--题干关键词一、引论二、项目运行环境三、项目经理的角色四、整合管理五、范围管理六、进度管理七、成本管理八、质量管理九、资源管理十、沟通管理十一、风险管理十二、采购管理十三、干系人管理 考试中的三大项目流程一 、变更流程二 、风险流程三 …

如何保护服务器免受恶意软件攻击?

了解如何保护服务器免受恶意软件的侵害一直是管理员关注的问题。各种恶意软件带来的威胁已经存在了几十年&#xff0c;早在 1949 年的一篇关于自我复制计算机程序的理论科学论文中就对其进行了讨论。自 20 世纪 70 年代初的实验性病毒以来&#xff0c;恶意软件一直是一种不断发…

八、Maven总结

1.为什么要学习Maven&#xff1f; 2.Maven 也可以配华为云和腾讯云等。 3.IDEA整合Maven 4.IDEA基于Maven进行工程的构建 5.基于Maven进行依赖管理&#xff08;重点&#xff09; 6. Maven的依赖传递和依赖冲突 7. Maven工程继承和聚合 8.仓库及查找顺序

【2024数模国赛赛题思路公开】国赛C题第二套思路丨附可运行代码丨无偿自提

2024年国赛C题第二套解题思路 第一问&#xff1a;2024~2030年农作物的最优种植方案 【问题分析】 题目要求为某乡村在2024~2030年制定农作物的最优种植方案&#xff0c;目的是最大化收益&#xff0c;并需考虑两种销售情况&#xff1a; 1. 超过预期销售量的部分滞销&#xff0…

【MacOS】mac定位服务中删除已经卸载的软件

mac定位服务中删除已经卸载的软件 网上的帖子真不靠谱 直接右键 WeTypeSettings &#xff0c;查找位置&#xff0c;丢废纸篓即可&#xff01;会提示你卸载的&#xff01;

未来出行:高效智能的汽车充电桩

解析高效智能的汽车充电桩的结构设计技术要求 充电桩按照充电方式分为交流充电桩与直流充电桩、交直流一体充电桩三种。直流充电桩一般安装在高速公路&#xff0c;充电站等地&#xff1b;交流充电桩一般安装在小区、停车场、道路停车位、高速公路服务区等位置。根据国网Q/GDW4…

【爬虫软件】小红薯评论区采集工具

一、采集目标与应用场景 您好&#xff01;我利用Python技术自主研发了一款高效的爬虫软件&#xff0c;批量收集小红薯平台上的评论&#xff0c;包括主评论及其下的二级评论。 为了拓宽用户群体&#xff0c;让不具备编程基础的小白用户也能轻松上手&#xff0c;我开发成了界面…

spring中添加@Test注解测试

1、添加maven依赖 <!-- 添加test方便测试--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><dependency><grou…

TCP/IP协议栈详解及其在现代网络中的应用

在当今数字化时代&#xff0c;网络已成为我们生活中不可或缺的一部分。无论是社交、工作还是娱乐&#xff0c;网络都在背后发挥着至关重要的作用。而这一切的实现&#xff0c;都离不开TCP/IP协议栈。本文将详细介绍TCP/IP协议栈的结构、各层功能以及它在现代网络中的应用。 什…

http和https区别

HTTP&#xff08;超文本传输协议&#xff09;和 HTTPS&#xff08;安全超文本传输协议&#xff09;是用于在互联网上传输数据的协议。它们之间的主要区别在于安全性&#xff1a; HTTP&#xff08;Hypertext Transfer Protocol&#xff09;: 加密: HTTP 不对传输的数据进行加密&…

数学建模强化宝典(8)粒子群算法

前言 粒子群算法&#xff08;Particle Swarm Optimization, PSO&#xff09;是一种基于群体智能的优化算法&#xff0c;它源于对鸟群捕食行为的研究。通过模拟鸟群中的个体相互协作和信息共享来寻找最优解&#xff0c;粒子群算法已被广泛应用于函数优化、神经网络训练、模糊系统…

Matlab simulink建模与仿真 第七章(表查询库)

参考视频&#xff1a;simulink1.1simulink简介_哔哩哔哩_bilibili 一、表查询库中的模块概览 二、表查询模块 使用Lookup Table表查询模块&#xff0c;需要在配置窗口中建立x-y&#xff08;自变量-因变量&#xff09;离散数据对&#xff0c;x与y的维数应相同&#xff0c;x集&a…

使用debugfs

在前面,我们学习到了sysctl这一基于sysfs和seq_file这一基于procfs文件系统进行交互数据的方式,其中procfs主要是针对进程属性,而sysfs是针对内核模型的,为了保证其稳健,我们很少拿来作为调试时数据交换使用,显然printk也满足不了,那么debugfs就应运而生了。一般发行版系…

Kafka【六】Linux下安装Kafka(Zookeeper)集群

Kafka从早期的消息传输系统转型为开源分布式事件流处理平台系统&#xff0c;所以很多核心组件&#xff0c;核心操作都是基于分布式多节点的。本文这里采用三台虚拟机模拟真实物理主机搭建Zookeeper集群和kafka集群。 VMware可以使用户在一台计算机上同时运行多个操作系统&…

掌握Hive函数[1]:从基础到高级应用

目录 函数简介 单行函数 算术运算函数 数值函数 字符串函数 日期函数 流程控制函数 集合函数 案例演示 函数简介 Hive将常用的逻辑封装成函数供用户使用&#xff0c;类似于Java中的函数。这样做的好处是可以避免用户反复编写相同的逻辑代码&#xff0c;可以直接调用这些函数。…

【Flutter】Flutter安装和配置(mac)

1、准备工作 升级Macos系统为最新系统安装最新的Xcode电脑上面需要安装brew https://brew.sh/安装chrome浏览器&#xff08;开发web用&#xff09; 2.、下载flutter https://docs.flutter.dev/release/archive?tabmacos 大家网页后&#xff0c;选择对应的版本【Tips&#x…