【DevOps云实践】Azure Function中使用发布/订阅模式
@TOC
推荐超级课程:
在分布式架构中,系统的不同部分将需要在事件发生时向其他部分提供信息。解决这个问题的方式之一是为每个消费者提供专用队列,并将消息异步发送以将其与消息发送者解耦。
然而,如果我们必须为大量的消费者执行此操作,这种方法就无法扩展,并且如果一些消费者只对生产者发送的信息的某些部分感兴趣会怎么样呢。
这个问题的答案可以在发布-订阅模式中找到,也称为发布/订阅消息,在这里我们可以使我们的生产者异步向订阅者发送事件,而不将其与发送者耦合。
发布/订阅消息是在分布式架构中使用的基本模式,因此在本篇博文中,我将谈论什么是发布/订阅消息,它提供了什么好处,以及在使用发布/订阅消息时需要考虑的一些事项。
什么是发布/订阅消息?
发布/订阅消息使应用程序和生产者能够异步向订阅者发送事件,而这些生产者无需与发送者耦合。
发送者(发布者)使用输入信道将事件打包成消息,然后发送消息。然后将这些消息发送到每个对消息感兴趣的消费者(订阅者)的输出消息信道。每个订阅者将从他们的输出信道中获得消息的副本。
代表具有发布者-订阅模型的消息系统的流程图。从左侧开始,一个标记为’发布者’的矩形发送一条消息到一个标记为’输入信道’的矩形。然后,该信道将消息转发到一个标记为’消息代理’的中央矩形。从消息代理,消息分发到三个标记为’订阅者’的矩形,每个订阅者连接到从消息代理发出的’输出信道’。该图形形象地表示了消息被发布、经纪和然后被不同消费者订阅的过程。
通过Azure中的一个示例,我们可以有一个Azure Function发送消息到服务总线主题。一个主题可以有多个订阅者,每个订阅者都可以注册到主题上。如果我们有多个作为主题订阅者的Azure Function,每个订阅者都会从主题中接收到他们自己的消息副本。
使用Azure服务总线主题的消息发布系统的示意图。左侧有一个带有闪电符号的标记为’发布者’的图标将消息发送到一个标记为’服务总线主题’的矩形框,该主题中间有Azure服务总线标志。在矩形框内部是代表消息的信封。从服务总线主题向右侧的三个图标发出三个箭头,每个图标都标记为带有闪电符号的’订阅者’,表示消息分发给多个订阅者。
事件驱动架构通过生成事件流的事件生成器与监听事件的事件消费者一起工作:
流程图描述了一个事件处理系统。图表从左侧开始,一个标记为’事件生成器’的矩形,发送一条箭头到中央标记为’事件摄入’的矩形。从事件摄入矩形,三个箭头分支到右侧三个单独的矩形,每个标记为’事件消费者’,表示事件分发给多个消费者。
事件驱动架构可以使用发布/订阅消息来跟踪事件的订阅者。当事件被发布时,它将发送给每个订阅者。接收事件后,它无法重新播放,并且新的订阅者看不到该事件。
这与另一种称为事件流的模式有些不同,其中事件被写入日志,而消费者不是订阅流,而是可以读取流的任何部分。这意味着他们可以随时加入流,并重播他们想要的事件。但是,在事件流中,客户端负责在流中前进。
发布/订阅消息的好处是什么?
发布/订阅消息帮助我们解耦需要进行通信的生产者和消费者。这帮助我们独立地管理它们,无论是扩展生产者以处理更多的消息,还是根据需要添加消费者。它还使我们能够通过消息代理本身来管理消息,如果消费者离线。
这种关注点的分离使每个应用能够专注于其核心功能,同时将将消息路由到正确的消费者的责任转移到消息代理。
我们的架构的整体可靠性增加了。异步消息传递使我们的应用在流量增加和处理间断性故障时能够平稳运行。测试性也提高了,因为我们可以检查我们的消息作为我们的测试策略的一部分。
订阅者不必立即从消息代理获取消息。根据你的业务需求,你可以选择在特定时间表上获取消息。
由于我们的架构的组件通过消息代理解耦,因此这些组件之间的集成变得更加容易,因为他们只需要能够从消息代理中接收消息。这意味着利用不同平台、运行在云端或本地,或使用不同编程协议的系统现在可以更有效地相互通信。
在实现发布/订阅消息时需要考虑什么?
如果可能的话,避免构建支持发布/订阅消息的自己的服务。有许多产品可以用于发布/订阅消息。在Azure世界中,Azure服务总线、事件中心和事件网格都可以用于发布/订阅架构。在Azure之外,Kafka、Redis和RabbitMQ都支持发布/订阅功能。
发布/订阅消息中的通信是单向的(单向移动)。如果您要求订阅者发送确认或将状态回传给发布者,最好使用[请求-响应模式]。
如何处理订阅者将是设计的一个重要方面。您的消息代理必须能够提供消费者订阅和取消订阅的能力。还必须考虑订阅者的安全性。安全地连接订阅者到消息通道对于防止未经授权的应用程序访问消息代理中的消息至关重要。
您还需要考虑订阅者如何处理消息。消息接收的顺序不是有保证的,消息创建的顺序也是如此。消息可能会发送多次(特别是如果发件人在发布消息后失败,然后启动一个新的发件人实例并重复消息)。
防止顺序和重复在系统中产生不良影响的一个方法是设计您的消息处理逻辑为幂等。
顺带一提,如果对于服务器而言,多次执行相同请求的预期效果与单个请求的效果相同,则该方法被认为是幂等的。
Azure服务总线有一个名为会话 的功能,可以强制标记有相同SessionId的消息合并在一起,并以先进先出(FIFO)的方式传递。在这种情况下,FIFO表示的是消息到达服务总线的顺序,而不是您在处理消息时要遵循的内部顺序。
说明了Azure服务总线中的消息排序的图表。图示顶部显示Azure服务总线标志,然后是一个具有数字标记的队列,表示顺序的消息。下面是三个水平线,代表不同的会话,每个都有一个’Session ID’。具有相同会话ID的消息在队列下方垂直对齐。箭头从这些消息指向右侧的三个接收者,每个接收者配有一个闪电符号。Receiver 1从’Session ID 1’获取消息,Receiver 2从’Session ID 2’获取消息,Receiver 3从’Session ID 3’获取消息,展示了如何基于会话ID将消息定向到特定接收者。
服务总线的另一个功能是消息延迟 ,通过其SequenceId将消息延迟以定义您定义的顺序处理消息。
其他消息考虑方面包括我们消息的生命周期(它们是否在一定时间后过期?)、我们的消息应在何时处理,以及是否不同的消息应该比其他消息更快地被处理。如果您需要为特定消息分配优先级,您可能希望考虑实施[优先级队列模式],以确保高优先级消息在其他消息之前被处理。
最后,如果消息的内容格式错误(称为毒消息),则您会希望阻止这些消息被返回到队列,并将有效载荷捕获到某个位置,以便您可以分析内容并在需要时修复问题。Azure服务总线通过使用死信队列 来支持此功能。
在什么情况下会使用这种模式?
如果您有一个需要向许多应用程序发送消息的应用程序,无论它们部署在何处或使用什么通信协议,发布/订阅模式都适用于广播该信息。如果您不需要实时从消费者那里获得响应,并且您的架构能够支持最终一致性,那么发布/订阅通信是理想的选择。
然而,如果您的架构中只有少数消费者,并且它们都需要来自生产者的不同信息片段,发布/订阅就不会对您有帮助。如果您需要实时响应和生产者与消费者之间的互动,您将需要考虑其他选择。
结论
在本文中,我们讨论了发布/订阅模式及其提供的好处,以及在使用发布/订阅消息时需要考虑的事项。