你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

发布者-订阅者模式

Azure 事件网格
Azure 事件中心
Azure 服务总线

使应用程序能够以异步方式向多个感兴趣的使用者公布事件,而无需将发送方与接收方耦合。

也称为:发布/订阅消息

上下文和问题

在基于云的分布式应用程序中,在发生事件时,系统组件通常需要向其他组件提供信息。

异步消息传送是将发件者与使用者解耦的有效方式,可避免阻止发送者等待响应。 但是,对每个使用者使用专用消息队列不能让多个使用者有效进行缩放。 此外,某些使用者可能仅对一部分信息感兴趣。 发送者如何在不知道使用者标识的情况下,向所有感兴趣的使用者公布事件?

解决方案

引入一个包括以下功能的异步消息传送子系统:

  • 发送者使用的输入消息传送通道。 发送者使用已知的消息格式将事件打包成消息,然后通过输入通道发送这些消息。 在此模式中,发送者也称为“发布者”。

    注意

    消息是数据包。 事件是一条消息,告知其他组件已发生某项更改或操作。

  • 每个使用者有一个输出消息传送通道。 使用者称为“订阅者”。

  • 一个机制,用于将输入通道中的每条消息复制到对该消息感兴趣的所有订阅者的输出通道。 此操作通常由消息中转站或事件总线等中介处理。

下图显示了此模式的逻辑组件:

使用消息中转站的发布-订阅模式

发布/订阅消息传送具有以下优势:

  • 解耦仍然需要通信的子系统。 可以独立管理子系统,即使一个或多个接收者处于脱机状态,也能正确管理消息。

  • 提高可伸缩性,改善发送者的响应能力。 发送者可以快速将一条消息发送到输入通道,然后恢复其核心处理责任。 消息传送基础结构负责确保将消息传送到感兴趣的订阅者。

  • 它提高了可靠性。 异步消息传送可以帮助应用程序在负载增大的情况下继续保持平稳运行,并更有效地处理间歇性故障。

  • 它允许延迟或计划的处理。 订阅者可以等到在非高峰期拾取消息,或者可以根据特定的计划路由或处理消息。

  • 这样可以简化使用不同平台、编程语言或通信协议的系统之间的集成,以及本地系统与云中运行的应用程序之间的集成。

  • 它简化了整个企业中的异步工作流。

  • 它改善了可测试性。 在执行整个集成测试策略过程中,可以监视通道,并可以检查或记录消息。

  • 它为应用程序提供关注点分离。 每个应用程序可以注重自身的核心功能,而消息传送基础结构可以处理所需的一切工作来可靠地将消息路由到多个使用者。

问题和注意事项

在决定如何实现此模式时,请考虑以下几点:

  • 现有技术。 强烈建议使用支持发布-订阅模型的可用消息传送产品和服务,而不要自行构建。 在 Azure 中,考虑使用服务总线事件中心事件网格。 其他可用于发布/订阅消息传送的技术包括 Redis、RabbitMQ 和 Apache Kafka。

  • 订阅处理。 消息传送基础结构必须提供相应的机制,让使用者通过可用的通道订阅或取消订阅。

  • 安全性。 连接到任何消息通道必须受安全策略的限制,以防止未经授权的用户或应用程序窃听。

  • 消息子集。 订阅者通常只对发布者分发的消息的子集感兴趣。 消息传送服务通常允许订阅者按以下各项缩小接收的消息集范围:

    • 主题。 每个主题都有一个专用输出通道,每个使用者可以订阅所有相关主题。
    • 内容筛选。 根据每个消息的内容检查和分发消息。 每个订阅者可以指定其感兴趣的内容。
  • 通配符订阅者。 考虑允许订阅者通过通配符订阅多个主题。

  • 双向通信。 发布-订阅系统中的通道被认为是单向的。 如果特定订阅者需要向发布者发回确认或通信状态,请考虑使用请求/回复模式。 此模式使用一个通道向订阅者发送消息,并使用一个独立的回复通道来与发布者通信。

  • 消息排序。 不能保证使用者实例接收消息的顺序,且不一定反映创建消息的顺序。 精心设计系统以确保消息处理是幂等的,以帮助消除对消息处理顺序的任何依赖。

  • 消息优先级。 某些解决方案可能要求按特定的顺序处理消息。 优先级队列模式提供一种机制用于确保按顺序传送特定的消息。

  • 有害消息。 格式不正确的消息或需要访问不可用资源的任务可能会导致服务实例失败。 系统应阻止将此类消息返回到队列。 应该捕获这些消息的详细信息并将其存储在其他位置,以便可按需要对其进行分析。 某些消息中转站(如 Azure 服务总线)通过其死信队列功能支持此操作。

  • 重复消息。 同一条消息可能会发送多次。 例如,在发布某条消息后,发送者可能会发生故障。 然后,该发送者的新实例可能会启动并重复发送该消息。 消息传送基础结构应该实施基于消息 ID 的重复消息检测和删除(也称为重复项删除),以便最多只传送消息一次。 或者,如果使用不删除重复消息的消息传递基础结构,请确保消息处理逻辑是幂等的

  • 消息过期。 消息可能带有有限的生存期。 如果在此期限内未处理该消息,则它不再有用,应该将其丢弃。 发送者可以在消息数据中指定过期时间。 接收者可以检查此信息,然后决定是否要执行与该消息关联的业务逻辑。

  • 消息计划。 可以暂时禁止传送某条消息,在特定的日期和时间之前,不应处理该消息。 在此时间之前,不应将该消息提供给接收者。

  • 横向扩展订阅者。 如果给定订阅者无法跟上接收消息的速率,请使用竞争性使用者模式将其横向扩展。

何时使用此模式

在以下情况下使用此模式:

  • 应用程序需要将信息广播到大量的使用者。

  • 应用程序需要与一个或多个独立开发的、可能使用不同平台、编程语言和通信协议的应用程序或服务通信。

  • 应用程序无需使用者的实时响应,即可将信息发送到使用者。

  • 集成的系统旨在支持其数据的最终一致性模型。

  • 应用程序需要向多个使用者传送信息,而这些使用者的可用性要求或运行时间计划可能与发送者不同。

在以下情况下,此模式可能不起作用:

  • 应用程序只有少量的几个使用者,而这些使用者所需的信息与生成方应用程序截然不同。

  • 应用程序需要与使用者进行近实时的交互。

工作负载设计

架构师应评估如何在其工作负载的设计中使用“发布者-订阅者模式”,以解决 Azure Well-Architected Framework 支柱中涵盖的目标和原则。 例如:

支柱 此模式如何支持支柱目标
可靠性设计决策有助于工作负荷在发生故障后复原,并确保它在发生故障后恢复到正常运行状态。 该模式中引入的分离实现了组件上的独立可靠性目标,并消除了直接依赖关系。

- RE:03 故障模式分析
- RE:07 后台作业
安全设计决策有助于确保工作负荷数据和系统的机密性完整性可用性 此模式引入了一个重要的安全分段边界,使队列订阅服务器能够与发布服务器进行网络隔离。

- SE:04 分段
成本优化的重点是维持和提高工作负载的投资回报率 这种分离的设计可以在体系结构中启用事件驱动方法,这与基于消费的计费很好地结合在一起,以避免过度预配。

- CO:05 比率优化
- CO:12 扩展成本
卓越运营有助于通过标准化流程和团队凝聚力提供工作负载质量 此间接层可以使你能够安全地更改发布服务器或订阅服务器端的实现,而无需协调对这两个组件的更改。

- OE:06 工作负载开发
- OE:11 安全部署实践
性能效率通过在缩放、数据和代码方面进行优化, 帮助工作负载高效地满足需求 发布者与使用者的分离使你能够针对使用者需要为特定消息执行的任务来优化计算和代码。

- PE:02 容量规划
- PE:05 缩放和分区

与任何设计决策一样,请考虑对可能采用此模式引入的其他支柱的目标进行权衡。

示例

下图显示了一个使用服务总线来协调工作流,并使用事件网格来向子系统通知发生的事件的企业集成体系结构。 有关详细信息,请参阅 Azure 上使用消息队列和事件的企业集成

企业集成体系结构

后续步骤

实现此模式时,以下指南可能比较有用:

实现此模式时,以下模式可能有用:

  • 观察者模式。 发布-订阅模式构建在观察者模式的基础之上,可以通过异步消息传送将主题与观察者解耦。

  • 消息中转站模式。 支持发布-订阅模型的许多消息传送子系统是通过消息中转站实施的。

此博客文章介绍了处理无序到达的消息的不同方法。