为什么我的排队的WCF消息会悄无声息地消失?

9

我在THOR服务器上建立了一个事务性MSMQ队列。我能够使用以下代码从工作站向该队列发布消息:

var queue = new MessageQueue("FormatName:Direct=OS:thor\\private\\myqueue");
using (var tx = new MessageQueueTransaction())
{
   tx.Begin();
   queue.Send("test", tx);
   tx.Commit();
}

然而,当我尝试使用WCF连接时,我的消息从未出现在队列中。这是我正在使用的配置:

<system.serviceModel>
  <bindings>
    <netMsmqBinding>
      <binding name="ClientNewsFeedServiceBinding" durable="true" exactlyOnce="true">
        <security mode="None" />
      </binding>
    </netMsmqBinding>
  </bindings>

  <client>
    <!-- NewsFeed Service -->
    <endpoint name="INewsFeedService"
              address="net.msmq://thor/private/myqueue"
              binding="netMsmqBinding"
              bindingConfiguration="ClientNewsFeedServiceBinding"
              contract="Service.Contract.INewsFeedService" />
  </client>
</system.serviceModel>

代码如下:

using (var tx = new TransactionScope())
{
   var cf = new ChannelFactory<INewsFeedService>("INewsFeedService");
   var service = cf.CreateChannel();
   service.TestMessage("test");
   ((IChannel)service).Close();
   tx.Complete();
}

我没有收到任何异常信息,但是在THOR上没有发布任何消息。有什么想法吗?由于它只是静默失败,所以我甚至不知道如何进行调试。
更新: 如果我将我的MSMQ URI更改为"net.msmq://localhost/private/myqueue",那么它将发布到我设置的本地事务队列。队列本身的设置是相同的(也就是说,我执行了创建本地主机和THOR队列的相同步骤)。

1
这些消息是否出现在您的事务性死信队列中? - marc_s
不,事务性 DLQ 中没有任何内容显示。 - AgileJon
更新了我的答案-您是否在涉及的所有机器上检查了DTC? - marc_s
5个回答

3
我认为,如果你想在MSMQ服务器端使你的队列具有事务性,你需要在WCF绑定配置中指定更多的设置-尝试以下内容:
<bindings>
    <netMsmqBinding>
      <binding name="ClientNewsFeedServiceBinding" 
               durable="true" exactlyOnce="true">
        <security mode="None" />
      </binding>
    </netMsmqBinding>
  </bindings>

如果我没记错的话,您需要为netMsmq绑定添加 durable="true"exactlyOnce="true" 属性才能使其正常工作。
有一个非常好的教程可以帮助您让MSMQ和WCF完美地配合使用:

Tom在第3部分中介绍了事务队列,并提到:

exactlyOnce="true"属性是 WCF术语,用于使用事务消息队列。

“durable=true”只是指将消息立即刷新到磁盘上,而不是将其保存在服务器内存中。这样做会更慢,但是在服务器崩溃或断电的情况下,消息不会丢失。这是速度与可靠性之间的经典权衡。更新:由于您要跨机器边界进行操作,并且正在使用事务队列,请检查涉及的所有机器上的DTC(分布式事务协调器)是否正常工作?请参阅Tom的博客第3部分:“检查DTC配置”。我们的史诗般的旅程即将结束。实际上,如果你还在家里玩耍,你可以尝试运行具有事务队列的应用程序,看看它是否正常工作。如果它失败了,一个可能的原因是分布式事务协调器配置出现问题。以下是一些尝试的方法:

尝试过了,不行。我在原帖中添加了更新,说明如果将我的MSMQ URI更新为指向本地主机而不是THOR,则可以运行WCF代码。 - AgileJon

1
我遇到了同样的问题。在尝试了这里列出的所有想法后,我开始寻找其他的方法。事实证明,当您选择安全模式为时,我的消息的发件人属性将被留空(如下图所示)。

MSMQ Message properties

当消息发送到localhost时,此类消息将被接受,但是远程服务器将拒绝它。为了使其工作,您有几个选项:
  1. 启用身份验证
  2. 授予ANONYMOUS LOGON发送权限
第一种选择当然更安全,但它需要使用Active Directory集成安装MSMQ。

不确定WCF,但这解决了我使用NServiceBus和MSMQ遇到的类似问题:发送消息到另一台机器后,它们被静默丢弃。将“ANONYMOUS LOGON”权限添加到队列中解决了该问题(尽管我已经给了“每个人”完全控制权!) - bk0

0

在关闭通道之前,请尝试完成事务范围。

当您关闭通道时,您将失去与其的联系,因此它具有未提交的事务,最终将被丢弃。


那没起作用。你说的有道理,但似乎没有产生影响。 - AgileJon

0

我曾经遇到过类似的问题,希望这个清单能够帮到你:

  1. 连接性:我假设你的 DNS 记录是正常的,对吗?检查一下是否可以 ping 通...
  2. 跨不同域的权限:我之前在某些迭代中也遇到了这个问题,原因是权限。我的测试本地机器和服务器所在的域不同。请确保 Thor 和你的机器在同一个域内。虽然跨域也是可能的,但我没能成功(所以我把测试移到了同一个域内的机器上)
  3. 队列工具:虽然你可以从管理工具中看到队列,但我发现 Queue explorer 工具(http://cogin.com/mq/index.php)非常有用。你可以查看消息卡在哪里了。

注意:第一条可能已经没问题了,但为了保险起见我还是写上了...


0

你需要使用MsmqIntegrationBinding。由于WCF不知道这些消息是什么,它们没有被识别并被丢弃。


1
我认为MsmqIntegrationBinding是用于WCF应用程序和非WCF应用程序之间的互通。手动向队列添加内容的示例代码只是为了说明这不是简单的“关闭防火墙”问题。在生产环境中,队列将仅由WCF服务访问。 - AgileJon
抱歉,我的眼睛忽略了第二个客户端。客户端是XP机吗?我们在XP上遇到了Kerberos的问题。有一个补丁可以解决它。 - Adam Fyles

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接