我有一个自托管的 WCF 服务(在 Windows 服务中运行)。此服务侦听 MSMQ 上的消息。该服务是 PerCall 和 Transactional,在 Windows 2008 R2、.NET 4.0、MSMQ 5.0 上运行。
每两周一次,该服务将停止处理消息。Windows 服务保持运行,但 WCF 服务主机本身停止。servicehost 出现以下异常:
时间戳:2015 年 3 月 21 日下午 5:37:06 消息:HandlingInstanceID:a26ffd8b-d3b4-4b89-9055-4c376d586268 发生并捕获了“System.ServiceModel.MsmqException”类型的异常。-------------------------------------------------- ------------------------------- 03/21/2015 13:37:06 类型:System.ServiceModel.MsmqException,系统.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 消息:从队列接收消息时出错:事务的操作顺序不正确。(-1072824239, 0xc00e0051)。确保 MSMQ 已安装并正在运行。确保队列可用于接收。来源:System.ServiceModel 帮助链接:错误代码:-1072824239 数据:System.Collections.ListDictionaryInternal TargetSite:Boolean TryReceive(System.TimeSpan, System.
搜索特定异常(“事务的操作顺序不正确”)不会产生很多信息。大多数关于如何修复故障服务的建议是在故障事件中重新启动服务主机。
我可以这样做,但我希望此异常有一个已知的可修复原因和/或是否有更清晰的方法来处理它。
我们的产品中遇到了这个问题,我们向微软开了一张票,最后他们承认这是 .NET Framework 中的一个错误,并且很快就会修复。
该问题在 Windows Server 2008 和 2012 上报告过,但从未在 2016 或 Windows 10 上报告过。
所以我们做了两个解决方案,建议所有客户升级到Windows 2016,并且我们添加了一段代码来处理服务主机重新启动服务的错误(您可以通过在WCF服务主机上重新启动MSMQ服务来模拟相同的错误)开了。
恢复服务的代码如下:
首先,为主机添加一个事件处理程序来处理“Faulted”事件:
SH.Faulted += new EventHandler(SH_Faulted);
//SH is the ServiceHost
Run Code Online (Sandbox Code Playgroud)
然后在事件处理程序内部
private static void SH_Faulted(object sender, EventArgs e)
{
if (SH.State != CommunicationState.Opened)
{
int intSleep = 15 * 1000;
//Abort the host
SH.Abort();
//Remove the event
SH.Faulted -= new EventHandler(SH_Faulted);
//I sleep to make sure that the MSMQ have enough time to recover, better make it optional.
System.Threading.Thread.Sleep(intSleep);
try
{
ReConnectCounter++;
LogEvent(string.Format("Service '{0}' faulted restarting service count # {1}", serviceName, ReConnectCounter));
//Restart the service again here
}
catch (Exception ex)
{
//failed.. .you can retry if you like
}
}
}
Run Code Online (Sandbox Code Playgroud)
最终错误会再次发生,但您的服务将继续正常工作,直到 Microsoft 解决问题或您升级到 2016
更新:经过进一步调查和微软的帮助,我们找到了问题的根本原因,即以下超时的顺序:
MachineLeveDTCTimeOut(20 分钟) >=
DefaultTimeOut(15 分钟) >= WCF 服务 transactionTimeout >
receiveTimeout()
因此,通过添加以下内容应该可以解决此问题:
<system.transactions>
<defaultSettings timeout="00:05:00"/>
</system.transactions>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
746 次 |
| 最近记录: |