我们一段时间以来一直在使用Microsoft的Service Broker外部激活器服务来毫无问题地处理Service Broker队列的外部激活。但是在过去的一周中,错误不断发生,我无法深入探究。
每天至少随机出现一次,该服务将遇到错误并陷入“正在停止”状态。此时,所有可以做的就是终止进程并重新启动服务。检查EATrace.log文件会显示以下错误:
18/07/2018 09:59:45 EXCEPTION
ERROR = 90, Internal exceptions have occurred when External Activator is runtime checkpointing.
18/07/2018 09:59:45 EXCEPTIONDETAILS Inner Exception:
18/07/2018 09:59:45 EXCEPTIONDETAILS System.IO.IOException: Cannot create a file when that file already exists.
18/07/2018 09:59:45 EXCEPTIONDETAILS
18/07/2018 09:59:45 EXCEPTIONDETAILS at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
18/07/2018 09:59:45 EXCEPTIONDETAILS at System.IO.File.Move(String sourceFileName, String destFileName)
18/07/2018 09:59:45 EXCEPTIONDETAILS at ExternalActivator.LogManager.SaveRecoveryContext(LogRecoveryContext recoveryContext)
18/07/2018 09:59:45 EXCEPTIONDETAILS at ExternalActivator.LogManager.Checkpoint(LogRecoveryContext recoveryContext)
18/07/2018 09:59:45 EXCEPTIONDETAILS at ExternalActivator.LogManager.Log(LogRecord recoveryLogRec)
18/07/2018 09:59:45 EXCEPTIONDETAILS at ExternalActivator.ApplicationMonitor.OnProcessExited(ProcessMonitor processMonitor)
18/07/2018 09:59:45 EXCEPTIONDETAILS at ExternalActivator.ProcessMonitor.NotifySubscriber()
18/07/2018 09:59:45 EXCEPTIONDETAILS at ExternalActivator.ProcessMonitor.OnProcessExited(Object a, EventArgs b)
使用Reflector,我发现了有问题的SaveRecoveryContext方法:
private void SaveRecoveryContext(LogRecoveryContext recoveryContext)
{
this.m_file = File.Open(this.TempLogFileName, FileMode.Create, FileAccess.Write, FileShare.Read);
foreach (LogRecord recoveryLogRec in recoveryContext.List)
this.Write(recoveryLogRec);
this.CloseFiles();
File.Delete(this.LogFileName);
File.Move(this.TempLogFileName, this.LogFileName);
this.m_file = File.Open(this.LogFileName, FileMode.Append, FileAccess.Write, FileShare.Read);
}
请注意,LogFileName为EARecovery.rlog,TempLogFileName为EARecovery_temp.rlog。错误发生后检查日志文件夹时,只有临时文件,并且按预期删除了原始文件。
我的第一个想法是,也许有多个线程试图同时进行检查点并相互跳闸,但在堆栈跟踪中进入以下步骤:
public void Log(LogRecord recoveryLogRec)
{
lock (this)
{
this.Write(recoveryLogRec);
if (!recoveryLogRec.CanCompress)
return;
++this.m_recordsToCompress;
if (this.m_recordsToCompress <= 100)
return;
LogRecoveryContext local_0 = new LogRecoveryContext();
string local_1 = Global.GetEaContext();
Global.SetEaContext(Localized.GL_EaContext_RuntimeCheckpoint);
this.Checkpoint(local_0);
Global.SetEaContext(local_1);
}
}
我希望lock语句可以防止这种情况发生。
除了通常的Windows Udpates之外,服务器上没有任何更改,负载也没有增加,但是由于某些原因,此错误自7月16日左右开始出现。打开详细日志记录,我可以看到它在检查点上的数量远远超出了我的预期,并且当错误发生时,它总是在上一个检查点的一两秒之内。
在我将头发拔掉的任何帮助或指示物上,接下来的查找将不胜感激。
答案 0 :(得分:3)
这并非特定于Service broker,但是我以前见过这种情况,尤其是在代码中:
File.Delete(this.LogFileName);
File.Move(this.TempLogFileName, this.LogFileName);
如果后台进程(例如防病毒软件)将文件保持打开状态,则该文件可能不会立即消失。如果您正在运行Windows Defender等防病毒软件或其他产品,则可能需要将该文件夹列入白名单,以便它不会尝试扫描文件。
我可以提出的另一个建议,也是不相关的,是清除Windows temp文件夹。几年前,我遇到了一些问题,其中根据Windows内部文件的命名或跟踪方式,创建多个临时文件导致Windows问题。我没有您的链接,我也不认为这是您的问题,但是您可能想尝试一下。