我正在将netMsmqBinding与事务性队列一起使用,尽管调用WCF服务没有问题,但是在处理完消息后60秒,该服务抛出了MsmqException。
这是例外:
System.ServiceModel.MsmqException(0xC00E0051):从队列接收消息时发生错误:无法识别的错误
-1072824239(0xc00e0051)。确保已安装并正在运行MSMQ。确保队列可供接收。在
System.ServiceModel.Channels.MsmqInputChannelBase.TryReceive(TimeSpan
超时,消息和消息)
System.ServiceModel.Dispatcher.InputChannelBinder.TryReceive(TimeSpan
超时,RequestContext&requestContext)
System.ServiceModel.Dispatcher.ErrorHandlingReceiver.TryReceive(TimeSpan
超时,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事件中看到它们)
操作完成后,第一笔交易完成
(MsmqException引发)60秒后,第二个事务中止
wcf主机(IIS)有时出现故障(我对automatically recover it有一些代码,显然在.net 4中此行为已更改)
如果主机已损坏并自动恢复,则所有内容将在下一条消息中再次发生
如果主机没有损坏,第二笔交易将不会在下一次启动,并且一切都会顺利进行:)。
如果我回收AppPool,问题会再次出现
最佳答案
我发现了问题。
当我使用两个不同的msmq端点公开同一服务时,出于某些奇怪的原因,SMSvcHost.exe进程两次激活同一端点。
我刚刚写了一篇有关解决方案的文章:http://blog.jorgef.net/2011/07/msmqexception.html
希望对您有所帮助。
乔治