你的假设:
我猜 MSMQ 将托管在单独的服务器上。
是不正确的。MSMQ 安装在所有想要参与消息队列的机器上。
将有 2 个 WCF 服务。一个用于传入消息,另一个用于传出消息
在最典型的配置中,目标队列对于侦听服务是本地的。
例如,您的 ServiceA 将有一个从中读取的本地队列。ServiceB 也有一个本地队列,它可以从中读取。如果 ServiceA 想要调用 ServiceB,它会将消息放入 ServiceB 的本地队列中。
我理解通过正确的配置,我们可以拥有系统以便它可以是事务性的(永远不会丢失任何消息)
这是对的。这是因为 MSMQ 使用称为存储转发的消息传递模式。请参阅此处以获取解释。
本质上,假设没有消息丢失是安全的,因为从一台机器到另一台机器的消息传输实际上是在三个不同的事务下进行的。
- 第一个事务:ServiceA 写入它自己的临时本地队列。如果失败,事务将回滚,ServiceA 可以处理异常。
- 第二个事务:ServiceA 机器上的队列管理器将消息传输到 ServiceB 机器上的队列管理器。如果失败,则消息保留在临时队列中。
- 第三个事务:ServiceB 从本地队列中读取消息。如果 ServiceB 消息处理方法抛出异常,则事务将消息回滚到本地队列。
应用程序/服务将是多线程的以处理消息
这很好,除非您需要在消息处理链中保留订单。如果您需要有序处理,那么如果不实现重新排序器以重新应用订单,您就不能拥有多个线程。
我认为 MSMQ 可以单独托管并让 x 服务器共享该队列?
所有想要参与消息交换的服务器都安装了 MSMQ。然后,每个服务器都可以写入任何其他服务器上的任何队列。
我之所以这么想,是因为如果服务器宕机了怎么办?那么消息将如何发送/接收到 MSMQ
如果队列是事务性的,那么这意味着它们上的消息将持久保存到磁盘。如果服务器出现故障,那么当它恢复时,消息仍然存在。当服务器关闭时,它显然无法参与消息交换。但是,消息仍然可以“发送”到该服务器——它们只是对发送者保持本地(在一个临时队列中),直到目标服务器重新联机。
因此,通过拥有一台中央 MSMQ 服务器(并对其进行镜像/故障转移),就可以保证正常运行时间
使用消息队列的全部意义在于它是一种容错传输,因此您不需要保证正常运行时间。如果您有 100% 的可用性,那么几乎没有理由使用消息队列。
WCF 将如何收到传入消息的通知?
每个服务都将侦听自己的本地队列。当消息到达时,WCF 运行时会调用处理方法并处理消息。
发送消息失败如何通知服务
如果 ServiceA 未能向 ServiceB 发送消息,则永远不会通知 ServiceB 该失败。也不应该。ServiceA 将处理传输失败,而不是 ServiceB。在这种情况下,您的期望会在服务之间产生硬耦合,消息队列应该消除这种耦合。