我们已经使用Microsoft的ServiceBrokerExternalActivator服务一段时间了,可以毫无问题地处理ServiceBroker队列的外部激活。但在过去的一个星期里,一个错误不断发生,我无法弄清到底是怎么回事。
每天至少一次,在随机时间,服务将遇到错误,并陷入停止状态。此时,所能做的就是终止进程并重新启动服务。检查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.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更新和加载之外,服务器上没有任何变化,但出于某种原因,此错误从7月16日左右开始出现。打开详细的日志记录,我可以看到它比我预期的检查点要多得多,当发生错误时,它总是在前一个检查点的一两秒钟内。
任何关于下一步该往哪里看的帮助或指示都将非常感谢,因为我正在为这一个撕我的头发。