发布订阅模式如何实现,发布订阅与观察者模式区别

发布订阅模式是一种通过中间代理层彻底解耦消息发送者和接收者的设计模式,广泛应用在事件驱动架构和消息队列系统中,能显著提升系统的灵活性和可扩展性。

发布订阅模式是什么?和观察者模式对比有什么不同?

很多人把发布订阅模式和观察者模式混为一谈,但它们在使用场景和耦合度上差异明显,发布订阅模式的核心是引入一个事件通道或消息代理,发布者不直接发送消息给订阅者,而是将消息发布到通道,由通道负责路由给所有订阅该主题的接收者,订阅者也不需要知道发布者的存在,只需声明自己感兴趣的主题即可。

「观察者模式」与「发布/订阅模式」,你分得清楚吗?
加载中
「观察者模式」与「发布/订阅模式」,你分得清楚吗?

观察者模式与发布订阅模式的本质区别

观察者模式中,被观察者直接持有观察者的引用,当状态变化时遍历调用通知,这种设计是直接通知,两者之间仍然存在依赖,而发布订阅模式完全切断这种依赖,双方都只与代理交互。

特性 观察者模式 发布订阅模式
耦合度 发布者知道订阅者,订阅者知道发布者 发布者和订阅者完全不知道彼此
通信方式 直接调用 通过消息代理异步传递
扩展性 随着订阅者增多,发布者修改压力大 发布者无感知,代理可水平扩展
典型实现 事件监听(如Java的Observable) 消息队列(如RabbitMQ、Kafka)

从实际项目选型来看,如果你只是需要单个对象内部的状态广播,观察者模式就够用了,但一旦涉及分布式系统、跨服务通信或者需要高吞吐量和异步处理,发布订阅模式是更稳妥的选择,业内专家指出,在微服务架构中,超过80%的异步通信场景都会选择基于发布订阅模式的消息中间件来降低服务间的直接耦合。

发布订阅模式的工作原理拆解

发布订阅模式包含三个角色:发布者、代理、订阅者,发布者产生消息,定义好主题标签;代理维护主题与订阅者的映射关系,并负责消息的存储和转发;订阅者预先注册自己感兴趣的主题,当消息到达时收到通知,整个过程是异步的,发布者不需要等待订阅者处理完成,订阅者也可以在不同时间消费消息,这种设计让系统更容易应对突发流量,因为代理可以缓存消息,等订阅者空闲时再推送。

发布订阅模式如何实现,发布订阅与观察者模式区别

发布订阅模式使用场景有哪些?实际项目怎么选?

发布订阅模式的使用场景非常广泛,从前端交互到后端数据流都能见到它的身影,选择它而不是其他模式,通常是因为系统需要应对动态变化的订阅关系、异步处理以及跨模块通信。

典型场景:事件驱动与消息队列

  • 前端事件系统:浏览器中的DOM事件机制就是典型的发布订阅模式,用户点击按钮时,浏览器自动触发事件,所有注册的处理函数依次执行,元素之间没有直接耦合。
  • 微服务异步通信:订单服务创建订单后,通过消息队列发布“订单已创建”事件,库存服务、通知服务、积分服务各自订阅该事件并执行后续操作,服务间不需要知道彼此的地址和接口,只需要约定好消息格式。
  • 日志收集与监控:各个服务将日志发布到统一主题,日志收集系统作为订阅者实时获取并聚合分析,避免直接写入文件导致的性能瓶颈。
  • 实时数据推送:股票行情、社交动态等需要实时更新的场景,服务器将变化数据推送到消息通道,客户端通过长连接订阅并更新界面。

根据项目规模选择实现方式

如果你在单体应用或小型项目中实现发布订阅模式,可以自己编写一个轻量级的事件总线,使用内存队列和回调函数即可,但一旦系统涉及跨进程、跨网络通信,就需要引入成熟的消息中间件,行业共识认为,RabbitMQ适合中小规模、需要灵活路由的场景,Kafka更适合高吞吐、日志场景,而Redis的Pub/Sub功能则适合快速搭建原型或低延迟透传,选择时不必纠结于“哪个最好”,而是看你的业务对消息持久化、消费顺序、吞吐量的要求,如果消息丢失会导致严重问题,就应该选择支持持久化的消息队列,而不是简单的内存队列。

发布订阅模式的优缺点分析

多数情况下,发布订阅模式能带来架构上的灵活性,但也会引入额外的复杂性,了解这些权衡,才能决定是否在项目中采用。

核心优势

  • 完全解耦

    发布订阅模式如何实现,发布订阅与观察者模式区别

    :发布者和订阅者不直接依赖,可以独立开发、部署和扩展,新增一个订阅者只需要注册新服务,不需要修改发布者代码。

  • 异步处理提升响应速度:发布者发送消息后立即返回,后续处理由订阅者异步完成,前台请求的响应时间大幅缩短。
  • 支持一对多广播:一条消息可以被多个订阅者同时消费,无需发布者重复发送,这在通知、日志等场景中非常高效。
  • 扩展性好:代理可以独立扩展,支持水平分片来提高吞吐量,发布者无须感知负载变化。

潜在问题

  • 消息可能丢失:如果代理宕机或订阅者处理失败,消息可能丢失,需要引入确认机制和重试策略。
  • 调试和追踪困难:消息流不再靠代码调用链,而是通过代理传递,出现问题时很难定位是发布者、代理还是订阅者的问题。
  • 消息顺序性难保证:在分布式环境下,消息到达顺序可能和发送顺序不一致,对顺序敏感的业务需要额外处理。
  • 系统复杂度增加:引入消息代理意味着多了一个维护点,需要处理网络延迟、消息积压等问题。

从实际项目经验看,发布订阅模式更适合业务逻辑相对独立、不需要强一致性的场景,如果系统要求实时强一致,比如金融交易,直接使用发布订阅模式可能会带来风险,通常需要结合分布式事务或最终一致性方案。

发布订阅模式实例:实现一个简单的发布订阅系统

理解概念最好的方式是自己动手实现一个最小版本,这里我们用伪代码演示核心逻辑,关键步骤拆解如下:

核心组件:事件总线

  1. 定义事件通道对象:用于存储主题和订阅者列表的映射关系。
  2. 实现订阅方法:接收主题和回调函数,将回调函数添加到对应主题的队列中。
  3. 实现发布方法:接收主题和消息数据,遍历该主题的所有订阅者,逐个调用回调函数,可异步执行。
  4. 实现取消订阅方法:从主题列表中移除指定的回调函数,避免内存泄漏。

操作路径

  • 初始化:创建一个空对象 events = {}。
  • 订阅:subscribe(topic, callback) →

    发布订阅模式如何实现,发布订阅与观察者模式区别

    events[topic] 不存在,则初始化为空数组,然后将 callback 加入数组。

  • 发布:publish(topic, data) → 获取 events[topic],遍历数组,对每个 callback 执行 callback(data)(可包裹在 setTimeout 或 Promise 中实现异步)。
  • 取消订阅:unsubscribe(topic, callback) → 过滤掉数组中的该回调。

实际项目中的注意事项

  • 避免回调地狱:在发布订阅中使用异步回调时,要注意控制并发,避免回调嵌套过深,可以使用 async/await 或消息队列的中间件机制。
  • 内存管理:订阅者不再需要时一定要取消订阅,否则会形成闭包引用,导致内存泄漏,在组件销毁或服务关闭时,主动清理注册的订阅。
  • 错误隔离:单个订阅者的回调异常不应影响其他订阅者,应该用 try...catch 包裹每个回调的调用,避免整个发布过程崩溃。

发布订阅模式常见问题

发布订阅模式如何保证消息不丢失?

消息丢失通常发生在三个环节:发布者到代理的传输、代理内部存储、代理到订阅者的传输,在发布者端,使用消息确认机制(如RabbitMQ的发布确认)确保消息被代理接收,在代理端,开启持久化,将消息写入磁盘,即使宕机也能恢复,在订阅者端,手动确认消费成功后再通知代理删除消息,如果处理失败,消息会重新入队,这样三层保障下,消息丢失概率极低。

发布订阅模式适合所有场景吗?

不是,如果系统内模块依赖关系简单,且消息量不大,直接调用或观察者模式更轻量,引入发布订阅会过度设计,对实时性要求极高且需要严格顺序的场景,比如实时交易撮合,发布订阅的异步特性可能引入延迟和乱序,此时需要更复杂的控制机制。

发布订阅模式实现时需要注意哪些性能问题?

主要关注消息积压和回调执行效率,代理的消费能力如果跟不上发布速度,消息会积压,导致内存或磁盘爆满,需要设置合理的队列长度和限流策略,订阅者回调应尽量异步且轻量,避免在回调中执行耗时操作,否则会阻塞后续消息的消费,如果订阅者数量巨大,考虑使用线程池或并发消费模型,同时监控代理的吞吐量指标,及时扩容。

首发原创文章,作者:王坚‌,如若转载,请注明出处:https://idctop.com/article/588131.html

赞 (0)
我的世界2b2t服务器外挂怎么用?,2b2t外挂哪个好用?
上一篇 2026年8月21日 02:20
如何正确发送蓝牙数据和多媒体数据,有哪些方法?
下一篇 2026年8月21日 02:21

相关推荐

  • 如何设置ftp服务器文件索引?,常见问题有哪些?

    建立一个高效的FTP服务器文件索引,核心在于选择适合的索引方案并配合定期维护,这能让你在数十万文件中秒级定位目标,为什么需要为FTP服务器建立文件索引当FTP服务器上的目录结构逐渐膨胀,文件数量突破万级,靠手动翻找或依赖系统自带的列表功能会变得异常低效,文件索引的作用就是预先扫描并组织文件元数据,形成一份可快速……

    2026年7月21日
    2200
  • Android开发Cocos2dx怎么搭建环境,详细配置教程步骤

    在移动游戏开发领域,将 Cocos2d-x 引擎与 Android 原生层深度结合是构建高性能、跨平台游戏的关键路径,核心结论在于:成功的集成必须建立在稳健的 JNI 通信机制、精确的生命周期同步以及高度优化的构建配置之上,只有处理好这三者,才能确保游戏在复杂的 Android 碎片化环境中保持流畅与稳定,避免……

    2026年2月20日
    14100
  • 培训与开发的内容有哪些?企业员工培训课程详解

    企业培训与开发的终极目标并非单纯的知识灌输,而是构建可持续的人才供应链,将员工能力转化为企业的核心竞争力,一个科学完善的培训体系,必须精准对接企业战略,覆盖从新员工融入 to 高层领导力提升的全周期,实现组织绩效与个人成长的双赢,核心在于建立“需求分析-计划制定-实施交付-效果评估”的闭环系统,确保每一分投入都……

    2026年3月30日
    11600
  • 2026有哪些值得参加的iOS开发者大会?苹果WWDC领衔推荐

    iOS开发者大会是苹果公司每年举办的全球开发者盛会,官方名称为WWDC(Worldwide Developers Conference),它为iOS开发者提供前沿技术更新、工具发布和社区交流平台,通过参与此类大会,开发者能加速技能提升,优化应用开发流程,并融入苹果生态系统,什么是iOS开发者大会的核心价值iOS……

    2026年2月8日
    22110
  • 技术支持转开发难吗?技术支持转开发的最佳路径

    技术支持转开发并非简单的岗位跳槽,而是一场基于业务理解优势的职业升维,成功的关键在于将“被动解决问题”的经验转化为“主动构建系统”的能力,核心路径在于补齐计算机基础短板、建立工程化思维以及构建可展示的项目作品集,这一转型过程虽然充满挑战,但技术支持人员独有的沟通能力和对业务逻辑的深刻洞察,往往能使其成为更懂业务……

    2026年3月20日
    15000
  • 上海电影节舆情监测怎么做?上海电影节舆情监测平台

    关于上海电影节的舆情监测随着上海国际电影节的日益国际化与数字化,其产生的海量数据——包括社交媒体讨论、新闻媒体报道、用户评论及实时搜索趋势——已成为城市文化形象管理与商业决策的核心资产,面对这一高并发、高实时性且非结构化特征显著的数据洪流,传统的服务器架构往往面临响应延迟、数据丢失或分析维度单一的挑战,构建一套……

    2026年6月10日
    4500
  • 委托开发的软件著作权归谁?委托开发成果归属权如何约定

    程序开发中的核心基石与实战指南在程序开发项目中,委托开发(如外包合作)时,明确知识产权的归属权是项目成功的决定性因素,它能预防法律纠纷,保护创新成果,并确保委托方和开发方的长期利益,本文基于行业实践,深入解析委托开发归属的关键要素,提供专业解决方案,助您高效管理开发流程,什么是委托开发归属?委托开发归属指在软件……

    2026年2月15日
    25000
  • 树莓派开发环境怎么搭建?新手入门配置教程

    构建高效稳定的树莓派开发环境,核心在于精准匹配硬件性能与软件需求,并通过远程开发模式实现“无头”操作的高效流转,一个成熟的开发环境不应局限于单板机本身的性能挖掘,更在于构建一套能够解耦编辑、编译与运行的标准化工作流,从而在资源受限的嵌入式平台上实现接近桌面级开发体验的效率, 硬件选型与基础系统配置:构建稳固的地……

    2026年3月13日
    14300
  • 云主机是什么?云主机和虚拟主机的区别

    关于云主机的ppt在数字化转型的浪潮中,云计算已成为企业基础设施的核心支柱,对于IT决策者、开发者及中小企业而言,选择一款稳定、高效且具备高性价比的云主机,是保障业务连续性与数据安全的关键,本文基于深度实测数据与行业基准测试,对当前主流云主机产品进行全方位解析,旨在为读者提供客观、专业的选型参考, 核心性能实测……

    2026年6月10日
    3400
  • 虚拟机亮度怎么调,vmware屏幕太暗怎么办

    VM虚拟机亮度调节的核心答案很简单:先装好VMware Tools,再检查显卡驱动和显示设置,绝大多数亮度问题都能解决,如果你在虚拟机里发现屏幕暗得看不清、调亮度没反应,或者画面发灰发白,别急着怪显示器,先跟着下面这几个模块排查,基本都能搞定,vm虚拟机亮度怎么调?先解决驱动这个拦路虎虚拟机里的“亮度调节”和物……

    2026年9月2日
    300

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注