2

我的团队有一个 Windows 服务,它使用 http 绑定托管一个 wcf 服务。当 wcf 服务接收到消息时,它会立即使用 NetMsmqBinding 将消息发送到另一个 wcf 服务,该服务也托管在 Windows 服务中。msmq 服务处理消息并将其保存到我们的数据库中。

在开发和登台环境中,一切正常。但是,当我们部署到生产环境时,我们看到发送到我们服务的消息被乘以 n+1 倍(对于 n 条消息)。

例如:收到 1 条消息,2 条已保存到 DB。收到 4 条消息,20 条保存到数据库等。

我们怀疑它与 Transactions 的 msmq 服务设置有关,

Concurrency,和InstanceContextMode,但我们想不通。

该服务的设置是:

  • InstanceContextMode:默认值。
  • 并发模式:默认
  • 交易:TransactionScoreRequired = True 和 TransactionAutoComplete = True。
  • 重试计数 = 1,重试周期 = 1

我们使用 .Net 4、MSMQ 3.0 和 Windows server 2003。

关于可能导致此问题的任何想法?

编辑:

经过大量研究,我们发现了以下几点:

  • 当 wcf 运行时尝试为单个消息提交事务时,它会引发“事务已异步中止”异常。每次复制消息时都会引发此异常。
  • 在 wcf 跟踪中,我们没有看到除上述异常之外的任何异常。
  • 在 System.Transaction 跟踪中,我们看到正在打开一个事务(对于第一条消息),然后在 wcf 运行时创建该事务的克隆后(使用属性 RollbackIfNotCompleted=true),几秒钟后没有消息进入跟踪,然后同样的事情再次发生。

我们真是一头雾水……

谢谢

4

2 回答 2

3

MSMQ 不会删除消息,除非您的应用程序将其删除或 TimeToBeReceived 计时器到期。

如果我正确理解了您的环境,您的问题可能是由于收到消息的处理时间过长造成的。如果在同一事务中完成消息的接收和重新发送,则第一个 WCF 服务可能会在最终从队列中删除之前多次尝试读取同一消息。

这使我想到了您可以尝试的以下想法:

  • 您可以在收到原始消息后尝试创建一条内容相同的新消息并将新消息发送到下一个 WCF 服务。这应该会减少接收到的消息的生命周期。

  • 如果您需要保留相同的消息顺序,您可以尝试 Miker169 的建议将您的配置更改为InstanceContextMode.Single , ConcurrencyMode = ConcurrencyMode.Single( https://stackoverflow.com/a/2610093/219344 )

于 2013-03-04T14:51:08.710 回答
2

好吧,我们终于明白了:我们使用 Entlib 进行日志记录,并添加了一个 DB 侦听器。Entlib DB 侦听器使用服务的相同事务。当它试图将事务传递给数据库服务器时,会抛出一个错误,因为数据库服务器上没有正确配置 MSDTC,这会导致事务回滚。当 WCF 运行时尝试提交事务时,它会失败,因为它已经中止,然后它会尝试再次处理相同的消息(因为内置的重试机制)。

当我们修复 MSDTC 设置时,复制停止了。
现在,我们需要弄清楚的是:为什么回滚到服务事务会导致消息成倍增加?

于 2013-03-04T18:05:10.990 回答