今天早上我们发生了一件非常可怕的事情。我们的 QA 团队(幸运的是他们在美国工作日开始之前开始工作)报告说我们的生产网站突然关闭了。那时我们还没有做过什么奇怪的事情;失败是突然的,同时影响了我们所有的环境。我进入生产 Web 服务器 (IIS),发现应用程序池已停止。我重新启动它,它立即再次崩溃。我检查了 Windows 事件查看器,在日志中发现以下错误:
来源:.NET 运行时
应用程序:w3wp.exe
框架版本:v4.0.30319
说明:进程因未处理的异常而终止。
异常信息:System.Security.Authentication.AuthenticationException 堆栈:在 System.Net.Security.SslState.ForceAuthentication(Boolean, Byte[], System.Net.AsyncProtocolRequest) 在 System.Net.Security.SslState.ProcessAuthentication(System.Net. LazyAsyncResult) 在 System.Net.Security.SslStream.AuthenticateAsClient(System.String) 在 LogentriesCore.AsyncLoggerBase.Run() 在 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) 在 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) 在 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) 在 System.Threading.ThreadHelper.ThreadStart()
来源:ASP.NET 4.0.30319.0
发生未处理的异常,进程终止。
应用程序 ID:/LM/W3SVC/1/ROOT
进程号:10156
异常:System.Security.Authentication.AuthenticationException
消息:根据验证程序,远程证书无效。
StackTrace:在 System.Net.Security.SslState.StartSendBlob(Byte[] 传入,Int32 计数,AsyncProtocolRequest asyncRequest)在 System.Net.Security 的 System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken 消息,AsyncProtocolRequest asyncRequest,异常异常) .SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartSendBlob(Byte[] 传入, Int32 计数, AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.ProcessReceivedBlob(Byte[] 缓冲区, Int32 计数, AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.StartReceiveBlob(Byte[] 缓冲区, AsyncProtocolRequest asyncRequest) 在系统.Net.安全。SslState.StartSendBlob(Byte[] 传入,Int32 计数,AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.ProcessReceivedBlob(Byte[] 缓冲区,Int32 计数,AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.StartReceiveBlob(Byte[ ] 缓冲区,AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.StartSendBlob(Byte[] 传入,Int32 计数,AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.ProcessReceivedBlob(Byte[] 缓冲区,Int32 计数,AsyncProtocolRequest asyncRequest)在 System.Net.Security.SslState.StartReceiveBlob(Byte[] 缓冲区,AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.StartSendBlob(Byte[] 传入,Int32 计数,AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState。 ProcessReceivedBlob(Byte[] 缓冲区,Int32 计数,AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.StartReceiveBlob(Byte[] 缓冲区,AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.StartSendBlob(Byte[] 传入,Int32 计数,AsyncProtocolRequest asyncRequest) 在 System.Net.Security .SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartSendBlob(Byte[] 传入, Int32 计数, AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.ProcessReceivedBlob(Byte[] 缓冲区, Int32 计数, AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.StartReceiveBlob(Byte[] 缓冲区, AsyncProtocolRequest asyncRequest) 在系统.Net.Security.SslState。System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResultlazyResult) 处的 StartSendBlob(Byte[] 传入,Int32 计数,AsyncProtocolRequest asyncRequest) System.Net.Security.SslStream.AuthenticateAsClient(String targetHost) at LogentriesCore.AsyncLoggerBase.Run() at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run (ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 在系统。Threading.ThreadHelper.ThreadStart()
这个堆栈跟踪不包含我们自己的任何代码;对我来说唯一有意义的是关于 Logentries 的一点。所以我立即打开web.config
文件并在配置中注释掉以下行Log4Net
:
<appender-ref ref="LeAppender" />
之前LeAppender
定义为
<appender name="LeAppender" type="log4net.Appender.LogentriesAppender, LogentriesLog4net">
<UseHttp value="false" />
<UseSsl value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level %logger [host=%P{log4net:HostName}:appdomain=%appdomain:referenceid=%property{referenceid}] - %message%newline" />
</layout>
</appender>
我重新启动了网站,一切又开始工作了,我们的客户一点也不聪明;很幸运,这一切都发生了,并在营业时间之前得到了解决(但已经很接近了!)。
这完全把我吓坏了。在我看来,Log4Net 应该是一个完全健壮的框架,不可能造成任何损害。在我看来,Logentries 的证书过期(或类似的东西),其结果是立即使我们的生产网站崩溃!
我们的 Log4Net/Logentries 设置有问题吗?
初始配置(不知道这可能有什么问题):
XmlConfigurator.Configure();
记录器本身是一个ILog
,它的分配方式如下:
_log = LogManager.GetLogger("Logger");
并且记录是这样完成的:
_log.Logger.Log(typeof(MyLogger), level, message, ex);
这里没有什么不愉快的。它已经运行了一年多。此外,正如我之前提到的,堆栈跟踪没有对我们自己的任何代码的任何引用,因此这可能不是由于我们编写的任何错误代码造成的。
任何想法出了什么问题,如何解决它,以及如何确保这种中断永远不会让我们的系统再次崩溃?