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

devtools/2025/1/15 22:41:05/

【深入理解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…