【问题标题】:NServiceBus and remote input queues with an MSMQ clusterNServiceBus 和带有 MSMQ 群集的远程输入队列
【发布时间】:2012-03-28 12:00:31
【问题描述】:

我们希望将 NServiceBus 的发布/订阅功能与 MSMQ 集群一起使用。让我详细解释一下:

  • 我们有一个 SQL Server 群集,它还托管 MSMQ 群集。除了 SQL Server 和 MSMQ,我们不能在这个集群上托管任何其他应用程序。这意味着我们的订阅者不允许在集群上运行。
  • 我们有多个应用程序服务器托管不同类型的应用程序(从 ASP.NET MVC 到 SharePoint Server 2010)。目标是在所有这些应用程序之间进行发布/订阅。
  • 通过 pub/sub 的所有消息都是关键的,并且对业务具有重要价值。这就是为什么我们不想在应用服务器上使用本地队列,但我们想在集群上使用 MSMQ(如果我们丢失了其中一台应用服务器,我们不会冒丢失消息的风险,因为它们在集群上是安全的) .

现在我假设我可以在订阅者端简单地执行以下操作:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="MsmqTransportConfig" type="NServiceBus.Config.MsmqTransportConfig, NServiceBus.Core" />
    ....
  </configSections>

  <MsmqTransportConfig InputQueue="myqueue@server" ErrorQueue="myerrorqueue" 
        NumberOfWorkerThreads="1" MaxRetries="5" />
  ....
</configuration>

我假设这曾经受到支持,请参阅文档:http://docs.particular.net/nservicebus/messaging/publish-subscribe/

但这实际上抛出了一个异常:

启动端点时出现异常,已记录错误。原因: “MsmqTransportConfig”部分中的“InputQueue”条目已过时。经过 默认队列名称取自类命名空间,其中 配置已声明。要覆盖它,请使用 .DefineEndpointName() 使用字符串参数作为队列名称或 Func 参数 返回队列名称。在这种情况下,定义了“myqueue@server” 作为队列名称。

现在,异常清楚地表明我应该使用 DefineEndpointName 方法:

        Configure.With()
                 .DefaultBuilder()
                 .DefineEndpointName("myqueue@server")

但这会引发另一个记录在案的异常(输入队列应该在同一台机器上):

启动端点时出现异常,已记录错误。原因:输入 queue 必须和这个进程在同一台机器上。

如果我不能在集群上使用 MSMQ,如何确保我的消息是安全的?

调度员!

现在我也一直在研究调度程序,但这似乎也不能解决我的问题。我还假设调度程序无法从远程输入队列中获取消息?除此之外,如果调度员向工作人员发送消息,并且工作人员宕机,我的消息就会丢失(即使它们没有被处理)?

有问题吗?

总而言之,这些是我在 NServiceBus 中的场景中想知道的事情:

  1. 我希望我的消息在 MSMQ 群集上是安全的,并使用远程输入队列。这是应该做还是不应该做的事情? NServiceBus 可以吗?
  2. 在这种情况下我应该使用调度程序吗?它可以从远程输入队列中读取吗? (我无法在集群上运行调度程序)
  3. 如果调度员向工作人员发送消息并且其中一名工作人员出现故障怎么办?我会丢失正在处理的消息吗?

【问题讨论】:

  • 您不想在远程队列上运行事务。使队列本地化,或者突袭应用程序驱动器,或者如果你有一个 san,将队列持久化到 san 驱动器而不是本地驱动器。

标签: msmq nservicebus


【解决方案1】:

菲尔的评论是正确的。

问题是,如果您设置虚拟化环境,则默认情况下您将获得实际需要的容错类型。在这种情况下,支持进程本地队列的 C 驱动器实际上位于 SAN 上的 VM 映像上。

【讨论】:

  • 这正是我想要的。我正在寻找一种使用 MSMQ 集群来确保所有消息安全的方法。但是根据您的评论,我与我们的管理员交谈,他们确认我所有磁盘都在 SAN 上,确保了消息的安全。这使得 MSMQ 集群的使用过时,允许我们使用本地输入队列。为了更加安全,我们决定在 UnicastBusConfig 上使用 ForwardReceivedMessagesTo 属性
  • 嗯,为了通过 NServiceBus 实现 HA 需要虚拟化基础架构(例如 VMware vSphere HA)的 HA 功能,这似乎表明 NServiceBus 存在某种缺陷。我希望看到弹性层,包括 但不完全依赖 vSphere HA(例如 MSMQ 集群、主动-主动调度程序等)作为完全弹性设计的一部分。警告:尽管我已经构建了异步发布-订阅消息队列系统,但我没有编写过 NServiceBus。米
【解决方案2】:

您将需要一个 MessageEndpointMappings 部分,用于指向发布者的输入队列。您的订阅者使用此队列来丢弃订阅消息。这需要是 QueueName@ClusterServerName。请务必使用集群名称而不是节点名称。订阅者的输入队列将用于接收来自发布者的消息,这将是本地的,因此您不需要@servername。

有两种级别的故障,一种是传输关闭(例如 MSMQ),另一种是端点关闭(Windows 服务)。如果端点关闭,传输将处理将消息持久化到磁盘。冗余网络存储设备可能是有序的。

如果传输发生故障,假设它是 MSMQ,消息将在 Publisher 端备份。因此,您必须考虑消息的大小和数量,以计算您希望消息备份多长时间。由于 Publisher 是集群的,因此您可以放心,假设您正确规划了磁盘,消息最终会到达。

【讨论】:

  • 嗨,亚当。我已经在订阅者端使用 MessageEndpointMappings 来删除订阅消息,但这不是我的问题的一部分。我希望我的队列在集群中的订阅者端...
  • @Sandrino 查看我对答案的编辑,您将无法完全按照您的意愿行事,但如果您遵循上述设置,消息最终会到达。
猜你喜欢
  • 2014-12-17
  • 1970-01-01
  • 2014-12-01
  • 2012-04-18
  • 1970-01-01
  • 2012-11-04
  • 1970-01-01
  • 1970-01-01
  • 2018-09-02
相关资源
最近更新 更多