我已经花了相当长的时间寻找答案,因为这个问题一直困扰着我。我们将用户登录信息和其他有关用户当前活动的数据存储在会话状态(InProc)中。偶尔我会得到一个空引用异常,尝试使用其中一个会话变量。它发生在随机页面上,随机会话变量上。我已经修改了web.config的httpRuntime和compilation标记以防止appPool重新启动:
<httpRuntime requestValidationMode="2.0" waitChangeNotification="86400" maxWaitChangeNotification="86400" />
<compilation debug="False" strict="false" explicit="true" targetFramework="4.0" numRecompilesBeforeAppRestart="1000" />
我已经设置了IIS在凌晨3点重新启动应用程序池,以确保它不会在人们繁忙使用服务器时重新启动。同时,我将应用程序池重启记录在事件日志中,以确保我知道何时发生。
Dim runtime As HttpRuntime = GetType(System.Web.HttpRuntime).InvokeMember("_theRuntime", BindingFlags.NonPublic Or BindingFlags.Static Or BindingFlags.GetField, Nothing, Nothing, Nothing)
Dim shutDownMessage As String = runtime.GetType().InvokeMember("_shutDownMessage", BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.GetField, Nothing, runtime, Nothing)
Dim shutDownStack As String = runtime.GetType().InvokeMember("_shutDownStack", BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.GetField, Nothing, runtime, Nothing)
Dim evtSource As String = "ASP.NET"
Dim log As New EventLog
log.Source = evtSource
log.WriteEntry(String.Format("_shutDownMessage={0}{2}_shutDownStack={1}", shutDownMessage, shutDownStack, vbCrLf & vbCrLf), EventLogEntryType.Warning)
当应用程序池重启时,我会收到事件日志条目。但是这些错误发生时,应用程序池并没有重新启动。
当特定的会话变量丢失时,同一用户的大多数其他会话变量仍然存在。此外,通常有另外10-20个登陆该站点的用户不受影响。
出现错误的用户将返回,再次浏览相同的页面,然后就可以正常工作了。
我曾在运行IIS6且安装了.NET 3.5 32位和4GB内存的Windows Server 2003(32位)上遇到过这个问题。一年前我们进行了服务器升级,得到了一个新的Web服务器 - 运行IIS 7的Windows Server 2008(64位),内存为16GB。我将网站升级到了.NET 4.0 64位。在新机器上仍然遇到同样的问题(每天通常发生1-3次 - 在一天中的任意时间)。
由于它的随机性,我无法在调试中重现这个问题,但我确实认为它也会随机出现在我们的开发环境中。开发服务器的规格与生产服务器几乎相同。
两个环境都是隔离的,并作为单个Web服务器运行,而不是Web farm的一部分。
我想我可以尝试实现一个状态服务器以退出InProc模式,但这只是在瞎猜。
除了尝试状态服务器之外,还有什么其他方法可以识别此时的情况或防止它发生吗?