【问题标题】:MSMQ concurrent processing design issueMSMQ并发处理设计问题
【发布时间】:2012-07-17 03:50:54
【问题描述】:

我有一个用 C# 编写的 Windows 服务,它从 MSMQ 读取并根据消息的类型将它们分配给在工作线程中处理该消息的代理。应用程序在没有代理的情况下启动,并在消息到达 MSMQ 时在运行时动态创建

这是它如何工作的基本图:

如果代理工作线程忙于工作,则消息将排队到其本地队列中。到目前为止,一切都很好。但是如果由于某种原因停止了服务,本地队列内容就会丢失。

我正在尝试找出处理这种情况的最佳方法。现在本地队列是System.Concurrent.ConcurrentQueue。我可能会使用 Sql Ce db 或其他一些持久存储,但我担心性能。我想到的另一件事是只有在代理准备好处理消息时才从 MSMQ 读取,但问题是我不知道 MSMQ 将包含什么消息。

我可以采取哪些可能的方法来解决这个问题?

【问题讨论】:

    标签: c# concurrency windows-services msmq


    【解决方案1】:

    我已经构建了一个类似的依赖于 Redis 的系统。这个想法是它提供了内存 - 与应用程序的其余部分隔离的快速数据访问,并且不会在我的服务关闭时关闭。此外,它最终会将我的数据保存到磁盘上,因此我在可靠性和速度之间取得了很好的折衷。

    如果您将其设计为每个客户端从其自己的消息队列中读取,该消息队列将托管在 Redis 中,您可以使队列独立于服务的停机时间,并在您下次启动服务时分配每个工作人员的负载。

    【讨论】:

    • 我很想在这里使用 Redis,但你不觉得这有点矫枉过正吗?
    • 一点也不。它非常轻巧,并且可以很好地完成其设计目的,因此您可以使用可以为您完成工作的东西,而不是自己酿造和调试新的东西。或者,您可以使用内存映射文件来实现对某种永久存储的快速访问,但是有一些复杂性,我不知道线程安全......
    【解决方案2】:

    您为什么不简单地创建两个新的 msms 队列来接收 Agenta 和 agentb 的消息,并创建一个新的代理(以事务方式)从主队列中获取命令并将消息分派到正确的代理队列?

    【讨论】:

    • 实际上代理是根据到达 MSMQ 的消息类型动态创建的。消息的类型可以从 1 到 n 不等。所以我不能为可能未知类型的消息创建一个单独的队列。
    • ObaidR 为什么不呢?您可以通过编程方式创建队列,可能有多大?
    • n 可能在 15~20 左右。但随后我将不得不更改另一端的系统,它将根据消息类型将消息放入单独的队列中。我想知道我是否可以在我的服务中处理这个问题。
    • @ObaidR 你可以使用一些 DB: SQlite 例如,但我真的建议多队列架构
    【解决方案3】:

    您的设计基本上实现了以下模式:http://www.eaipatterns.com/MessageDispatcher.html

    但是,您选择在多线程代码中实现调度程序,而不是使用实际的消息传递。

    相反,每个处理代理都应该是一个具有自己的物理消息队列的自治进程。这将在失败的情况下提供消息持久性。它还允许您通过托管更多处理代理实例来进行扩展。

    【讨论】:

    • 不确定您是否需要有单独的进程 - 从隔离 PoV 方便但难以协调。绝对同意为每个代理设置单独的消息队列(使用某种约定以编程方式创建,该约定允许队列名称包含某种标识符,将其链接到负责其消息的代理。然后在服务启动期间,您可以重新创建任何已经存在队列的代理。
    猜你喜欢
    • 1970-01-01
    • 2010-12-08
    • 2012-04-30
    • 1970-01-01
    • 2010-12-09
    • 1970-01-01
    • 2020-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多