2

不是 MSMQ 或 WCF 方面的专家,我已经阅读了一些关于它的内容,它听起来和看起来都很棒。我正在尝试开发一些东西,但首先是一些理论,它需要坚固耐用。

我猜 MSMQ 将托管在单独的服务器上。

将有 2 个 WCF 服务。一个用于传入消息,另一个用于传出消息(接收消息,进行一些内部处理/验证,然后将其放在传出消息队列中,或者可能发送电子邮件/短信/其他)

我理解通过正确的配置,我们可以让系统成为事务性的(永远不会丢失任何消息)并且可以只发送一次,因此没有重复消息的机会。

应用程序/服务将是多线程的以处理消息,其中将有成百上千的消息。

但是在处理消息或通过服务生命周期期间,如果服务器崩溃怎么办?如果服务器重启怎么办?如果服务出于某种原因抛出异常怎么办?怎么可能不丢失该消息,但如何将其放回队列等待再次处理?另外,如何确保该服务是健壮的,以使其再次产生自己?

我很感激这里的任何建议和细节。有很多东西可以吸收,WCF/MSMQ 提供了很多选项。

4

2 回答 2

9

你的假设:

我猜 MSMQ 将托管在单独的服务器上。

是不正确的。MSMQ 安装在所有想要参与消息队列的机器上。

将有 2 个 WCF 服务。一个用于传入消息,另一个用于传出消息

在最典型的配置中,目标队列对于侦听服务是本地的。

例如,您的 ServiceA 将有一个从中读取的本地队列。ServiceB 也有一个本地队列,它可以从中读取。如果 ServiceA 想要调用 ServiceB,它会将消息放入 ServiceB 的本地队列中。

我理解通过正确的配置,我们可以拥有系统以便它可以是事务性的(永远不会丢失任何消息)

这是对的。这是因为 MSMQ 使用称为存储转发的消息传递模式。请参阅此处以获取解释。

本质上,假设没有消息丢失是安全的,因为从一台机器到另一台机器的消息传输实际上是在三个不同的事务下进行的。

  1. 第一个事务:ServiceA 写入它自己的临时本地队列。如果失败,事务将回滚,ServiceA 可以处理异常。
  2. 第二个事务:ServiceA 机器上的队列管理器将消息传输到 ServiceB 机器上的队列管理器。如果失败,则消息保留在临时队列中。
  3. 第三个事务:ServiceB 从本地队列中读取消息。如果 ServiceB 消息处理方法抛出异常,则事务将消息回滚到本地队列。

应用程序/服务将是多线程的以处理消息

这很好,除非您需要在消息处理链中保留订单。如果您需要有序处理,那么如果不实现重新排序器以重新应用订单,您就不能拥有多个线程。

我认为 MSMQ 可以单独托管并让 x 服务器共享该队列?

所有想要参与消息交换的服务器都安装了 MSMQ。然后,每个服务器都可以写入任何其他服务器上的任何队列。

我之所以这么想,是因为如果服务器宕机了怎么办?那么消息将如何发送/接收到 MSMQ

如果队列是事务性的,那么这意味着它们上的消息将持久保存到磁盘。如果服务器出现故障,那么当它恢复时,消息仍然存在。当服务器关闭时,它显然无法参与消息交换。但是,消息仍然可以“发送”到该服务器——它们只是对发送者保持本地(在一个临时队列中),直到目标服务器重新联机。

因此,通过拥有一台中央 MSMQ 服务器(并对其进行镜像/故障转移),就可以保证正常运行时间

使用消息队列的全部意义在于它是一种容错传输,因此您不需要保证正常运行时间。如果您有 100% 的可用性,那么几乎没有理由使用消息队列。

WCF 将如何收到传入消息的通知?

每个服务都将侦听自己的本地队列。当消息到达时,WCF 运行时会调用处理方法并处理消息。

发送消息失败如何通知服务

如果 ServiceA 未能向 ServiceB 发送消息,则永远不会通知 ServiceB 该失败。也不应该。ServiceA 将处理传输失败,而不是 ServiceB。在这种情况下,您的期望会在服务之间产生硬耦合,消息队列应该消除这种耦合。

于 2012-04-20T11:05:26.330 回答
0

即使临时关闭服务或重新启动计算机,MSMQ 也可以存储消息。
WCF 的主要目标是将消息从源传输到目标。不管是什么交通工具。在您的情况下,MSMQ 是 WCF 的传输,并且客户端和服务同时在线/可用并不明显。但是,当收到消息时,您有责任正确处理它,无论使用何种传输方式发送消息。

于 2012-04-20T10:42:35.253 回答