我将 netMsmqBinding 与事务队列一起使用,尽管调用 WCF 服务没有问题,但该服务在处理消息后仅 60 秒就抛出 MsmqException。
这是一个例外:
System.ServiceModel.MsmqException (0xC00E0051):从队列接收消息时出错:无法识别的错误 -1072824239 (0xc00e0051)。确保 MSMQ 已安装并正在运行。确保队列可用于接收。在 System.ServiceModel.Channels.MsmqInputChannelBase.TryReceive(TimeSpan timeout, Message& message) 在 System.ServiceModel.Dispatcher.InputChannelBinder.TryReceive(TimeSpan timeout, RequestContext& requestContext) 在 System.ServiceModel.Dispatcher.ErrorHandlingReceiver.TryReceive(TimeSpan timeout, RequestContext& requestContext) )
我做了一些研究,调试和跟踪,我发现当收到一条新消息时,会打开两个事务,第一个事务在服务执行后提交,但第二个从未提交,所以在 60 之后秒,DTC 中止它抛出 MsmqException。这是操作定义:
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void SomeOperation(SomeParameter parameter)
{
// business logic
}
关于正在发生的事情的任何想法,我该如何解决这个问题?
更新:
配置:
<netMsmqBinding>
<binding name="TransactionalMsmqBinding" exactlyOnce="true" deadLetterQueue="System" receiveErrorHandling="Move">
<security mode="None"/>
</binding>
</netMsmqBinding>
...
<service name="SomeNamespace.SomeService">
<endpoint contract="SomeNamespace.ISomeService" bindingConfiguration="TransactionalMsmqBinding" binding="netMsmqBinding" address="net.msmq://localhost/private/services/someservice.svc">
</endpoint>
<endpoint contract="SomeNamespace.IAnotherService" bindingConfiguration="TransactionalMsmqBinding" binding="netMsmqBinding" address="net.msmq://localhost/private/services/anotherservice.svc">
</endpoint>
</service>
服务实施:
[ExceptionShieldingBehavior(typeof(ArgumentValidationException), typeof(ValidationServiceException))]
[AuthorizationAndAuditBehaviour]
[ServiceBehavior(Namespace = GlobalConstants.ServiceContractNamespace)]
public class SomeService: ISomeService, IAnotherService
{
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void SomeOperation(SomeParameter parameter)
{
// business logic
}
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void AnotherOperation(AnotherParameter parameter)
{
// business logic
}
}
服务合同:
[ServiceContract(Namespace = GlobalConstants.ServiceContractNamespace)]
public interface ISomeService
{
[OperationContract(IsOneWay = true)]
void SomeOperation(SomeParameter parameter);
}
[ServiceContract(Namespace = GlobalConstants.ServiceContractNamespace)]
public interface IAnotherService
{
[OperationContract(IsOneWay = true)]
void AnotherOperation(AnotherParameter parameter);
}
完整的行为:
- 客户端发送消息
- 服务已启动
- DTC 启动两个事务(我可以在 DTC 监视器和 TransactionManager.DistributedTransactionStarted 事件中看到它们)
- 第一个事务在操作完成后立即完成
- 第二个事务在 60 秒后中止(抛出 MsmqException)
- wcf 主机 (IIS) 有时会出现故障(我有一些代码可以自动恢复它,显然这种行为在 .net 4 中已经改变)
- 如果主机被破坏并自动恢复,下一条消息将再次发生
- 如果主机没有损坏,则第二次事务将不会在下一次开始,一切都会正常工作:)。
- 如果我回收 AppPool,问题又开始了