[Java微服务组件]注册中心P3-Nacos中的设计模式1-观察者模式

在P1-简单注册中心实现和P2-Nacos解析中,我们分别实现了简单的注册中心并总结了Nacos的一些设计。
本篇继续看Nacos源码,了解一下Nacos中的设计模式。

目录

  • Nacos 观察者模式 Observer Pattern
  • 观察者模式总结

Nacos 观察者模式 Observer Pattern

模式定义:观察者模式是一种行为型模式,定义对象间一对多依赖,确保当一个对象变化时,其依赖对象也会被通知并自动更新。

在配置管理中,客户端 (ConfigService) 注册监听器 (Listener) 来监听特定 dataId 和 group 的配置变更。当 Nacos Server 上的配置发生变化时,会通知所有监听该配置的客户端。
在服务发现中,客户端 (NamingService) 订阅 (subscribe) 特定服务名。当该服务的实例列表(上线、下线、状态变更)发生变化时,Nacos Server 会将最新的服务实例列表推送给所有订阅的客户端。
这种推送机制和探测机制不一样,是不区分服务实例是持久化(persistent)还是临时(ephemeral)实例的,都会触发通知。

下面是简单的模拟:

// 观察者接口 (Nacos 客户端 Listener)
public interface ConfigObserver {void onConfigChange(String dataId, String group, String newContent);
}
// 被观察者 (Nacos 配置中心)
public class ConfigSubject {private Map<String, List<ConfigObserver>> observers = new HashMap<>();private Map<String, String> configStore = new HashMap<>(); // 模拟配置存储private String getConfigKey(String dataId, String group) {return dataId + "@" + group;}// 注册观察者 (客户端添加 Listener)public void addObserver(String dataId, String group, ConfigObserver observer) {String key = getConfigKey(dataId, group);observers.computeIfAbsent(key, k -> new ArrayList<>()).add(observer);System.out.println("Observer added for: " + key);// 首次添加时,可以考虑推送当前配置String currentContent = configStore.getOrDefault(key, null);if (currentContent != null) {observer.onConfigChange(dataId, group, currentContent);}}// 移除观察者public void removeObserver(String dataId, String group, ConfigObserver observer) {String key = getConfigKey(dataId, group);List<ConfigObserver> observerList = observers.get(key);if (observerList != null) {observerList.remove(observer);System.out.println("Observer removed for: " + key);}}// 发布配置 (模拟配置变更)public void publishConfig(String dataId, String group, String content) {String key = getConfigKey(dataId, group);System.out.println("Publishing config for " + key + ": " + content);configStore.put(key, content);notifyObservers(dataId, group, content);}// 通知观察者private void notifyObservers(String dataId, String group, String newContent) {String key = getConfigKey(dataId, group);List<ConfigObserver> observerList = observers.get(key);if (observerList != null && !observerList.isEmpty()) {System.out.println("Notifying " + observerList.size() + " observers for " + key);// 创建副本以防并发修改List<ConfigObserver> observersToNotify = new ArrayList<>(observerList);for (ConfigObserver observer : observersToNotify) {try {observer.onConfigChange(dataId, group, newContent);} catch (Exception e) {System.err.println("Error notifying observer: " + e.getMessage());}}}}
}
// 具体观察者实现 (客户端应用中的监听器)
public class MyConfigListener implements ConfigObserver {private String listenerName;public MyConfigListener(String name) {this.listenerName = name;}@Overridepublic void onConfigChange(String dataId, String group, String newContent) {System.out.println("[" + listenerName + "] Received config change: DataId=" + dataId + ", Group=" + group + ", Content=" + newContent);// 在这里处理配置变更逻辑,例如更新应用内部状态}
}
// --- Demo Main ---
public class ObserverDemo {public static void main(String[] args) {ConfigSubject configCenter = new ConfigSubject();MyConfigListener listener1 = new MyConfigListener("App1-Listener");MyConfigListener listener2 = new MyConfigListener("App2-Listener");// App1 和 App2 都监听同一个配置configCenter.addObserver("app.properties", "DEFAULT_GROUP", listener1);configCenter.addObserver("app.properties", "DEFAULT_GROUP", listener2);System.out.println("\n--- Publishing first config ---");configCenter.publishConfig("app.properties", "DEFAULT_GROUP", "database.url=jdbc:mysql://localhost:3306/mydb");System.out.println("\n--- Publishing updated config ---");configCenter.publishConfig("app.properties", "DEFAULT_GROUP", "database.url=jdbc:mysql://remote:3306/prod_db");System.out.println("\n--- App1 stops listening ---");configCenter.removeObserver("app.properties", "DEFAULT_GROUP", listener1);System.out.println("\n--- Publishing final config ---");configCenter.publishConfig("app.properties", "DEFAULT_GROUP", "database.url=jdbc:mysql://new_remote:3306/final_db");}
}

Nacos源码(用的是nacos2.1.1版本源码,可以在release中下载)位置如下:

  • 配置监听
    客户端接口: com.alibaba.nacos.api.config.ConfigService#addListener
    客户端监听器接口: com.alibaba.nacos.api.config.listener.Listener
    客户端内部实现: com.alibaba.nacos.client.config.NacosConfigService, com.alibaba.nacos.client.config.impl.ClientWorker (处理长轮询和回调)
    服务端通知逻辑: com.alibaba.nacos.config.server.service.LongPollingService, com.alibaba.nacos.config.server.utils.ConfigExecutor (处理配置变更事件和推送)

  • 服务订阅
    客户端接口: com.alibaba.nacos.api.naming.NamingService#subscribe
    客户端监听器接口: com.alibaba.nacos.api.naming.listener.EventListener
    客户端内部实现: com.alibaba.nacos.client.naming.NacosNamingService, com.alibaba.nacos.client.naming.core.ServiceInfoUpdater
    服务端推送逻辑: com.alibaba.nacos.naming.push.PushService, com.alibaba.nacos.naming.core.Service (管理服务实例变更并触发推送)

观察者模式总结

通过Nacos的案例,我们可以简单总结出观察者模式的特点,如下图:
![[Pasted image 20250419152551.png]]

其中,被观察的通知动作可以是异步业可以是同步,观察者收到通知后,可以决定是否告知已接收还是或是不告知。
上面的类图只是用于简单理解。出于单一职责原则与低耦合、可扩展设计等考虑,观察者模式可以做出如下抽象:
被观察者(主题 Subject)、观察者(Observer)

![[Pasted image 20250419153013.png]]

将观察者被和被观察主要功能抽象成接口。

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

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

相关文章

电脑 访问 github提示 找不到网页,处理方案

1、找到 本机的 host文件 例如 windows 的 一般在 C:\Windows\System32\drivers\etc\hosts 用管理员身份打开 hosts 文件 如果文件中没有 github的配置&#xff0c;需要自己手动添加上去&#xff1b; 如果有&#xff0c;则需要 检查 github.com 与 github.global.ssl.fastly.…

Linux系统中的网络管理

1.RHEL9版本中&#xff0c;使用nm进行网络配置&#xff0c;ifcfg不再是网络配置文件的主存储&#xff0c;样式仍然可用&#xff0c;但它不再是NetworkManger存储新网络配置文件的默认位置&#xff0c;RHEL以key-file格式在etc/NetworkManger/system-connections/中存储新的网络…

AI技术深度解析:从移动芯片到AIoT的全面突破

作为全球无线通信技术和半导体解决方案的重要参与者,高通始终将技术创新作为核心驱动力,在移动通信、物联网(IoT)、汽车电子、AI计算等领域占据关键地位。本文将从其核心产品线、技术突破、应用场景及未来布局四个维度,客观解析高通的技术积累与行业角色。 一、核心产品线…

使用CS Roofline Toolkit测量带宽

使用CS Roofline Toolkit测量带宽 工程下载&#xff1a;使用CS Roofline Toolkit测量带宽-案例工程文件&#xff0c;也可以按照下面的说明使用git clone下载 目录 使用CS Roofline Toolkit测量带宽0、Roofline模型理解1、CS Roofline Toolkit下载1.1、设置代理1.2、git clone下…

EAGLE代码研读+模型复现

要对代码下手了&#xff0c;加油(ง •_•)ง 作者在他们自己的设备上展现了推理的评估结果&#xff0c;受第三方评估认证&#xff0c;EAGLE为目前最快的投机方法&#xff08;虽然加速度是评估投机解码方法的主要指标&#xff0c;但其他点也值得关注。比如PLD和Lookahead无需额…

基于SFC的windows修复程序,修复绝大部分系统损坏

效果:可以自动修复大部分由系统文件损坏而导致的错误 例如:系统应用无法打开 系统窗口(例如开始菜单)无法使用 电脑蓝屏或者卡死.....文章 01技术背景 Windows自带了一个SFC命令行应用程序,可以检查大部分的系统文件错误,以及复这些文件 其中自动检查所有系统文件&#x…

liunx日志问题

一、日志定向 Linux 系统的日志配置文件&#xff08;如/etc/syslog.conf或/etc/rsyslog.conf &#xff09;中&#xff0c;用于定义系统日志的记录规则&#xff0c;决定哪些类型的日志消息会被记录到特定的日志文件中。 *.info;mail.none;authpriv.none;cron.none /va…

2.凸包优化求解

1.减而治之(Decrease and Conquer) 插入排序 典型的减而治之算法就是插入排序方法 插入排序法: 在未排序中选择一个元素&#xff0c;插入到已经排序号的序列中 将凸包也采用减而治之的方法 2.In-Convex-Polygon Test 怎么判断引入的极点存在于多边形里面还是外面&#xff1…

系统思考:危机中的转型机遇

“危机不仅是挑战&#xff0c;更是转型的机会” 每当大事发生&#xff0c;很多企业老板常常被眼前的困境压得喘不过气&#xff0c;焦虑与压力让人难以思考长远。特别是在危机面前&#xff0c;大家忙于应对眼前的风险&#xff0c;却忽略了背后隐藏的机遇。而危机&#xff0c;恰…

大模型Rag - 如何评估Rag

一.RAG流程与评估标准补充 RAG&#xff08;Retrieval-Augmented Generation&#xff09;是一种结合检索与生成的问答架构。为了确保系统效果&#xff0c;需要从以下三个角度对其评估&#xff1a; 回顾RAG流程 用户提出问题 → 系统检索相关上下文 → 基于上下文由大语言模型…

Linux RT RT RT

RT的最终目的是尽可能多的让原来系統不可抢占的部分变成可抢占&#xff0c;让高优先级的程序先跑。这里的rt引入了一个deadline的说法&#xff0c;此时的实时性是保证在最大一个时间间隔内&#xff0c;程序被执行。比如每100ms算法做一次决策。 所以此时面临着几座大山…

演员柳琦正式加入创星演员出道计划,开创演艺事业新天地

4月18日&#xff0c;演员柳琦正式加入“创星演员出道计划”&#xff0c;不仅得到参演都市爱情喜剧《和我结婚吧》角色的机会&#xff0c;还获得文旅精品网剧《醉梦灵州》的出演机会&#xff0c;自此开启全新影视之路。对表演艺术极具天赋的柳琦&#xff0c;相信未来可以凭借自身…

16.Chromium指纹浏览器开发教程之WebGPU指纹定制

WebGPU指纹概述 WebGPU是下一代的Web图形和计算API&#xff0c;旨在提供高性能的图形渲染和计算能力。它是WebGL的后继者&#xff0c;旨在利用现代GPU的强大功能&#xff0c;使得Web应用能够实现接近原生应用的图形和计算性能。而且它是一个低级别的API&#xff0c;可以直接与…

HTTP:九.WEB机器人

概念 Web机器人是能够在无需人类干预的情况下自动进行一系列Web事务处理的软件程序。人们根据这些机器人探查web站点的方式,形象的给它们取了一个饱含特色的名字,比如“爬虫”、“蜘蛛”、“蠕虫”以及“机器人”等!爬虫概述 网络爬虫(英语:web crawler),也叫网络蜘蛛(…

Vue3+TS中svg图标的使用

安装依赖 pnpm i vite-plugin-svg-icons -D配置引入 vite.config.ts ... import { createSvgIconsPlugin } from vite-plugin-svg-icons import path from node:pathconst svgIconsPlugin createSvgIconsPlugin({iconDirs: [path.resolve(process.cwd(), src/assets/icons)]…

【java实现+4种变体完整例子】排序算法中【堆排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格

以下是堆排序的详细解析&#xff0c;包含基础实现、常见变体的完整代码示例&#xff0c;以及各变体的对比表格&#xff1a; 一、堆排序基础实现 原理 基于二叉堆结构&#xff08;最大堆&#xff09;&#xff0c;通过以下步骤实现排序&#xff1a; 构建最大堆&#xff1a;将…

论文阅读笔记:Generative Modeling by Estimating Gradients of the Data Distribution

1、参考来源 论文《Generative Modeling by Estimating Gradients of the Data Distribution》 来源&#xff1a;NeurIPS 2019 论文链接&#xff1a;https://arxiv.org/abs/1907.05600 参考链接&#xff1a; 【AI知识分享】真正搞懂扩散模型Score Matching一定要理解的三大核心…

Kubernetes相关的名词解释CNI插件(1)

&#xff08;一&#xff09;什么是CNI插件&#xff1f; 在 Kubernetes 中&#xff0c;CNI 插件&#xff08;Container Network Interface Plugin&#xff09; 是一种用于配置容器网络接口的标准工具&#xff0c;负责为 Pod 分配网络资源&#xff08;如 IP 地址&#xff09;并建…

2021-11-10 C++蜗牛爬井进3退1求天数

缘由C大一编程题目。-编程语言-CSDN问答 int n 0, t 0;cin >> n;while ((n - 3)>0)n, t;cout << t << endl;

分享一个DeepSeek+自建知识库实现人工智能,智能回答高级用法。

这个是我自己搞的DeepSeek大模型自建知识库相结合到一起实现了更强大的回答问题能力还有智能资源推荐等功能。如果感兴趣的小伙伴可以联系进行聊聊&#xff0c;这个成品已经有了实现了&#xff0c;所以可以融入到你的项目&#xff0c;或者毕设什么的还可以去参加比赛等等。 1.项…