【发布时间】:2011-08-05 15:28:39
【问题描述】:
我一直在寻找答案,因为它继续困扰着我。我们将用户登录信息和有关用户当前活动的其他数据存储在会话状态 (InProc) 中。每隔一段时间,我就会在尝试使用其中一个会话变量时遇到空引用异常。它发生在随机页面上,带有随机 Session 变量。我已经修改了 web.config httpRuntime 和 compliation 标签以防止 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 名登录该网站的用户在发生这种情况时不受影响。
收到错误的用户将备份,再次浏览相同的页面,它会正常工作。
我在运行带有 .NET 3.5 32 位和 4GB 内存的 IIS6 的 Windows Server 2003(32 位)上遇到了这个问题。大约一年前,作为我们服务器升级的一部分,我们得到了一个新的网络服务器 - Windows Server 2008(64 位) ) 运行具有 16GB 内存的 IIS 7。我将网站升级到 .NET 4.0 64 位。在新机器上仍然存在同样的问题(通常每天 1-3 次 - 一天中的随机时间)。
由于它的随机性,我无法在调试中实现它,但我相信它也会在我们的开发环境中随机发生。开发服务器的规格与生产服务器几乎相同。
两种环境都是隔离的,并作为单个 Web 服务器运行,而不是 Web 场的一部分。
我在想我可能会尝试实现一个状态服务器来摆脱 InProc 模式,但这只是在黑暗中的又一次尝试..
除了尝试状态服务器之外,我还能做些什么来确定这种情况何时发生或防止它发生?
【问题讨论】:
-
尝试在StackOverflow上搜索,有很多相同的问题有很多建议
-
您是否在负载均衡器后面运行两个 Web 服务器? (并且您确定您已经仔细检查了代码的设置位置以确保它们没有被覆盖)?
-
我一直在通过代码反复寻找我可能无意中覆盖它们的地方,但找不到我所在的任何地方。此外,它发生在不同会话变量的许多不同页面上 - 以及不同的用户/浏览器/平台。发生这种情况时,我找不到实例之间的任何关联
-
可能值得仔细检查您没有任何空的 catch 块。如果您尝试向会话添加一个不可序列化的对象(或包含不可序列化的嵌套对象的对象),它将抛出。但是,如果您正在捕获并吃掉抛出的异常,您最终可能会遇到一种情况,即您认为您在会话中添加了一些东西,但它却悄悄地失败了。
-
@mikemanne - 这是个好主意,如果/当我实现状态服务器时,我肯定会检查 NonSerializable 对象,但由于它当前是 InProc,我可以将任何对象添加到 Session,不仅可序列化的对象。这是我还没有完成状态服务器的原因之一 - 有很多地方要经过并确保所有对象都是可序列化的..