Publisher/Subscriber 订阅-发布模式原理解析

一、概念

发布/订阅消息被称为pub/sub,是serverlessmicroservices架构中使用的一种异步服务对服务的通信方法。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 的基本消息流如下:


订阅系统架构 订阅推送架构_设计模式_02

在此方案中,有两个发布者针对单个主题发布消息。该主题有两个订阅。第一个订阅有两个订阅者,这意味着消息将在这两个订阅者之间进行负载平衡,每个订阅者会收到一部分消息。第二个订阅有一个订阅者,该订阅者将收到所有消息。粗体字母代表消息。消息 A 来自发布者 1,通过订阅 1 发送给订阅者 2,通过订阅 2 发送给订阅者 3。消息 B 来自发布者 2,通过订阅 1 发送给订阅者 1,通过订阅 2 发送给订阅者 3。

便于利用proto文件进行开发,以下对整个操作过程,请求载荷和响应结果进行展实

3.1 创建架构

订阅系统架构 订阅推送架构_应用程序_03

订阅系统架构 订阅推送架构_分布式_04

3.2 验证消息

订阅系统架构 订阅推送架构_设计模式_05

订阅系统架构 订阅推送架构_应用程序_06

订阅系统架构 订阅推送架构_订阅系统架构_07

订阅系统架构 订阅推送架构_分布式_08

3.3 创建主题

订阅系统架构 订阅推送架构_分布式_09

订阅系统架构 订阅推送架构_分布式_10

3.4 创建订阅

订阅系统架构 订阅推送架构_分布式_11

订阅系统架构 订阅推送架构_订阅系统架构_12

3.5 发布消息

订阅系统架构 订阅推送架构_分布式_13

订阅系统架构 订阅推送架构_分布式_14

3.6 拉取消息

订阅系统架构 订阅推送架构_云服务_15

订阅系统架构 订阅推送架构_分布式_16

以上就是该Pub/Sub系统的基本使用流程