会话状态丢失

61

我有一个ASP.NET应用程序,用户在执行某些操作时无法成功完成,我假设这是由于失去了他们的会话(其中包含当前用户信息,并确定他们是否已登录)。

我不知道他们为什么会失去会话,所以我的第一个问题是:

通常会导致ASP.NET用户失去会话的原因是什么?

同时,我不知道用户何时失去会话,也无法自己重现:

如何跟踪用户何时失去会话?

以下是我的sessionState配置供参考:

<sessionState
           mode="InProc"
           cookieless="false"
           cookieName="My.Site.Com"
           timeout="480"/>

7
您可能在想太多了。您说您“假设”会话丢失,这可能是一次徒劳的追寻。也许您最好分析一下您收到的异常,并考虑其中的因素。其他可能包括使用Web farm或集群时出现的问题。由于会话模式为“InProc”,如果连接更改服务器,会话状态将会丢失。 - Russ
我知道我肯定没有使用 Web Farm,但我在虚拟机上。我承认,我只是假设,但我大约有80%的把握它是会话状态问题,至少在我排除其他可能性之前,我希望继续假设它是一个问题。 - Adam Ritenauer
1
对我来说,在我的web.config中添加一个机器密钥是有效的。我使用共享主机,并且此链接有助于创建一个本地密钥,然后发布它。链接 - Riaan Swart
11个回答

113

有很多原因会导致会话状态突然消失:

  1. 会话状态超时
  2. 更新web.config或其他文件类型,导致应用程序域重启
  3. IIS中的AppPool重启
  4. 您更新了大量文件的站点,ASP.NET会主动销毁应用程序域以重新编译和保留内存。

-

如果您正在使用IIS 7或7.5,以下是一些需要注意的事项:

  1. 默认情况下,IIS设置AppPools在一段时间不活动后自动关闭。
  2. 默认情况下,IIS将AppPools设置为每1740分钟重启一次(显然取决于您的根配置,但这是默认设置)
  3. 在IIS中,查看您的AppPool的“高级设置”。其中有一个名为“空闲超时”的属性。将其设置为零或高于默认值(20)。
  4. 在IIS中,检查您的AppPool的“回收”设置。在此处,您可以启用或禁用AppPool重启。向导的第2页是将每种类型的AppPool关闭记录到事件日志的方法。

如果您正在使用IIS 6,相同的设置适用(在很大程度上是相同的),但是获取它们进行日志记录更加困难。以下是一个链接,可以使IIS 6记录AppPool重启事件:

http://web.archive.org/web/20100803114054/http://surrealization.com/sample-code/getnotifiedwhenapppoolrecycles/

-

如果你正在更新Web应用程序上的文件,你应该预期所有会话都将丢失。这只是它的特性。然而,您可能不希望它发生多次。如果您更新15个或更多文件(aspx、dll等),很可能会在一段时间内有多次重启,因为用户访问网站时这些页面会被重新编译。请参阅以下两个链接: http://support.microsoft.com/kb/319947 http://msdn.microsoft.com/en-us/library/system.web.configuration.compilationsection.numrecompilesbeforeapprestart.aspx 将numCompilesBeforeAppRestart设置为更高的数字(或手动弹出AppPool)将消除此问题。
您始终可以处理Application_SessionStart和Application_SessionEnd以在创建或结束会话时收到通知。HttpSessionState类还具有一个IsNewSession属性,您可以在任何页面请求上检查以确定是否为活动用户创建了新会话。

最后,如果您的情况允许,我已经成功地使用了SQL Server会话模式。如果您在其中存储了大量数据(每个请求都会从SQL Server加载和保存完整数量的数据),则不建议使用该模式,并且如果您将自定义对象放入其中,它可能会很麻烦(因为它们必须是可序列化的)。但它帮助我在无法配置我的AppPool不回收几个小时的共享托管方案中。在我的情况下,我只存储了有限的信息,没有任何不良性能影响。此外,现有用户将默认重新使用其SessionID,我的用户从未注意到AppPool回收导致他们的内存中的会话已被删除,因为他们所有的状态都存储在SQL Server中。


哇...非常详尽的列表,谢谢!您列出了服务器端可能发生的所有情况,是否有任何可能会妨碍IIS识别请求并将其与正确的会话匹配的情况? - Adam Ritenauer
我该如何在服务器上配置IIS(而不是我的本地电脑)? - Mazdak Shojaie
刚刚在处理一个旧的asp.net应用程序,它是“20分钟默认”。 - JonH
即使当前的IIS默认为20分钟。@JonH - Adam Sills
@AdamSills - 我本以为我解决了它,但显然不是。我的问题更奇怪。在大约20分钟的不活动后,我的表单上的值会消失。会话状态没有丢失...但如果在代码后台中执行类似string text = MyDropDownlist.SelectedValue;的操作,则下拉列表为空/ null。这适用于任何asp.net控件。我已经检查了应用程序池的高级设置,并将其修改为60分钟,只是为了保持清醒。我不知道要寻找什么,甚至不知道要搜索什么... - JonH
显示剩余2条评论

5

我在ASP.NET 4.0中遇到一个情况,每次页面请求时我的会话都会重置(且我的SESSION_START代码会在每个页面请求上运行)。这不是每个用户的每个会话都会发生,但通常会发生,并且一旦发生,它会在每个页面请求上发生。

我的web.config sessionState标记具有与上述标记相同的设置。

cookieless="false"

当我将其更改为以下内容时...
cookieless="UseCookies"

...问题似乎消失了。 显然,true|false是ASP.NET 1中的旧选择。 从ASP.Net 2.0开始,枚举选择开始可用。 我猜这些选项已被弃用。 在过去,“false”值从未出现过问题-我只在ASP.NET 4.0上注意到过。 我不知道4.0是否发生了某些变化,不再正确支持它。

另外,我不久前才发现这一点。 由于问题以前是间歇性的,所以我认为我仍然可能会遇到它,但迄今为止,使用这个新设置可以解决问题。


3

您的会话丢失是因为....

请确保没有运行时错误,任何致命的异常都将使会话终止!

在 Microsoft 技术栈中,Visual Studio - 按 Ctrl + Alt + E - 打开所有异常,然后在调试模式下运行代码。任何致命异常都是会话丢失的原因。


+1 .非常有趣。我们遇到了完全相同的问题。在写入文本文件时出现未处理的错误导致会话被清除!在写入文本文件模块中,没有代码涉及到会话! - S Nash

2
在我的情况下,将AppPool-> AdvancedSettings-> Maximum Worker Proccesses设置为1有所帮助。

0

不知道是否与您的问题有关,但Windows 2008 Server R2或SP2已更改其IIS设置,导致会话持久性出现问题。默认情况下,它为HTTP和HTTPS管理单独的会话变量。当在HTTPS中设置变量时,这些变量仅在切换到HTTPS页面时才可用。

要解决此问题,可以进行IIS设置。在IIS管理器中,打开ASP属性,展开会话属性,并将安全连接上的新ID更改为False


0

我只是失去了一个不是字符串或整数而是数据行的会话。 将数据放入可序列化对象中并将其保存到会话中对我有用。


0

你可以在Global.asax的Session_Start和Application_Start中添加一些日志记录,以跟踪用户会话和整个应用程序的情况。

此外,如果你正在运行Web Farm模式(应用程序池中定义了多个IIS线程)或负载均衡,请注意,因为用户可能最终会访问到不具有相同内存的不同服务器。如果是这种情况,你可以将会话模式切换到SQL Server。


4
Web Farm不会是应用程序池的多个工作进程。那将是Web Garden。Web Farm将跨越多台服务器。 - Jeff Reddy

0

我为这个问题苦苦挣扎了14天。

以下是帮助我的方法:

  1. 检查 App Pool 的回收选项,进入“高级设置”。关闭所有选项,以防止自动回收。
  2. 检查 web.config 文件,找到 httpRuntime 下的 executionTimeout 属性,并增加其值。
  3. 检查 web.config 文件,找到 sessionState 下的 timeout 属性,并增加其值(我将其设置为300分钟)。
  4. 进入服务器的事件日志,检查应用程序日志中是否有未处理的异常导致工作进程崩溃。在代码中修复它们或使用trycatch来消除崩溃。
  5. 尝试将最大工作进程的值从0更改为1或反之亦然,这也可能解决此问题。

0

我曾经遇到过会话丢失的问题。每次重新加载页面时,我的会话都会被清除,然后在重新加载任何页面时,我的会话会以有效值返回...

我通过将IIS中的MaximumWorkerProcesses从0更改为1来解决了这个问题。


0
在我的情况下,会话状态由于负载均衡器而丢失。会话存储在一个服务器上,负载均衡器将下一个调用重定向到另一个服务器,其中会话状态丢失了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接