设计心得——发布订阅

news/2025/4/1 3:47:51/

一、发布/订阅

发布/订阅(Pub/Sub)方式,在互联网中应用是极其广泛的,可以不负责任的说,只要上过网就用到过这种消息通信模式。发布/订阅基于异步通信模式,允许消息的生产者(Publisher)和消费者(subscriber)通过中间代理(Broker)进行通信 。发布者和订阅者解耦,它们互相无感,订阅者只关注自己的主题(Topic)即可。这种方式可以实现高效、灵活的消息分发和控制。
大家都知道,只要解耦,就意味着整个消息机制的可扩展性大大增强,这也是发布/订阅应用广泛的一个重要原因。
发布/订阅方式的主要核心模块包括:
1、发布者(Publisher):其实就是提到的消息的生产者,它可以把消息分配到主题(Topic)
2、订阅者(Subscriber):就是消息的消费者,它可以根据自己的爱好来接收某个主题下的消息
3、消息代理(Broker):消息的分发者,控制着消息的路由,维护发布者和订阅者的对应关系
4、主题(Topic):主题可以认为是收音机的频道,它是一个逻辑概念,是发布者和订阅者间消息分类组织的交互通道
这种方式的优越性很高,它实现生产者和消费者间的完全解耦,并且使用了异步的通信机制,消除了同步的等待,提高了吞吐量且可以实现削峰添谷。同时,主题机制又可以使订阅者灵活的选择和删除相关的消息接收。而中间代理的出现则增加了消息的广播,即发布许/订阅方式实现了多对多的场景。在其内部又利用缓存机制,保证了历史数据的安全消费,达到了消息离线和在线的整体逻辑控制。
一般来说,常见的MQ框架等都支持这种方式,如Kafka、Pulsar、ActiveMQ、RocketMQ、ZeroMQ、RabbitMQ等等吧,对于互联网开发者来说这种方式已经是司空见惯了。

二、与推拉机制的关系

如果思考一下,发现发布/订阅方式与推拉机制有着很相似的应用场景,而其实现的逻辑也大抵相同。其实实际情况也差不多,大家可以看发布/订阅模式当成一种更高级的推拉模式的封装应用。不过发布/订阅方式由于抽象层更高,实现了更高层次的解耦并可以在分布式系统中实现动态路由。同时,在发布/订阅方式中,由于使用了borker中间代理人的角色,而不是简单的服务端和客户端的直接联系,这也是为什么这种方式解耦更好的原因所在。
虽然说一般情况下是broker将消息推送到订阅者,但也允许订阅者自行拉取相关的消息,这个就看设计实现者的意图了。典型的如Kafka就是如此。另外,在很多的发布/订阅方式中,采用了长轮询的方式,其实这就一种混合模式。看到这里,应该就明白了设计不是千篇一律的,它一定是动态的、发展的和可适应性的。实际的需求和条件决定了一切。
大家可以看推拉模式当成发布/订阅方式的基础实现,而后者是前者更高层次的抽象。这也是设计原则中经常提到的,面向抽象编程的一个重要体现。

三、应用场景

现在送牛奶的其实就有点类似这个行为,消费者可以订不同的奶(鲜奶、酸奶等Topic),也可以随时取消或增加。而生产者则会让送货员按时按期送达消费者而不用二者见面(异步)。而一个奶箱可以一个单元共享(多播、缓存)。所以说,计算机中应用的技术,基本都可以在现实世界上进行映射,毕竟计算机的出现就是为了解决现实中的问题。因此大家不要迷信技术。
明白了发布/订阅方式的主要原理就可以想象得到其应用的主要场景了:
1、通知系统:如订单更新、新闻推送、物流变化等等
2、日志处理系统:将日志分类到主题,然后交订阅者进行处理分析
3、IOT控制:这个大家用得很多,但感觉很少。它主要是对传感器数据进行主题划分然后交到感 兴趣的订阅方处理,比如马路上的监控探头
4、微服务通信:这个就和开发者比较接近了,特别是互联网后台的开发者,此处不展开
其实大家明白了发布/订阅方式后,一些细节在设计中非常重要,比如消息的传递形式,是使用JSON还是流或者其它;另外如何设置消息的过滤;需不需要消息的持久化以及是否支持重试保证消息的准确送达。另外,对一些安全等级高的,是不是要划分可靠性的等级,如何处理一些异常的状态,如消息无法正常投递等等。
它们当中相当多的问题是互相牵制的,比如消息内容形式就影响消息的过滤,重试又可能影响可靠性。所以在实际应用中,就需要设计者根据应用的特点来进行取舍,不能教条。
发布/订阅方式多用于互联网的分布式系统中,但不代表在本地无法使用。当然,本地使用常见的一些框架可能有些重或者说得不偿失,那么就可以自己利用一些设计模式(如观察者模式等)进行模拟实现。实现的手段不是关键,关键在设计者的目的是否达到。

四、实例分析

下面利用ZeroMQ实现一个简单的发布/订阅的例子:

//Pub
#include <zmq.hpp>
#include <iostream>
#include <string>
#include <chrono>
#include <thread>int main() {zmq::context_t context(1);zmq::socket_t pub(context, ZMQ_PUB);pub.bind("tcp://*:5555");  sleep(1);  int count = 0;while (true) {std::string topic = "news"; std::string message = "msg " + std::to_string(++count);// subject+delimiter+contentzmq::message_t zmqTopic(topic.size());memcpy(zmqTopic.data(), topic.c_str(), topic.size());zmq::message_t zmqMsg(message.size());memcpy(zmqMsg.data(), message.c_str(), message.size());publisher.send(zmqTopic, zmq::send_flags::sndmore);publisher.send(zmqMsg, zmq::send_flags::none);sleep(1);}return 0;
}//Sub
#include <zmq.hpp>
#include <iostream>
#include <string>int main() {zmq::context_t context(1);zmq::socket_t sub(context, ZMQ_SUB);sub.connect("tcp://localhost:5555");  const std::string topicFilter = "news";sub.set(zmq::sockopt::subscribe, topicFilter);while (true) {zmq::message_t rTopic;zmq::message_t rMsg;sub.recv(rTopic);sub.recv(rMsg);std::string topic(static_cast<char*>(rTopic.data()), rTopic.size());std::string msg(static_cast<char*>(rMsg.data()), rMsg.size());std::cout << "recv msg: [" << topic << "] " << msg << std::endl;}return 0;
}

代码不复杂,就不展开说明了。

五、总结

目前,智能驾驶这个赛道火得很,但其中的车联网系统中就广泛使用了这种机制。所以说,掌握好原理才能更好的拓展一项技术的应用,而不只是机械的模仿。需要说明的是,本篇不是分析发布/订阅机制内部实现的文章,而重点在于将其如何应用于设计当中。尽管篇幅不大,但希望给大家一个另外的角度做为切入点,也就是说,要从不同的角度来看待一个技术问题,才能更好更全面的明白其在整个技术框架中的作用。


http://www.ppmy.cn/news/1584044.html

相关文章

【Qt】程序加入开机自启动

设置程序为开机自启动 一是与 Windows 系统注册表交互&#xff0c;实现开机自启动功能的设置与取消&#xff1b; setAutoStart 函数 功能&#xff1a;负责处理程序开机自启动的设置与取消操作。实现细节&#xff1a; 首先&#xff0c;创建一个 QSettings 对象&#xff0c;指…

解决 Gin Web 应用中 Air 热部署无效的问题

解决 Gin Web 应用中 Air 热部署无效的问题 在使用 Go 语言开发 Web 应用时&#xff0c;Gin 框架因其高效和简洁深受开发者喜爱。为了提升开发效率&#xff0c;我们常常借助 Air 工具实现热部署&#xff0c;让代码修改后能实时生效&#xff0c;无需手动重启服务。然而&#xf…

如何构建化工质检的体系 质检LIMS系统在化工原料生产中的应用

一、构建化工质检的全流程质量管控体系 化工原料生产具有成分复杂、检测参数多的特点&#xff0c;传统实验室管理模式难以满足多品类、高频次检测需求。质检LIMS系统通过数字化改造&#xff0c;实现"样品登记-任务分配-数据采集-报告生成"的全流程自动化。以某精细化…

自然语言处理|人工智能如何革新作文批改:技术全解析

一、引言 在当今数字化时代&#xff0c;教育科技正在快速改变学习和教学方式。从在线课程的普及到智能教学工具的应用&#xff0c;教育领域正经历深刻变革。作文自动批改技术作为一项创新应用&#xff0c;逐渐受到关注&#xff0c;为作文教学提供了新思路和方法。这一技术不仅…

豪越消防一体化安全管控平台:消防管理智能化

在社会快速发展、城市建设日益复杂的今天&#xff0c;消防安全始终是保障人民生命财产安全、维护社会稳定的重要基石。传统消防管理模式在应对当下复杂多变的消防安全需求时&#xff0c;逐渐暴露出诸多局限性&#xff0c;而豪越消防一体化平台的出现&#xff0c;为消防管理领域…

自然语言处理|金融舆情解析:智能事件抽取与风险预警之道

一、金融市场的信息需求 在金融领域&#xff0c;信息是投资决策的关键因素。金融市场受宏观经济数据、政治局势、企业业绩、市场情绪等多种因素影响&#xff0c;呈现高度的波动性和不确定性。例如&#xff0c;一家上市公司的财报发布&#xff0c;若净利润超出预期&#xff0c;…

解决electron-builder vue 打包后element-ui字体图标不显示问题

项目使用的是vue2 element-ui electron 当使用electron打包完成的时候&#xff0c;启动项目发现使用的element-ui字体图标没显示都变成了小方块&#xff0c;并出现报错&#xff0c;请看下图&#xff1a; 解决方法&#xff1a; 在vue.config.js中设置 customFileProtocol字段…

基于C++实现一个平面上的形状编辑程序

平面上的形状编辑 一、设计目的&#xff1a; 实现一个平面上的形状编辑程序。 二、程序功能简介&#xff1a; 按照下图给出的层次关系来定义类。 2.所有形状支持无参数构造&#xff0c;有参数构造&#xff0c;拷贝构造&#xff0c;析构。 3.所有形状支持平移操作&#xff…