ASP.NET 会话管理内部机制






3.52/5 (28投票s)
2004 年 8 月 3 日
4分钟阅读

314712
本文将深入探讨 ASP.NET 会话管理内部机制。
引言
由于 HTTP 协议的无状态性,每个 ASP.NET 应用程序都需要管理客户端会话信息。在新闻组、论坛和邮件列表中经常被问到的一个问题是:ASP.NET 会话管理是如何工作的?在 Web 场或高并发用户的大型网站中,哪种 ASP.NET 技术是管理会话的最佳方式?我们将从快速概述 ASP.NET 会话管理选项开始,然后深入探讨 ASP.NET 会话管理内部机制,并在最后提出一些建议。
ASP.NET 会话管理选项
ASP.NET 提供了三种会话状态存储模式,由您的 Web 应用程序的 Web.config 文件中 <sessionState>
标签的 mode
属性控制。下面是该标签的一个示例:
<sessionState
mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
cookieless="false"
timeout="20" />
Attribute | 选项 | 描述 |
---|---|---|
模式 |
指定会话状态的存储位置。 | |
关闭 |
禁用会话状态管理。 | |
InProc |
会话状态存储在 ASP.NET 工作进程的本地内存中。 | |
StateServer |
会话状态存储在 ASP.NET 工作进程之外,由 Windows 服务管理。该服务的地址由 stateConnectionString 属性指定。 | |
SQLServer |
会话状态存储在 ASP.NET 工作进程之外的 SQL Server 数据库中。该数据库的地址由 sqlConnectionString 属性表示。 |
现在,让我们看看会话存储的内部机制。
我们通过一个名为 Session
的属性来访问 Session 数据。这个 Session
属性由 System.Web.HttpContext
类和 System.Web.UI.Page
公开。(每个 ASP.NET 页面都会被转换为一个派生自 Page
类的类。)这个 Session
属性是 System.Web.SessionState
命名空间下的 HttpSessionState
类的一个对象,如上所示。
HttpSession
对象有一个名为 _dict
的私有成员,其类型为 SessionDictionary
(命名空间 System.Web.SessionState
),如下所示。
private SessionDictionary _dict;
SessionDictionary
是一个派生自 NameObjectCollectionBase
的内部类。
关系在一个小型类图中有所体现。
会话状态管理中最重要的部分是一个名为 SessionStateModule
的 HttpModule
。这个 HttpModule
与会话状态提供程序通信,并为每个 HTTP 请求填充 HttpSessionState
。这个 HttpModule
在您的 machine.config 文件的 <httpModules>
部分列出。
为了参考,我从我的计算机的 machine.config 文件中复制了该部分的一部分。
<httpModules>
<add name="OutputCache" type="System.Web.Caching.OutputCacheModule"/>
<add name="Session" type="System.Web.SessionState.SessionStateModule"/>
.
.
.
</httpModules>
对于您 ASP.NET 应用程序中的每个页面发起的 HTTP 请求,都会创建一个 HttpWorkerRequest
类型的对象,并由 HttpApplication
类的一个实例来处理。(有关 HTTP Pipeline 模型的完整讨论,请参阅“参考文献”中提到的 URL。)
在此请求处理过程中,会调用 HttpApplication
类的 InitModules()
方法。
下面的图 3 描绘了整个调用序列。
在 InitModules()
内部,所有在 <system.web>
/<httpModules>
部分列出的模块都会被初始化,即每个 HttpModule
的 Init
方法都会被调用,也就是会调用 SessionStateModule
的 Init
方法。在 SessionStateModule
的 Init
方法中,会话状态设置从您的 ASP.NET 应用程序的 web.config 文件的 <system.web>
/<sessionState>
部分读取,然后调用另一个方法 InitModuleFromConfig
。该方法的签名如下所示。
private void InitModuleFromConfig(HttpApplication app,
Config config, bool configInit);
参数 app
代表正在用于处理 HTTP 请求的 HttpApplication
类的一个实例。
InitModuleFromConfig
为 HttpApplication
的 InitInternal()
方法引发的与会话管理相关的事件添加各种事件处理程序。
下表显示了 SessionStateModule
中的哪些 EventHandler
与 HttpApplication
类的哪些事件相关联。
表:SessionStateModule 处理的 HttpApplication 事件 事件处理程序 | |
---|---|
事件 | 事件处理程序 |
AcquireRequestState |
BeginAcquireState , EndAcquireState |
ReleaseRequestState |
OnReleaseState |
EndRequest |
OnEndRequest |
请注意,此时会话状态数据尚未获取。在上述 EventHandler
被绑定之后,还会发生另一件重要的事情。根据您的 ASP.NET 应用程序配置文件中 <system.web>
/<sessionState>
部分的属性值设置,会话状态提供程序会绑定到 SessionStateModule
。
所有会话状态提供程序都实现了 IStateClientManager
接口。
下表显示了基于 sessionStateTag
的 mode
属性值用于管理状态的对象类型。
<System.web>\<sessionState> 的模式属性基于的会话状态提供程序 | |
---|---|
模式 | 处理会话状态的类 |
InProc |
InProcStateClientManager |
StateServer |
OutOfProcStateClientManager |
SQLServer |
SqlStateClientManager |
这个会话状态提供程序或 StateClientManager
存储在 SessionStateModule
的一个私有变量中。
一旦 SessionStateModule
的 Init()
方法将控制权交还给 HttpApplication
的 InitInternal
方法,处理就会继续,并引发 AcquireRequestState
事件。
此时会话状态才会被实际获取。当此事件被引发时,SessionStateModule
中先前绑定的事件处理程序(BeginAcquireState
)会被调用,然后调用 SessionStateModule
的 GetSessionStateItem
,后者会请求 StateClientManager
来获取会话状态。
为了判断性能差异,我们将逐一考察这些 StateClientManager
,看看会话数据是如何实际存储和检索的。欲知更多详情,敬请期待第二部分。