ASP.NET 状态服务 及 session丢失问题解决方案总结

 转自【http://blog.csdn.net/high_mount/archive/2007/05/09/1601854.aspx】

最近在开发一ASP.NET2.0系统时,在程序中做删除或创建文件操作时,出现session丢失问题。在网上搜了不少资料,最后终于解决了,采用了如下方法:

1、 asp.net Session 的实现
asp.net的Session是基于HttpModule技术做的,HttpModule可以在请求被处理之前,对请求进行状态控制,由于Session本身就是用来做状态维护的,因此用HttpModule做Session是再合适不过了。
ASP.NET 提供了 Session 对象,从而允许程序员识别、存储和处理同一个浏览器对象对服务器上某个特定网络应用程序的若干次请求的上下文信息。 Session 对应浏览器与服务器的同一次对话,在浏览器第一请求网络应用程序的某个页面时,服务器会触发 Session_onStart 事件;在对话超时或者被关闭的时候会触发 Session_onEnd 事件。 程序员可以在代码中响应这两个事件来处理与同一次对话相关的任务,如开辟和释放该次对话要使用的资源等。
   ASP.NET 的程序中要使用 Session 对象时,必须确保页面的 @page 指令中 EnableSessionState 属性是 True 或者 Readonly ,并且在 web.config 文件中正确的设置了 SessionState 属性。
  ASP.NET Session 的状态保持是由 web.config 文件中的 <system.web> 标记下的 <sessionstate> 标记的 mode 属性来决定的。该属性有四种可能的值: Off Inproc StateServer SQlServer.
  设为 Off 会禁用 Session.
  Inproc 是缺省的设置 , 这种模式和以前的 ASP 的会话状态 的方法是类似的 , 会话的状态会被保存在 ASP.NET 进程中,它的优点是显而易见的:性能。进程内的数据访问自然会比夸进程的访问快。 然而,这种方法 Session 的状态依赖于 ASP.NET 进程,当 IIS 进程崩溃或者正常重起启时,保存在进程中的状态将丢失。
  为了克服 Inproc 模式的缺点, ASP.NET 提供了两种进程外保持会话状态的方法。
  ASP.NET 首先提供了提供了一个 Windows 服务: ASPState , 这个服务启动后, ASP.NET 应用程序可以将 mode 属性设置为 “SateServer”, 来使用这个 Windows 服务提供的状态管理方法。
  除了在 web.config 文件中设置 mode 属性为 StateServer 外,还必须设置运行 StateServer 服务器的 IP 地址和端口号 . 如果 IIS 所在的机器运行 StateServer IP 地址就是 127.0.0.1, 端口号通常是 42424. 配置如下:
 mode=”StateServer”
 stateConnectionString="tcpip=127.0.0.1:42424"
    使用这种模式 , 会话状态的存储将不依赖 IIS 进程的失败或者重启 , 会话的状态将存储在 StateServer 进程的内存空间中。
   另一种会话状态模式是 SQLServer 模式。这种模式是将会话的状态保存在 SQL Server 数据库中的。使用这种模式前,必须至少有一台 SQL Server 服务器,并在服务器中建立需要的表和存储过程。 .NET SDK 提供了两个脚本来简化这个工作: InstallSqlState.sql UnInstallSqlState.sql 。这两国文件存放在下面路径中:
  <%SYSTEMDRIVER%>"Winnt"Microsoft.NET"Framework"<%version%>"
要配置 SQL Server 服务器,可以在命令行中运行 SQL Server 提供的命令行工具 osql.exe
  osql -s [server name] -u [user] -p [password] <InstallSqlState.sql
例如:
  osql -s (local) -u as -p “”-i  InstallSqlState.sql
做好必要的数据库准备工作后,将 web.config 文件中的 sessionstate 元素的 mode 属性改为 ”sqlserver”, 并指定 SQL 连接字符串。具体如下:
  mode="SQLServer"
    sqlConnectionString="data source=127.0.0.1;userid=sa;password=;Trusted_Connection=yes"
使用 SQLServer 模式处了可以使 Session 的状态不依赖于 IIS 服务器之外,还可以利用 SQL Server 的集群,使状态存储不依赖于单个的 SQL Server, 这样就可以为应用程序提供极大的可靠性。
 
2、 丢失原因:
转( 1 ): Asp.net 默认配置下, Session 莫名丢失的原因及解决办法
      正常操作情况下 Session 会无故丢失。因为程序是在不停的被操作,排除 Session 超时的可能。另外, Session 超时时间被设定成 60 分钟,不会这么快就超时的。
     
这次到 CSDN 上搜了一下帖子,发现好多人在讨论这个问题,然后我又 google 了一下,发现微软网站上也有类似的内容。
现在我就把原因和解决办法写出来。
原因:
由于 Asp.net 程序是默认配置,所以 Web.Config 文件中关于 Session 的设定如下:
<sessionState
mode = 'InProc'
stateConnectionString = 'tcpip=127.0.0.1:42424'
sqlConnectionString = 'data source=127.0.0.1;Trusted_Connection=yes'
cookieless = 'true'
timeout = '60' />

我们会发现 sessionState 标签中有个属性 mode ,它可以有 3 种取值: InProc StateServer?SQLServer (大小写敏感) 。默认情况下是 InProc ,也就是将 Session 保存在进程内( IIS5 aspnet_wp.exe ,而 IIS6 W3wp.exe ),这个进程不稳定,在某些事件发生时,进程会重起,所以造成了存储在该进程内的 Session 丢失。
[ asp Session 是具有进程依赖性的。 ASP Session 状态存于 IIS 的进程中,也就是 inetinfo.exe 这个程序。所以当 inetinfo.exe 进程崩溃时,这些信息也就丢失。 ]

哪些情况下该进程会重起呢?微软的 一篇文章 告诉了我们:
1 、配置文件中 processModel 标签的 memoryLimit 属性
2
Global.asax 或者 Web.config 文件被更改
3
Bin 文件夹中的 Web 程序( DLL )被修改
4
、杀毒软件扫描了一些 .config 文件。
更多的信息请参考 PRB: Session variables are lost intermittently in ASP.NET applications
解决办法:
      前面说到的 sessionState 标签中 mode 属性可以有三个取值,除了 InProc 之外,还可以为 StateServer SQLServer 。这两种存 Session 的方法都是进程外的,所以当 aspnet_wp.exe 重起的时候,不会影响到 Session

     
现在请将 mode 设定为 StateServer StateServer 是本机的一个服务 ,可以在系统服务里看到服务名为 ASP.NET State Service 的服务,默认情况是不启动的。当我们设定 mode StateServer 之后,请手工将该服务启动。 这样,我们就能利用本机的 StateService 来存储 Session 了,除非电脑重启或者 StateService 崩掉,否则 Session 是不会丢的(因 Session 超时被丢弃是正常的)。
     
除此之外,我们还可以 Session 通过其他电脑的 StateService 来保存 [ 如使用状态服务器 ] 。具体的修改是这样的。同样还在 sessionState 标签中,有个 stateConnectionString='tcpip=127.0.0.1:42424' 属性,其中有个 ip 地址,默认为本机( 127.0.0.1 ),你可以将其改成你所知的运行了 StateService 服务的电脑 IP ,这样就可以实现位于不同电脑上的 Asp.net 程序互通 Session 了。

     
如果你有更高的要求,需要在服务期重启时 Session 也不丢失,可以考虑将 mode 设定成 SQLServer ,同样需要修改 sqlConnectionString 属性。关于使用 SQLServer 保存 Session 的操作,请访问 这里
     
在使用 StateServer 或者 SQLServer 存储 Session 时,所有需要保存到 Session 的对象除了基本数据类型(默认的数据类型,如 int string 等)外,都必须序列化。 只需将 [Serializable] 标签放到要序列化的类前就可以了。
如:
[Serializable]
public class MyClass
{
    ......
}
具体的序列化相关的知识请参 这里
至此,问题解决。
备注
1 )使用 StateServer 模式
确保运行 ASP.NET 状态服务的服务器是要存储会话状态信息的远程服务器。该服务与 ASP.NET 一起安装,其默认位置为
< 驱动器 >:"systemroot"Microsoft.NET"Framework"version"aspnet_state.exe
在应用程序的 Web.config 文件中,
设置 mode=StateServer 并设置 stateConnectionString 属性。
例如, stateConnectionString="tcpip=sarath:42424"
2 )使用 SQLServer 模式
在运行 SQL Server 的计算机(它将存储会话状态)上运行 InstallSqlState.sql
(默认的安装位置为 < 驱动器 >:"systemroot"Microsoft.NET"Framework"version )。
这将创建一个名为 ASPState 的数据库,该数据库具有新的存储过程并且在 TempDB 数据库中具有 ASPStateTempApplications 表和 ASPStateTempSessions 表。
在应用程序的 Web.config 文件中,设置 mode=SQLServer 并设置 sqlConnectionString 属性。例如, sqlConnectionString="data source=localhost;Integrated Security=SSPI;Initial Catalog=northwind"
3 )示例
以下示例指定若干会话状态配置设置。

<configuration>
<system.web>
<sessionState mode="InProc"
cookieless="true"
timeout="20"/>
</sessionState>
</system.web>
</configuration>
要求
包含于: <system.web>
Web
平台: IIS 5.0 IIS 5.1 IIS 6.0
配置文件: Machine.config Web.config
配置节处理程序: System.Web.SessionState.SessionStateSectionHandler
请参见

ASP.NET
配置 | ASP.NET 设置架构 | SessionStateModule
作者:    来源:  ( 责任编辑 :webjx)--- ------------- 收集之二 ---------------------------------
[ 出现原因: ] Windows2003 的服务器中的 IIS6 加入了应用程序池来回收一些无用的进程的功能,当由于网站程序的错误访问量太多的导致的应用程序池会自动回收该进程,防止网站进入 死机 状态,而这时候的应用程序池的回收就会导致 session 变量被清除,就出现了 session 变量不见的现象。
为了解决这种在 Windows2003 下才出现的问题,我们在服务端起动 ASP.NET State Service 服务,并且在系统的 machine.config 做了一些改动。现在默认的情况下会话状态 mode StateServer 。如果您的网站根目录下也配有一个 web.config 配置文件,请把 mode="InProc" 改成 mode="StateServer" ,如下代码,就可以防止 session 变量的丢失:
<sessionState
mode="StateServer"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;Integrated Security=SSPI"
cookieless="false"
timeout="30"
/>
+
注:只适用于支持 asp.net 的用户。
 
转( 2 ):原因及一些解决之道
Session 保存在 State Server 里:
1. 启动服务 “ASP.NET State Service”
2.
然后,修改 web.config:
<sessionState
mode="StateServer"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
cookieless="false"
timeout="140000"
/>
注意 ://mode="StateServer" 这种模式下即使修改页面也不会丢失 session!
当然 :mode="InProc" 如果你的模式为这种 , 修改页面的时候会丢失 session!!!!!!

WebConfig 里将 Session Mode 设成 SQLServer 或者 StateServer 都不会丢 Session 的,
前者需要写入数据库,后者需要系统开 StateServer 服务
 
原因 1
bin
目录中的文件被改写, asp.net 有一种机制,为了保证 dll 重新编译之后,系统正常运行,它会重新启动一次网站进程,这时就会导致 Session 丢失,所以如果有 access 数据库位于 bin 目录,或者有其他文件被系统改写,就会导致 Session 丢失。 [ 目录的删除操作一定丢失 session asp.net 的内部机制对待目录有点像个守财奴,它死守着目录,你创建它不会管(往里加),一但创建他就会监视该目录,若你要删除或重命名它的(动它的目录),它就发生重起了。。 ]
原因 2
文件夹选项中,如果没有打开 在单独的进程中打开文件夹窗口 ,一旦新建一个窗口,系统可能认为是新的 Session 会话,而无法访问原来的 Session ,所以需要打开该选项,否则会导致 Session 丢失
原因 3
似乎大部分的 Session 丢失是客户端引起的,所以要从客户端下手,看看 cookie 有没有打开
原因 4
Session
的时间设置是不是有问题,会不会因为超时造成丢失。
[ 默认时间是 20 分钟,可以在 Web.Config 中设置 Session timeOut ,如改为 60 分钟等 ]
原因 5
IE
中的 cookie 数量限制(每个域 20 cookie )可能导致 session 丢失
原因 6
使用 web garden 模式,且使用了 InProc mode 作为保存 session 的方式
解决丢失的经验
1.
判断是不是原因 1 造成的,可以在每次刷新页面的时候,跟踪 bin 中某个文件的修改时间。
2.
Session 读写日志,每次读写 Session 都要记录下来,并且要记录 SessionID Session 值、所在页面、当前函数、函数中的第几次 Session 操作,这样找丢失的原因会方便很多
3.
如果允许的话,建议使用 state server sql server 保存 session ,这样不容易丢失
4.
global.asa 中加入代码记录 Session 的创建时间和结束时间,超时造成的 Session 丢失是可以在 SessionEnd 中记录下来的。
5.
如果有些代码中使用客户端脚本,如 javascript 维护 Session 状态,就要尝试调试脚本,是不是因为脚本错误引起 Session 丢失。
 
可能的原因 1
win2003 server
下的 IIS6 默认设置下对每个运行在默认应用池中的工作者进程都会经过 20 多个小时后自动回收该进程,造成保存在该进程中的 session 丢失。

因为 Session,Application 等数据默认保存在运行该 Web 应用程序的工作者进程中 , 如果回收工作者进程,则会造成丢失。

解决办法:
修改配置,设置为不定时自动回收该工作者进程,比如设置为当超出占用现有物理内存 60 %后自动回收该进程。通过使用默认应用程序池,可以确保多个应用程序间互相隔离,保证由于一个应用程序的崩溃不会影响另外的 Web 应用程序。还可以使一个独立的应用程序运行在一个指定的用户帐号特权之下。如果使用 StateServer 方式或者 Sql Server 数据库方式 来保存 Session, 则不受该设置的影响。

可能的原因 2
系统要运行在负载平衡的 Web 场环境 中,而系统配置文件 web.config 中的 Session 状态却设置为 InProc (即在本地存储会话状态) ,导至在用户访问量大时, Session 常经超时的情况。引起这个现象的原因主要是因为用户通过负载平衡 IP 来访问 WEB 应用系统,某段时候在某台服务器保存了 Session 的会话状态,但在其它的 WEB 前端服务器中却没有保存 Session 的会话状态,而随着并发量的增大, 负载平衡会当作路由随时访问空闲的服务器,结果空闲的服务器并没有之前保存的 Session 会话状态

解决办法:
1.
当您在负载平衡的 Web 场环境中 运行 ASP.NET Web 应用程序时,一定要使用 SqlServer StateServer 会话状态模式 在项目中我们基于性能考虑并没有选择 SqlServer 模式来存储 Session 状态,而是选择一台 SessionStateServer 服务器来用户的 Session 会话状态 。我们要在系统配置文件 web.config 中设置如下:
<sessionState
mode="StateServer" cookieless="false" timeout="240"
stateConnectionString ="tcpip=192.168.0.1:42424" stateNetworkTimeout="14400" />
还要添加一项
<machineKey
validationKey ="78AE3850338BFADCE59D8DDF58C9E4518E7510149C46142D7AAD7F1AD49D95D4" decryptionKey="5FC88DFC24EA123C" validation="SHA1"/> 

2.
我们同时还要在 SessionStateServer 服务器中启动 ASP.NET State Service 服务 ,具体设置:控制面板 >> 管理工具 >> 服务 >>ASP.NET State Service ,把它设为自动启动即可。  

3.
每台前端 WEB 服务的 Microsoft“Internet 信息服务 ”(IIS) 设置
            
要在 Web 场中的不同 Web 服务器间维护会话状态, Microsoft“Internet 信息服务 ”(IIS) 配置数据库中 Web 站点的应用程序路径(例如, "LM"W3SVC"2 )与 Web 场中所有 Web 服务器必须相同。大小写也必须相同,因为应用程序路径是区分大小写的。在一台 Web 服务器上,承载 ASP.NET 应用程序的 Web 站点的实例 ID 可能是 2 (其中应用程序路径是 "LM"W3SVC"2 )。在另一台 Web 服务器上, Web 站点的实例 ID 可能是 3 (其中应用程序路径是 "LM"W3SVC"3 )。因此, Web 场中的 Web 服务器之间的应用程序路径是不同的。我们必须使 Web Web 站点的实例 ID 相同即可。你可以在 IIS 中把某一个 WEB 配置信息保存为一个文件,其他 Web 服务器的 IIS 配置可以来自这一个文件。您如果想知道具体的设置请访问 Microsoft Support 网站:
 
(4):丢失问题集锦
SessionState Timeout) ,其主要原因有三种。
一:有些杀病毒软件会去扫描您的 Web.Config 文件,那时 Session 肯定掉,这是微软的说法。
: 程序内部里有让 Session 掉失的代码,及服务器内存不足产生的。
三:程序有框架页面和跨域情况。
第一种解决办法是 : 使杀病毒软件屏蔽扫描 Web.Config 文件 ( 程序运行时自己也不要去编辑它 )
第二种是检查代码有无 Session.Abandon() 之类的。
第三种是在 Window 服务中 ASP.NET State Service 启动。
http://community.csdn.net/Expert/topic/3100/3100218.xml?temp=.4426386
还有可能就是你在测试期间改动了,网站的文件。

下面是帮助中的内容 :
(ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.2052/cpguide/html/cpconsessionstate.htm)
ASP.NET 提供一个简单、易于使用的会话状态模型,您可以使用该模型跨多个 Web 请求存储任意数据和对象。
它使用基于字典的、内存中的对象引用(这些对象引用存在于 IIS 进程中)缓存来完成该操作。
使用进程内会话状态模式时请考虑下面的限制:
使用进程内会话状态模式时,如果 aspnet_wp.exe 或应用程序域重新启动,则会话状态数据将丢失。这些重新启动通常会在下面的情况中发生:
1 在应用程序的 Web.config 文件的 <processModel> 元素中,设置一个导致新进程在条件被满足时启动的属性,例如 memoryLimit
2 )修改 Global.asax Web.config 文件。
3 )更改到 Web 应用程序的 "Bin 目录。
4 用杀毒软件扫描并修改 Global.asax 文件、 Web.config 文件或 Web 应用程序的 "Bin 目录下的文件。
5 如果在应用程序的 Web.config 文件的 <processModel> 元素中启用了网络园模式,请不要使用进程内会话状态模式。否则将发生随机数据丢失。
 
我也碰到过。本机器上的 Session 或者 Cookie 丢失。
<sessionState
mode="StateServer"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
cookieless="false"
timeout="40"
/>
mode=""
的三个属性。本地 / 其他机器 /sqlserver
很多网络架构,各个服务器之间都是通过一台专门保存状态的服务器(专门的状态服务器)来保存比如说 session,cookie..
 
我以前遇到这种问题,我用了以下几个方法来解决。现在也没有这种情况发生了。
1、 release ,不要 debug 发布。
2、 <sessionState cookieless="true" cookieless 设为 true 。因为客户端禁用 cookie 时, session 也无效。
3、在 IIS 中把 Session 过期时间延长。
4、让杀毒软件不扫描 bin 文件夹下的文件和 Web.Config 文件
以上我是不明不白的做的。不过 Session 正常使用了!呵呵 ~~ 我幸运 !
 
没啥好讲的,不要用 Session 好了,直接用 Forms 认证 把,
我前两天的系统就是用这个搞定的,觉得挺好的。
刚碰到一个类似的问题:在使用 frameset 的时候, session 变量丢失。
在微软的网站上找到了解决的方法
http://support.microsoft.com/kb/323752/EN-US/
不知道是否有用?

IIS--->>
应用程序连接池 --->> 属性 ---->>[ 回收 ][ 性能 ][ 运行状况 ] 里的各项参数 尽量都往大的改 ^_^), 我不知道改拉那个才对的 , 反正我改完后所有的 session 都好拉 . 客户的网站和动网论坛的后台也跟着好拉。
 
(5): 模态窗口中打开新窗口的session丢失
         一直被这个问题郁闷。  在窗口 A 中使用 showModalDialog() 打开了一个新的模态窗口 B 。然后在 B 窗口中进行一些业务操作,最后还需要根据业务操作打印一些表单,结果此时在 B 中调用 open() 方法就会出现 session 丢失的现象, 提示用户重新登陆。 
         两天来一直没头苍蝇一样不停的试验各种方法。如果在这个窗口中采用打开非模态对话框的打开方法 showModelessDialog() 就没有任何问题,但是直接使用 open() 方法就是不能达到想要的效果。 在网上不停的 google ,到各大 bbs 寻找解答,提供的都是最简单的应用。好不容易找到一篇文章,其中提到 session 对象的有效范围, 却也没有具体提到我遇到的问题: 
IE : 
有效的窗品包括 
         1.Session 对象只在建立 Session 对象的窗口中有效。 
         2. 在建立 Session 对象的窗口中新开链接的窗口  
无效的窗口包括 
         1. 直接启动 IE 浏览器的窗口 
         2. 不是在建立 Session 对象的窗口中新开链接的窗口。(即作者在建立 Session 对象的 A 窗口弹出的 B 窗口上调用了 open() 方法。)
考虑只在建立 session 对象的窗口中有效,于是就在子窗口中重新使用 session.setAttribute() 方法,以为如此就可以成功,结果还是不行,郁闷。 
         早上起来突然来了灵感,既然子窗口中造成了 session 丢失,在父窗口中是无论如何还存在着 session 的变量的,我可以不必在子窗口中重新设置 session 变量,而可以直接调用父窗口的 javascript 函数 open() 方法可能会到目的吧。 不管如何先试试,结果果然如此。       很多时候问题就是这样的,想要偷懒,于是不自己钻研,到处寻求解答,最后还是得靠自己来搞定。

你可能感兴趣的:(asp.net)