消息队列的好策略?

Posted

技术标签:

【中文标题】消息队列的好策略?【英文标题】:Good Strategy for Message Queuing? 【发布时间】:2010-11-23 05:13:07 【问题描述】:

我目前正在设计一个最终希望迁移到 Windows Azure 的应用程序。不过,在短期内,它将在我自己托管的服务器上运行。

该应用程序涉及许多独立的 Web 应用程序 - 其中一些本质上是接收数据的 WCF 服务,而另一些则是供用户管理数据的站点。此外,还需要在后台运行一个工作服务,以各种方式处理数据。

我非常热衷于为此使用解耦架构。理想情况下,我希望组件(即 Web 应用程序和工作服务)尽可能少地相互了解。似乎在这里使用消息队列将是最好的解决方案 - Web 应用程序可以将带有工作单元的消息排入队列,并且工作服务可以根据需要将它们挑选出来并处理它们。

但是,我想制定一套好的技术来实现这一点,记住我最终会迁移到 Azure,并且希望在迁移时尽量减少我需要做的返工到云端。 Azure 有一个内置的队列组件,看起来非常适合我的需求。我想做的是自己创造一些东西,尽可能地模仿这一点。

看起来有几个选项(我在 Windows 上使用 .NET,带有 SQL Server 2005 后端)- 目前我发现的选项是:

MSMQ SQL Server 服务代理 使用数据库表和一些存储过程自行滚动

我想知道是否有人对此有任何建议 - 或者是否有人做过类似的事情并对要做/避免的事情提出建议。我意识到每种情况都不同,但在这种情况下,我认为我的排队要求非常笼统,所以我很想听听其他人对最佳方式的想法。

提前致谢,

约翰

【问题讨论】:

【参考方案1】:

如果您考虑使用 Azure,也许您应该直接从 Azure 开始,因为 API 和语义在 Azure 队列与任何 MSMQ 或 SSB 之间存在显着差异。

MSMQ 与 SSB 的 3048 米快速比较(我将保留自定义表作为队列,因为它实际上取决于您如何实现它...)

部署:MSMQ 是一个 Windows 组件,SSB 是一个 SQL 组件。 SSB 需要一个 SQL 实例来存储任何消息,因此断开连接的客户端需要访问一个实例(可以是 Express)。 MSMQ 需要在客户端部署 MSMQ(操作系统的一部分,但可选安装)。 可编程性:MSMQ 提供了一个成熟的、受支持的 WCF 通道。 SSB 仅在http://ssbwcf.codeplex.com 提供实验性 WCF 通道 性能:在事务模式下,SSB 将明显快于 MSMQ。如果让 MSMQ 在非事务模式下运行(尽力而为、无序、交付),MSMQ 会更快 可查询性:SSB 队列可以被 SELECTE uppon(查看任何消息,完整的 SQL JOIN/WHERE/ORDER/GROUP 功能),MSMQ 队列可以被查看(仅下一条消息) 可恢复性:SSB队列集成在数据库中,因此它们与数据库一起备份和恢复,与应用程序状态保持一致。 MSMQ 队列在 NT 文件备份子系统中进行备份,因此为了保持备份同步(一致)队列数据库必须暂停。 事务(因为每个入队/出队总是伴随着数据库更新):SSB 完全集成在 SQL 中,因此出队和入队是本地事务操作。 MSMQ 是一个单独的 TM(事务管理器),因此 queue/dequeue 必须是分布式事务操作才能在事务中注册 SQL 和 MSMQ。 管理和监控:同样糟糕。没有任何工具。 相关消息处理:SSB 可以通过内置的Conversation Group Locking 阻止并发线程处理相关消息。 事件驱动:SSB 有Activation 来启动存储过程,MSMQ 使用Windows Activation 服务。相似的。由于 WAITFOR(RECEIVE) 和 MAX_QUEUE_READERS 的交互方式,SSB 具有自我负载平衡能力。 可用性:SSB 搭载 SQL Server 高可用性故事,它可以在集群或数据库镜像环境中工作。 MSMQ 仅涉及 Windows 群集故事。数据库镜像比集群作为 HA 解决方案要便宜得多。

此外,我要补充一点,SSB 和 MSMQ 在它们提供的原语级别上存在显着差异:SSB 原语是一种对话,而 MSMQ 原语是一种消息。想想 TCP 与 UDP 语义。

【讨论】:

谢谢!这很有帮助。看起来 MSMQ 对于我们的目的可能是一个更好的选择——我想下一步的一大步是将 MSMQ 与 Azure 队列进行比较。例如,我知道 Azure 不保证消息将按顺序传递(或仅传递一次),因此我需要对照 MSMQ 对此进行检查,以了解相应的行为是什么。但再次感谢这一点 - 这是一个非常有用的比较。【参考方案2】:

选择适合您或更适合您的环境的队列后端。 @Remus 对 MSMQ 和 SSB 进行了很好的比较。 MSMQ 将更容易实现,但有一些明显的限制,而 SSB 将感觉非常沉重,因为它位于频谱的另一端。

随心所欲 为了最大限度地减少您的应用程序的返工,将队列访问抽象化为一个接口,然后为您最终决定使用的队列传输提供一个实现。当需要迁移到 Azure 或其他队列传输时,您只需提供接口的新实现即可。

您可以控制您希望如何与队列交互的语义,从而为您的应用程序提供一致的可用 API。

一个粗略的想法可能是:

interface IQueuedTransport

  void SendMessage(XmlDocument);
  XmlDocument ReceiveMessage();


public class MSMQTransport : IQueuedTransport 
public class AzureQueueTransport : IQueuedTransport 

您可能不是在构建最能满足您需求的队列传输。如果您使用 Xml,请传递 xml。如果您在字节数组中工作,请传递字节数组。 :)

祝你好运! Z

【讨论】:

【参考方案3】:

使用 Win32 Mailslots。它们在单个服务器上是可靠的,易于实施,并且不需要任何额外的软件。

【讨论】:

以上是关于消息队列的好策略?的主要内容,如果未能解决你的问题,请参考以下文章

Kafka源码深度解析-系列1 -消息队列的策略与语义

Redisson,工作队列/ dequeu。系统/ pod关闭时不完整消息处理的消息/元素处理策略

消息队列消息丢失和消息重复发送的处理策略

58消息队列master负载均衡策略设计

RabbitMQ 消息队列学习

移动云消息队列RabbitMQ对资源创建数量有限制吗?