Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/google-sheets/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# MSMQ并行处理设计问题_C#_Concurrency_Windows Services_Msmq - Fatal编程技术网

C# MSMQ并行处理设计问题

C# MSMQ并行处理设计问题,c#,concurrency,windows-services,msmq,C#,Concurrency,Windows Services,Msmq,我有一个用C#编写的windows服务,它从MSMQ读取消息,并根据消息的类型将它们分配给在工作线程中处理该消息的代理。应用程序启动时没有代理,在消息到达MSMQ时在运行时动态创建 以下是其工作原理的基本图: 如果代理工作线程正忙于执行工作,则消息将排入其本地队列。到现在为止,一直都还不错。但是,如果由于某种原因停止服务,本地队列内容将丢失 我正试图找出处理这种情况的最佳方法。目前,本地队列是一个系统.Concurrent.ConcurrentQueue。我可能会使用Sql Ce db或其他一

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

以下是其工作原理的基本图:

如果代理工作线程正忙于执行工作,则消息将排入其本地队列。到现在为止,一直都还不错。但是,如果由于某种原因停止服务,本地队列内容将丢失

我正试图找出处理这种情况的最佳方法。目前,本地队列是一个
系统.Concurrent.ConcurrentQueue
。我可能会使用Sql Ce db或其他一些持久性存储,但我担心性能。我脑海中的另一件事是仅当代理准备好处理消息时才从MSMQ读取,但问题是我不知道MSMQ将包含什么消息


在这个问题上,我可以采取哪些可能的方法

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


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

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

您的设计基本上实现了以下模式:

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


相反,每个处理代理应该是一个具有自己的物理消息队列的自治进程。这就是在发生故障时提供消息持久性的原因。它还允许您通过托管更多的processing agent实例来进行扩展

实际上,代理是根据到达MSMQ的消息类型动态创建的。消息的类型可以从1到n不等。因此,我无法为潜在未知类型的消息创建单独的队列。ObaidR为什么不?您可以通过编程方式创建队列,n可能有多大?n可能在15~20之间。但是,我必须更改另一端的系统,它将根据消息类型将消息放在单独的队列中。我想知道我是否能在我的服务中以某种方式处理这个问题。@obaird你可以使用一些DB:SQlite,例如,但我真的建议使用多队列体系结构。我很想在这里使用Redis,但你不认为这会是一种过分的做法吗?一点也不。它非常轻,而且它能很好地完成它的设计目的,因此,你可以使用一些能为你完成工作的东西,而不是独自酝酿和调试一些新的东西。或者,您可以使用内存映射文件来实现对某种永久存储的快速访问,但存在一些复杂问题,而且我不知道线程安全性……不确定您是否需要单独的进程—与隔离PoV相比非常方便,但协调起来很难。绝对同意为每个代理设置单独的消息队列(使用某种约定以编程方式创建),该约定允许队列名称包含某种标识符,将其链接到负责其消息的代理。然后,在服务启动期间,您可以重新创建任何已存在队列的代理。