Publisher/Subscriber 订阅-发布模式原理解析
一、概念
发布/订阅消息被称为pub/sub,是serverless和microservices
架构中使用的一种异步服务对服务的通信方法。Pub/Sub模型包括如下两个基本组成部分:
- 发送消息的发布者(publisher)。
- 通过消息中介(broker)接收消息的订阅者(subscriber)。
1.1 基础概念
随着解耦(decouple)和基于微服务(microservices-based)的应用程序的流行,组件(components)和服务(services)之间的适当通信对整个应用程序的功能至关重要。Pub/Sub模式的消息传递在两个关键方面对此有所帮助:
- 允许开发人员通过可靠的通信方法轻松创建解耦应用程序。
- .使用户能够轻松创建事件驱动(event-driven)的架构
Pub/Sub模型允许消息在应用程序的多个部分异步广播。
促进这一功能的核心组件是Topic
。发布者将消息推送给一个Topic
,而Topic
将立即把消息推送给所有订阅者。这就是Pub/Sub模型与传统的消息中介的不同之处,在传统的消息中介中,消息队列会对单个消息进行批处理,直到用户或服务请求这些消息并将其检索出来。
在Pub/Sub模型中,无论消息是什么,它都会被自动推送给所有的订阅者。唯一的例外是用户为订阅者创建的策略,它将过滤掉消息。
这种方法使得创建事件驱动的服务成为可能,而不需要不断查询消息队列的消息。它还使开发者能够使用相同的消息(数据)创建不同的隔离功能,这些功能可以并行执行(can be executed parallelly),并能够为多个订阅者提供服务。
Pub/Sub模式将发布者与订阅者隔离开来,因此发布者不需要知道消息在哪里被使用,而订阅者不需要知道发布者的情况。这有助于有机地提高应用程序的整体安全性。
1.1.1 现实举例
比如当我们进入一个聊天室 / 群,如果有人在聊天室发言,那么这个聊天室里的所有人都会收到这个人的发言。这是一个典型的发布 - 订阅模式,当我们加入了这个群,相当于订阅了在这个聊天室发送的消息,当有新的消息产生,聊天室会负责将消息发布给所有聊天室的订阅者。
再举个栗子,当我们去 adadis 买鞋,发现看中的款式已经售罄了,售货员告诉你不久后这个款式会进货,到时候打电话通知你。于是你留了个电话,离开了商场,当下周某个时候 adadis 进货了,售货员拿出小本本,给所有关注这个款式的人打电话。
这也是一个日常生活中的一个发布 - 订阅模式的实例,虽然不知道什么时候进货,但是我们可以登记号码之后等待售货员的电话,不用每天都打电话问鞋子的信息。
1.2 优点
1.2.1 解耦/松耦合的组件
Pub/Sub允许你轻松地分离通信和应用逻辑,从而创造出孤立的组件。这样做可以:
- 创建更多的模块化、健壮和安全的软件组件或模块
- 提高代码质量和可维护性
1.2.2 更好的系统可视性
Pub/Sub模式的简单性意味着用户可以很容易地理解应用程序的流程。
该模式还允许创建解耦组件,帮助我们获得信息流的鸟瞰图。我们可以确切地知道信息从哪里来,在哪里传递,而不需要在源代码中明确地定义源头或目的地。
1.2.3 实时通信
Pub/Sub通过基于推送的方式将消息即时传递给订阅者,使其成为满足近乎实时通信要求的理想选择。这消除了检查队列中的消息的任何轮询需要,并减少了应用程序的交付延迟。
1.2.4 便于发展
由于Pub/Sub不依赖于编程语言、协议或特定的技术,任何支持的消息中介可以使用任何编程语言轻松地集成到其中。此外,Pub/Sub可以作为一个桥梁,通过管理组件间的通信,实现使用不同语言构建的组件间的通信。
这促进了与外部系统的轻松集成,而不需要创建功能来促进通信或担心安全问题。我们可以简单地将消息发布到一个Topic
,并让外部应用程序订阅该Topic
,从而消除了与底层应用程序直接交互的需要。
1.2.5 提高可扩展性和可靠性
Pub/Sub这种消息传递模式被认为是有弹性的——我们不需要预先定义一个固定数量的发布者或订阅者。它们可以根据使用情况被添加到所需的Topic
中。
通信和逻辑之间的分离也导致了更容易的故障排除,因为开发人员可以专注于特定的组件,而不用担心它影响到应用程序的其他部分。
Pub/Sub还提高了应用程序的可扩展性,因为它允许在不影响底层组件的情况下改变消息中介架构、过滤器和用户。有了Pub/Sub,如果消息格式是兼容的,即使有复杂的架构变化,新的消息传递实现也只是改变Topic
的问题。
1.2.6 改进可测试性
随着整个应用程序的模块化,测试可以针对每个模块,创建一个更精简的测试管道。通过针对应用程序的每个组件进行测试,这大大降低了测试案例的复杂性。
Pub/Sub模式也有助于轻松了解数据的来源和目的地以及信息流。它对测试以下问题特别有帮助:
- 数据损坏
- 格式化
- 安全性
1.3 缺点
1.3.1 小型系统中不必要的复杂性
Pub/Sub需要被正确配置和维护。如果可扩展性和解耦性对你的应用程序不是至关重要的因素,实施Pub/Sub将是对资源的浪费,并导致小型系统不必要的复杂性。
1.3.2 不适用于流媒体(Media streaming)
在处理音频或视频等媒体时,Pub/Sub并不适合,因为它们需要在主机和接收器之间进行流畅的同步流。而Pub/Sub不支持同步的端到端通信,所以Pub/Sub消息传递不适合于:
- 视频会议
- VOIP——基于IP的语音传输
- 一般流媒体应用
1.4 Pub/Sub消息传递的使用案例
Pub/Sub模式可用于不同行业,以促进实时和分布式通信。例如,自动化是受益于这种模式的一个关键领域。
下面的章节描述了Pub/Sub的常见用例。
1.4.1 IoT (物联网)
有了智能设备,我们需要一种可靠和有效的方式来收集和分发信息。一个控制节点或服务器可以发布更新,这些更新将被自动传递给所有订阅的物联网设备。
终端用户的物联网设备也可以作为发布者,将通知、传感器信息等发布到云端,然后通知给用户。
1.4.2 系统监控和事件通知
Pub/sub允许用户创建Topic
来收集系统信息,并将它们推送到可视化和通知前台。这在处理大规模部署时非常有用。
- 消息可以被归类到不同的
Topic
中。 - 所有的服务器或服务都可以将数据发布到这些共同的
Topic
,而不需要单独的通知管道(notification pipelines)。
我们可以通过向Topic
订阅维护或管理功能来进一步扩展这一功能。例如,如果一个服务器报告了一个错误,它将触发一个功能来自动替换该服务器。
1.4.3 数据库备份和复制
对于分布在不同供应商的多个数据库,进行备份是非常必要的。我们可以使用cron jobs配置定期备份或快照。
然而,假设我们需要将这些备份转移到不同的地区或云存储。在这种情况下,我们可以使用Pub/Sub消息传递来创建一个管道,该管道将推送一个消息,告知备份完成。然后,一个订阅的函数将使用该消息作为触发器来启动迁移或复制过程。
1.4.4 日志管理
Pub/Sub可以作为中间人来聚合和分发日志。我们可以从多个地点收集日志,并将它们推送给elastic search
等订阅服务,或者简单地将它们存储在不同的指定位置。
日志可以按问题、审计跟踪、通知、后台任务等进行过滤,并直接推送给不同的订阅者,实现适当的日志管理。
1.5 Pub/Sub消息传递服务
现在有大量的Pub/Sub消息服务,从专用的消息中介到云服务。以下是一些常见的Pub/Sub服务:
- Apache Kafka。由Apache开发,Kafka具有强大的Pub/Sub消息传递功能和消息日志。
- Faye。简单的Pub/Sub服务,旨在通过为NodeJS和Ruby设计的服务器为网络应用提供动力。
- Redis。这是最流行的消息中介之一,既支持传统的消息队列,也支持Pub/Sub模式的实现。
- Amazon SNS。亚马逊简单通知服务是一个完全管理的服务,提供Pub/Sub消息。
- Google Pub/Sub。GCP提供的pub/sub消息服务实现。
- Azure Service Bus。一个强大的消息服务(MaaS)解决方案,提供Pub/Sub模式。
二、Avro
Avro是一个数据序列化系统,主要用于支持大批量数据交换的应用。
特点:
- 支持二进制序列化方式,可以便捷、快速的处理大量数据;
- 动态语言有好,Avro提供的机制使动态语言可以方便的处理Avro数据
Avro Schema结构如下
{
"type":"record",
"name":"aaa", //包名
"namespace":"bbb",
"fields":[ // 列举所有属性,是json数组
{
"name":"ccc", // 属性名
"type":"int", // 属性类型
"doc":"ccc", // 属性文档
"default":0 // 属性默认值,需要对应属性类型
},
{
"name":"ddd",
"type":"string",
"doc":"ddd",
"default":""
}
]
}
Avro的一个关键特性是能够为数据定义模式。例如,代表产品销售的事件可能是这样的:
{
"time": 1424849130111,
"customer_id": 1234,
"product_id": 5678,
"quantity":3,
}
它可能有这样一个schema,它定义了这五个字段:
{
"type": "record",
"doc":"This event records the sale of a product",
"name": "ProductSaleEvent",
"fields" : [
{"name":"time", "type":"long", "doc":"The time of the purchase"},
{"name":"customer_id", "type":"long", "doc":"The customer"},
{"name":"product_id", "type":"long", "doc":"The product"},
{"name":"quantity", "type":"int"}
]
}
三、Google Cloud Pub/Sub
官网:https://cloud.google.com/pubsub/architecture
Pub/Sub 是一种全托管式实时消息传递服务,可让您在独立的应用之间发送和接收消息。
Pub/Sub 的基本消息流如下:
在此方案中,有两个发布者针对单个主题发布消息。该主题有两个订阅。第一个订阅有两个订阅者,这意味着消息将在这两个订阅者之间进行负载平衡,每个订阅者会收到一部分消息。第二个订阅有一个订阅者,该订阅者将收到所有消息。粗体字母代表消息。消息 A 来自发布者 1,通过订阅 1 发送给订阅者 2,通过订阅 2 发送给订阅者 3。消息 B 来自发布者 2,通过订阅 1 发送给订阅者 1,通过订阅 2 发送给订阅者 3。
便于利用proto文件进行开发,以下对整个操作过程,请求载荷和响应结果进行展实
3.1 创建架构
3.2 验证消息
3.3 创建主题
3.4 创建订阅
3.5 发布消息
3.6 拉取消息
以上就是该Pub/Sub系统的基本使用流程