上文说了Asp.Net会话状态的Session源由,本节主要介绍下Session存储和配置。
一、客户端存储
根据上文说的Sessio源由,可知Session是存储在两个地方的。SessionID是存储在客户端的,主要是以Cookie存储的,而Session其他信息则是存储在服务器端的,而存储在服务器端是很多种模式的。SessionID存储在客户端,在ASP时,是完全存储在Cookie里的,这就会有一个问题,就是如果客户禁用Cookie时,会给他浏览web应用程序造成很大困扰。到了Asp.Net时代,SessionID在客户端的存储主要有两种方式:Cookie和Cookieless,其中Cookie方式是默认的存储方式,但是Cookieless 不是以Cookie存储的,而是以URL方式存储的,具体配置就是找到应用程序web.config下如下代码:
<sessionState mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
cookieless="false"
timeout="20"/>
把其中的cookieless="false" 改为cookieless="true"即可。
这样Session会话信息就不是以cookie存储的,而是以URL方式存储,同时会在URL地址上显示。做一个测试页面default.aspx,将cookieless="true",运行时URL会显示如下所示(其中红色方框即为Session会话信息,且为自动增加)。
二、服务器端存储
页面的所有代码都使用类似于字典样式的方式来引用Session对象,但Session在服务器端存储的方有点奇怪,是使用提供程序的模式来选择会话状态的存储方式。而Asp.Net使用三种存储提供程序:
1、InProc——进程中的会话状态存储
这个是当我们新建一个应用程序后系统默认采取的会话状态存储方式。在这种模式下会话状态存储在Asp.Net内存中的辅助进程中。它没有串行化,对象也没有退出进程,因互它是会话模式中速度最快的。但是会话是存储在内存中,存储的数据越多,服务器端所消耗的内存就越大,在会话超时前就可能耗尽内存。假设你访问某个应用程序并单击其中一个页面,就可能在正在进行的会话中存储一个40M的XmlDocument,如果你一直没有退出,这块内存就要被占用20分钟左右(根据配置超时时间长短不同)。
尽管该模式速度很快,但也有局限,即当你再次使用辅助进程或应用程序时,所有的会话数据都会丢失。另外当你因修改web.config配置文件或是修改文件时就会造成重新启动,因此此模式适合于只需要一个web服务器的小型应用程序。
该模式的配置实例如下:
<sessionState mode="InProc"
cookieless="false"
timeout="20"
/>
2、StateServer——进程外的会话状态存储
该会话状态是将会话数据存储到单独的内存缓冲区中,即存储在Asp.Net State Server服务aspnet_state.exe的进程中,再由单独一台机器上运行的Windows服务控制这个缓冲区。应用程序的代码运行在Asp.Net辅助进程中(aspnet_wp.exe 或w3wp.exe),状态服务运行在另一个aspnet_state.exe服务中,所以存储在会话中的对象不能存储为引用,而必须通过二进制串行化退出辅助进程。正因为需要串行化,所以此模式性能较InPoc会有所降低(后文将详解各种模式的性能问题)。
要使用该模式,首先需要在服务器启动aspnet_state服务,即使用Services MMC管理单元(控制面板-管理工具-服务)或在命令行(vs2008-visual studio tools-visual studio 2008 命令提示)运行如下net命令启动,启动成功后显示如下图:
使用该模式需要注意的是,必须在stateConnectionString属性中包含运行会话状态服务的IP地址和端口,默认端口为:42424,可以通过修改注册表项对该端口进行修改:HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesaspnet_stateParametersPort。
服务器端修改好后,还需要对客户端的Web.config进行修改,来指定服务所在的服务器,以及要监视的端口。配置实例如下:
<sessionState mode="StateServer"
stateConnectionString="tcpip=服务器ip:42424"
cookieless="false"
timeout="20"
/>
使用该模式的优点是进程隔离,并可以web form中共享。此模式不像SQLServer模式那样把数据存储在数据库中,它只是将数据存储在内存中。使用该模式后,会话状态的存储不依赖于IIS进程的失败或重启。这种模式下的数据在应用程序再次利用时会保存下来,但状态服务中止或计算机重新启动时,所有会话数据都会丢失。但如果状态存储在不同的机器上,web服务器再次使用和重新启动时,状态仍存在。
该模式的特点就是在响应/速度的平衡。
3、SQLServer——SQL会话状态存储
该会话状态存储在SQLServer数据库的专用数据库表中,可以使用aspnet_regsql.exe进行配置。
可以有两种方式对aspnet_regsql.exe进行配置,一种就是GUI方式,在系统盘:windowsmicrosoft.netframework<version>目录下。双击aspnet_regsql.exe,就会弹出asp.net SQL Server 安装向导,如下图所示:
根据窗口提示一步步操作即可,操作非常简单。
另一种方式就是使用命令行(打开命令行跟StateServer一样)方式。可以在命令提示窗口下输入aspnet_regsql -?查看所有命令选项,这里主要列出用于会话状态的几个选项。
会话状态选项 | 说明 |
---|---|
-ssadd | 添加对SQLServer模式会话状态的支持。 |
-ssremove | 删除对SQLServer模式会话状态的支持。 |
-sstype t/p/c | 支持的会话状态选项: t:表示temporary,会话状态数据存储在tempdb数据库中,管理会话的存储过程安装在ASPState数据库中。如果重新启动SQL,数据不会保存下来(默认)。 p:表示persisted,会话状态数据和存储过程都存储在ASPState数据库中。 c:表示custom。会话状态数据和存储过程都存储在定制的数据库中。必须指定数据库名。 |
-d<database> | -sstype是c时使用的定制数据库名。 |
如上表所示,共有三种方式支持会话状态:t、p和c,三者之间的区别在于,t选项不在SQLServer重启过程中保存会话状态数据,而p选项则是在SQLServer重启时保存会话状态数据,而c选项则可指定数据库,并使用-d参数,并指定数据库名称。
举个例子,其中SQLServer位于localhost,账户为sa,密码为***,在aspnetstate中设置永久保存数据,在命令行输入如下命令(重要提示:所有参数选项必须大写),运行结果如下:
打开SQLServer数据库,如下图所示,发现多出一个名叫ASPNETState的数据库,且其中有两个数据表:ASPStateTempApplications和ASPStateTempSessions,还创建一系列的存储过程,支持SQL和内存之间会话。
当然,也可以在Web应用程序中将会话状态存储在自己的数据库中,使用aspnet_regsql带-d<database>数据库名。以将会话状态存储在Northwind数据库中为例,SQLServer位于localhost中,命令如下所示:
数据库所添加的结果与上文保存在ASPNETState数据库中一样,同样增加两张数据表和若干存储过程。
将会话状态添加自定义的数据库中,添加会话状态成功后,就有一个提示,要求修改web.config文件,增加allowCustomSqlDatabase和sqlConnectionString属性(这两个属性是必须的)。
SQLServer模式配置实例如下:
<sessionState allowCustomSqlDatabase="true" mode="SQLServer"
sqlConnectionString="data source=localhost;uid=sa;pwd=***"
cookieless="false"
timeout="60"
/>
4、OFF和其它方式
实际上,以上不管是哪种会话状态管理模式,都是需要系统开销的。如果某个页面要有最佳性能,可以将页面的Page预编译指令的EnableSessionState设置为False,如果代码使用Session对象,就会抛出HttpException,停止页面的执行。即:
<%@ Page Language="c#" EnableSessionState="False"……%>
如果整个应用程序禁用会话状态,可在web.config文件中将sessionState的mode属性设置为Off。
5、各模式综述及性能评比
从以上的描述大家可以看到,这几种模式各有所长。进程内InProc模式是保存在Asp.Net工作进程映射的内存中,所以它性能最优。但其工作进程为维护性能,周期性地进行自动回收,会导致Session信息无故丢失。StateServer模式保存在aspnet_state进程中,这个进程独立asp.net进程外,不受工作进程回收的影响。运行稳定,但是性能有所损失,因为需要先Session信息序列化后只在到asp.net_state进程中,而读取的时候还需要将其反序列化。另外一个优点就是可以将Session信息保存在Web服务器之外的另一台服务器上。SQLServer模式则是将Session信息保存在SQLServer数据库中,保存也最持久,但是也有性能损耗,大约在15-25%。
下表列出了各种方式存储方式及性能对比。
方式名称 | 存储方式 | 性能 |
OFF | 不使用Session功能 | 无 |
InProc | 设置将Session存储在进程中,这是ASP.Net默认的方式 | 性能最优,速度最快 |
StateServer | 设置将Session存储在独立的状态服务进程aspnet_state.exe中 | 性能损失10-15% |
SQLServer | 设置将Session存储在SQLServer中 | 性能损失15-25% |
Custom | 自定义存储方式 | 根据存储方式定 |
6、几种方式如何选择
通过以上几种方式的综述及性能评比,性能方面:InProc>StateServer>SQLServer,稳定性方面:InProc<StateServer<SQLServer。也就是是说,性能好的,持久性不能,持久性好的性能又有缺憾。因此,必须在性能和强壮性之间找到平衡点,可以因人而异。建议一般情况都使用进程外模式。
三、Session访问
上文说了半天都是Session信息存储的各种模式,接着介绍如何访问这些Session信息。
存储信息:Session["mysession"]=TextBox1.text;
读取信息:string MySession=(string)session["mysession"];
注意在读取信息时,需要进行类型转换。
更详细的Session用法请见:Session使用介绍(本文还没写,之后完善)。
四、Web.config配置文件介绍
看到了本文最上边的代码了吧,接下来我们介绍下这个代码是哪里来的,这些都通过web.config进行配置的。那么接下来我们介绍下web.config文件。
首先介绍下Web.config是干什么的,估计用过MS的Visual Studio IDE做过开发的都知道,新建一个项目后系统自动添加了web.config文件,从后缀名config就可以看出一些端倪,config是configuration配置的缩写,其实就是一个配置文件。知道了这个是配置文件之后,那么这个配置文件是干什么的呢?主要就是存储应用程序的编写语言、安全认证、Session和数据库连接等信息。任何一个应用程序都可以通过System.Web名字空间进行引用,它是xml文件,可以通过任何的文本编辑器进行修改。web.config是有适用范围的,有全局性的、有局部性的。如果这个文件是在应用程序下,那么这个配置对整个应用程序有效,如果是在应用程序下边的一个文件夹,那么这个文件就覆盖掉应用程序的web.config文件,只对该文件夹有效。
关于Web.config配置文件中SessionState配置更详细的介绍请见的另一篇博文:Web.config配置文件详解。