消息队列的良好策略是什么?

9
我目前正在设计一个应用程序,最终我希望将其移至Windows Azure。然而,在短期内,它将在我自己托管的服务器上运行。
该应用程序涉及多个独立的Web应用程序-其中一些本质上是接收数据的WCF服务,而另一些则是用户管理数据的网站。此外,还需要在后台运行一个工作程序,以各种方式处理数据。
我非常希望使用解耦架构来实现这一点。理想情况下,我希望组件(即Web应用程序和工作程序)尽可能少地了解彼此。使用消息队列似乎是最佳解决方案-Web应用程序可以将带有工作单元的消息排入队列中,而工作程序可以根据需要选择并处理它们。
但是,我想找出一组良好的技术来做到这一点,考虑到我最终将移动到Azure,并希望在迁移到云时尽量减少需要重新工作的量。Azure具有内置的队列组件,看起来非常适合我的需求。我想做的是创建一个尽可能类似于此的东西。
看起来有几个选项(我在Windows上使用.NET,并拥有SQL Server 2005后端)-我迄今为止发现的选项是:
MSMQ SQL Server服务代理程序 使用数据库表和一些存储过程滚动自己的
我想知道是否有人对此有任何建议-或者是否有人做过类似的事情,并提供关于要做/避免的事情的建议。我意识到每种情况都是不同的,但在这种情况下,我认为我的排队要求非常通用,因此我很乐意听取任何其他人对如何做到最好的想法。
提前致谢,
约翰
3个回答

18

如果你考虑使用 Azure,可能应该直接使用 Azure,因为 Azure 队列与 MSMQ 或 SSB 的 API 和语义显著不同。

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

  • 部署:MSMQ 是一个 Windows 组件,SSB 是一个 SQL 组件。SSB 需要一个 SQL 实例来存储任何消息,因此断开连接的客户端需要访问一个实例(可以是 Express)。MSMQ 需要在客户端上部署 MSMQ(OS 的一部分,但可选安装)。
  • 编程能力:MSMQ 提供完全成熟、受支持的 WCF 通道。SSB 只提供一个实验性的 WCF 通道,位于 http://ssbwcf.codeplex.com
  • 性能:SSB 在事务模式下比 MSMQ 显著更快。如果在未启用事务模式下运行,则 MSMQ 将更快(最佳尝试、无序传递)
  • 查询能力:SSB 队列可以进行 SELECT 操作(查看任何消息,具有全面的 SQL JOIN/WHERE/ORDER/GROUP 功能),MSMQ 队列可以进行 Peek 操作(只能查看下一条消息)
  • 可恢复性:SSB 队列集成在数据库中,因此它们随着数据库备份和还原而备份和还原,与应用程序状态保持一致。MSMQ 队列在 NT 文件备份子系统中备份,因此为了使备份保持同步(一致),队列 数据库必须被暂停。
  • 事务(由于每个 enqueue/dequeue 操作始终伴随着一个数据库更新):SSB 完全集成在 SQL 中,因此 dequeueing 和 enqueueing 是本地事务操作。MSMQ 是一个单独的 TM(Transaction Manager),因此队列/dequeue 必须是分布式事务操作,以将 SQL 和 MSMQ 同时注册到事务中。
  • 管理和监控:两者都非常糟糕。没有任何工具。
  • 相关消息处理:SSB可以通过内置的Conversation Group Locking来阻止并发线程对相关消息进行处理。
  • 事件驱动:SSB具有激活功能来启动存储过程,MSMQ使用Windows Activation服务。虽然相似,但由于WAITFOR(RECEIVE)和MAX_QUEUE_READERS的交互方式,SSB具有自我负载平衡的能力。
  • 可用性:SSB依赖于SQL Server高可用性故事,它可以在集群或数据库镜像环境中工作。MSMQ仅依赖于Windows集群故事。作为HA解决方案,数据库镜像比集群便宜得多。
  • 此外,我想补充一点,SSB和MSMQ在它们提供的原语层面上有很大的差异:SSB的原语是一个会话,而MSMQ的原语是一个消息。可以将其视为TCP和UDP语义。


    谢谢!那非常有帮助。看起来 MSMQ 可能是我们目的更好的选择—我猜下一步大的工作将是比较 MSMQ 和 Azure Queuing。例如,我知道 Azure 不能保证按顺序交付消息(或仅交付一次),因此我需要将其与 MSMQ 进行比较以查看相应的行为。但再次感谢您——这是一个非常有用的比较。 - John

    10

    选择适合你的队列后端,或者适合你环境的后端。@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


    0

    使用Win32 邮槽。它们在单个服务器上可靠,易于实现,不需要任何额外的软件。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接