ASP.NET 会话状态

 

罗布·霍华德
Microsoft Corporation

2000 年 12 月 28 日

注意 本文中的代码面向 Microsoft .NET 的 beta 版本。 某些代码可能需要重新处理,以便在更高版本的.NET Framework上正常运行。

在本月的专栏中,我们将加快步伐,并直接探讨 ASP.NET 的一些新功能。 首先,我们将 ASP.NET 会话状态与经典 ASP 进行比较,然后展示有关如何配置和使用 ASP.NET 会话状态的代码和示例。

会话定义为唯一用户与 Web 应用程序交互的时间段。 Active Server Pages (ASP) 希望为唯一用户会话保留数据的开发人员可以使用称为会话状态的内部功能。

以编程方式,会话状态只不过是字典或哈希表形状中的内存,例如键值对,可以在用户会话期间设置和读取这些键值对。 例如,用户选择要跟踪的股票,Web 应用程序可以将这些值存储在用户的 ASP 会话实例中:

Session("Stocks") = "MSFT; VRSN; GE"

在后续的页面上,读取这些值,并且 Web 应用程序可以访问这些值,而无需用户重新输入它们:

' Get Stocks, split string, etc.
Dim StockString
StockString = Session("Stocks")

ASP 通过向客户端提供在会话开始时分配给用户的唯一密钥来维护会话状态。 此密钥存储在客户端在每个请求时发送到服务器的 HTTP Cookie 中。 然后,服务器可以从 Cookie 中读取密钥,并重新扩充服务器会话状态。

ASP 会话状态问题

ASP 开发人员知道会话状态是一项出色的功能,但有些有限。 这些限制包括:

  • 进程相关。 托管 ASP 的进程中存在 ASP 会话状态;因此,影响进程的操作也会影响会话状态。 当进程被回收或失败时,会话状态将丢失。
  • 服务器场限制。 当用户在 Web 服务器场中从服务器移动到服务器时,其会话状态不会跟随他们。 ASP 会话状态特定于计算机。 每个 ASP 服务器都提供自己的会话状态,除非用户返回到同一服务器,否则会话状态不可访问。 虽然网络 IP 级别路由解决方案可以通过确保客户端 IP 路由到原始服务器来解决此类问题,但某些 ISP 选择为其客户端使用代理负载均衡解决方案。 其中最臭名昭著的是AOL。 AOL 等解决方案会阻止将请求路由到服务器的网络级别,因为无法保证请求者的 IP 地址是唯一的。
  • 依赖于 Cookie。 不接受 HTTP Cookie 的客户端无法利用会话状态。 某些客户端认为 Cookie 会损害安全和/或隐私,因此会禁用它们,从而禁用服务器上的会话状态。

这些是设计 ASP.NET 会话状态时考虑的几个问题集。

ASP.NET 会话状态

ASP.NET 会话状态解决了与经典 ASP 会话状态相关的上述所有问题:

  • 独立于进程。 ASP.NET 会话状态能够在与 ASP.NET 主机进程分开的进程中运行。 如果会话状态在单独的进程中,则 ASP.NET 进程可以来来去去,而会话状态进程仍然可用。 当然,你仍然可以在类似于经典 ASP 的进程中使用会话状态。
  • 支持服务器场配置。 通过移动到进程外模型,ASP.NET 还可以解决服务器场问题。 新的进程外模型允许场中的所有服务器共享会话状态进程。 可以通过将 ASP.NET 配置更改为指向公共服务器来实现此配置。
  • 与 Cookie 无关。 尽管经典 ASP 确实存在无 Cookie 状态管理问题的解决方案,但实现这些解决方案并非易事。 另一方面,ASP.NET 将无 Cookie 会话状态的复杂性降低到简单的配置设置。

让我们更详细地了解其中每个功能,包括如何配置设置。

使用 ASP.NET 会话状态

ASP.NET 中的会话状态设置通过 ASP.NET XML 配置文件 config.web 进行配置。 我们将在后面的列中更详细地介绍 config.web ,但对于会话状态的此讨论,让我们简要介绍一下。

Config.web

有两种类型的配置文件:计算机配置文件和应用程序配置文件,都名为 config.web。 两者是相同的,只不过计算机配置文件将设置应用于所有应用程序,但应用程序配置文件要么是限制性的,要么是扩展的,要么是逐个应用程序。

在 Beta 1 中,计算机 config.web 文件位于 WinNT\Microsoft.NET\Framework\v1.0.2204 目录中,而可选的应用程序配置文件位于应用程序的目录中。 Application config.web 文件是可选的,如果应用程序 config.web 文件不存在,则改用计算机 config.web 设置。 ASP.NET 会话状态设置可在计算机 config.web 文件中进行,并在特定应用程序的 config.web 文件中重写。

注意:config.web 所做的更改会立即应用,这与经典 ASP 不同,在经典 ASP 中,必须停止并启动服务器才能使设置生效。

会话配置

下面是用于配置 ASP.NET 应用程序的会话状态设置的示例 config.web 文件:

<configuration>
  <sessionstate 
      mode="inproc"
      cookieless="false" 
      timeout="20" 
      sqlconnectionstring="data source=127.0.0.1;user id=<user id>;password=<password>"
      server="127.0.0.1" 
      port="42424" 
  />
</configuration>

上述设置用于配置 ASP.NET 会话状态。 让我们更详细地了解每一个,并介绍之后的各种用途。

  • Mode。 模式设置支持三个选项:inproc、sqlserver 和 stateserver。 如前所述,ASP.NET 支持两种模式:进程内和进程外。 进程外状态管理还有两个选项:基于内存的 (stateserver) 和基于SQL Server的 (sqlserver) 。 我们稍后将讨论如何实现这些选项。
  • 无 Cookie。 ASP.NET 的无 cookie 选项是使用此简单的布尔设置配置的。
  • 超时。 此选项控制会话被视为有效的时长。 会话超时是一个滑动值;对于每个请求,超时期限设置为当前时间加上超时值
  • Sqlconnectionstring。 sqlconnectionstring 标识为用于模式 sqlserver 的数据库命名的数据库连接字符串。
  • Server。 在进程外模式状态器中,它将运行所需 Windows NT 服务的服务器命名为 ASPState。
  • 端口。 服务器设置附带的端口设置标识与模式状态器的服务器设置相对应的端口号。

示例会话状态应用程序

在使用会话状态之前,我们需要一个应用程序来测试它。 下面是一个简单的 Visual Basic® 应用程序的代码,该应用程序可写入会话状态 SessionState.aspx 并从中读取会话状态:

<Script runat=server>
  Sub Session_Add(sender As Object, e As EventArgs)
     Session("MySession") = text1.Value
     span1.InnerHtml = "Session data updated! <P>
                        Your session contains: <font color=red>" +
                        Session("MySession").ToString() + "</font>"
  End Sub

  Sub CheckSession(sender As Object, e As EventArgs)
    If (Session("MySession") = Isnull) Then
      span1.InnerHtml = "NOTHING, SESSION DATA LOST!"
    Else
      span1.InnerHtml = "Your session contains: 
                         <font color=red>" +             
                         Session("MySession").ToString() + "</font>"
    End If
  End Sub
</Script>

<form runat=server>
  <input id=text1 type=text runat=server>
  <input type=submit runat=server 
              OnServerClick="Session_Add" Value="Add to Session State">
  <input type=submit runat=server 
              OnServerClick="CheckSession" Value="View Session State">
</form>
<hr size=1>
<font size=6><span id=span1 runat=server/></font>

此简单页面为 “添加” 和“ 查看 ”按钮连接两个服务器端事件,并简单地将会话状态设置为文本框中的值。

我们可以更详细地查看四个常规配置设置:进程内模式、进程外模式、SQL Server模式和无 Cookie。

进程内模式

进程内模式仅意味着以类似于经典 ASP 会话状态的方式使用 ASP.NET 会话状态。 也就是说,会话状态在进程中进行管理,如果进程重新循环,则状态将丢失。 鉴于 ASP.NET 提供的新设置,你可能想知道为什么会使用此模式。 推理非常简单:性能。 会话状态的性能(例如,读取和写入会话状态字典所需的时间)在内存读取和写入会话状态字典时会快得多,因为跨进程调用会在数据来回封送或可能从SQL Server读取数据时增加开销。

进程内模式是 ASP.NET 的默认设置。 使用此设置时,唯一使用的其他会话 config.web 设置是无 Cookie 和超时。

如果我们调用 SessionState.aspx,设置会话状态值,并停止并启动 ASP.NET 进程 (iisreset) ,则循环进程之前设置的值将丢失。

进程外模式

.NET SDK 附带的是 Windows® NT 服务:ASPState。 ASP.NET 使用此 Windows 服务进行进程外会话状态管理。 若要使用此状态管理器,首先需要启动服务。 若要启动服务,请打开命令提示符并键入:

net start aspstate

你将看到:

图 1. 在命令提示符下启动 Windows NT 服务 ASPState

此时,Windows NT 服务 ASPState 已启动,可供 ASP.NET。 接下来,我们需要配置 ASP.NET 以利用此服务。 为此,我们需要配置 config.web

<configuration>
  <sessionstate 
      mode="stateserver"
      cookieless="false" 
      timeout="20" 
      sqlconnectionstring="data source=127.0.0.1;user id=<user id>;password=<password>"
      server="127.0.0.1" 
      port="42424" 
  />
</configuration>

仅将 模式 inproc 更改为 stateserver mode。 此设置指示 ASP.NET 在 和 port 设置中指定的server服务器上查找 ASP 状态服务,在本例中为本地服务器。

现在可以调用 SessionState.aspx,设置会话状态值,停止和启动 IIS 进程 (iisreset) ,并继续访问当前状态的值。

SQL Server模式

SQL Server模式选项类似于 Windows NT 服务的模式选项,只不过信息会保留到SQL Server而不是存储在内存中。

若要将 SQL Server 用作会话状态存储,我们首先必须创建必要的表和存储过程,ASP.NET 将查找标识的SQL Server。 .NET SDK 为我们提供了一个 SQL 脚本 (state.sql) 来执行此操作。

state.sql

state.sql 文件包含用于创建 ASPState 数据库的 SQL 命令。 此脚本创建两个表和多个存储过程。 ASP.NET 使用表和过程在SQL Server中存储数据。 建议通读 state.sql ,详细了解它正在执行的操作。

state.sql 文件可在 [system drive]\winnt\Microsoft.NET\Framework\[version]\ 中找到

应用 state.sql 脚本

若要应用 state.sql 脚本,请使用命令行工具SQL Server提供: osql.exe。 使用 sa 等效的 SQL 用户时,使用以下语法:

osql –S [server name] –U [user] –P [password] <state.sql

注意:安装 .NET SDK 时,将安装轻型版本的 SQL Server。

应显示以下内容:

图 2. 使用 SQL Server 命令行工具应用 state.sql 脚本

运行 osql 后,启动和停止SQL Server;状态.sql 添加的部分内容是需要运行的启动存储过程。 接下来,修改配置设置以将模式设置为 sqlserver ,并修改 sqlconnectionstring 以标识为 ASPState 数据库提供服务的相应SQL Server。 例如:

<configuration>
  <sessionstate 
      mode="sqlserver"
      cookieless="false" 
      timeout="20" 
      sqlconnectionstring="data source=MySqlServer;
                           user id=ASPState;
                           password=1Gr8State"
      server="127.0.0.1" 
      port="42424" 
  />
</configuration>

同样,与 Windows NT 服务状态管理器类似,我们现在可以调用 SessionState.aspx,设置会话状态值,停止和启动 IIS 进程 (iisreset) ,并继续访问当前状态的值。 事实上,我们可以对 SQL Server 进行群集化,这样,如果一个SQL Server恰好不可用,则复制其数据的另一台服务器可能会取代它。 这提供了 ASP 中不可用的可靠性级别。

无 Cookie 状态

我们可以为 ASP.NET 会话状态配置的最后一项新功能是无 Cookie 会话状态。 从本质上讲,此功能允许其客户端选择不使用 Cookie 的站点利用 ASP.NET 会话状态。

为此,请使用唯一标识会话的 ID 修改 URL:

https://localhost/(lit3py55t21z5v55vlm25s55)/Application/SessionState.aspx

ASP.NET 将修改在页面中找到的相对链接并嵌入此 ID。 因此,只要用户遵循站点提供的链接路径,就可以保持会话状态。 但是,如果最终用户重新写入 URL,会话状态实例很可能丢失。

IIS 4.0 资源工具包提供了类似的功能。 它是作为 ISAPI 筛选器实现的,该筛选器可以修改传入和传出字节流以写入和读取必要的信息。 此功能与 ASP.NET 功能之间的区别在于使用该功能所需的工作量。 在 ASP.NET 中,只需翻转 config.web 文件中的布尔值即可:

<configuration>
  <sessionstate 
      mode="stateserver"
      cookieless="true" 
      timeout="20" 
      sqlconnectionstring="data source=127.0.0.1;user id=<user id>;password=<password>"
      server="127.0.0.1" 
      port="42424" 
  />
</configuration>

将 cookieless 设置为 true 后,ASP.NET 将执行启用无 Cookie 会话状态所需的工作。 另请注意,无 Cookie 会话支持所有模式。

性能和可靠性注意事项

值得一提的是,在使用 ASP.NET 会话状态模式时应考虑的一些性能和可靠性问题。

  • 正在处理中。 进程中的性能最佳,因为会话状态内存保留在 ASP.NET 进程中。 对于托管在单个服务器上的 Web 应用程序、保证将用户重新定向到正确的服务器的应用程序,或者当会话状态数据不是关键 (可以重新构造或重新填充) ,这就是要选择的模式。
  • 进程外。 当性能很重要,但无法保证用户将从哪个服务器请求应用程序时,最好使用此模式。 使用进程外模式,可以获得从内存读取的性能,以及管理所有服务器状态的单独进程的可靠性。
  • SQL Server。 当数据的可靠性是应用程序稳定性的基础时,最好使用此模式,因为数据库可以针对故障情况进行群集化。 性能不如进程外快,但权衡在于更高的可靠性级别。

可分解性

本文中未介绍的内容以及我们将在以后的文章中介绍的内容是 ASP.NET 的可分解性。 从本质上讲,这是扩展或替换 ASP.NET 功能(如会话状态)的功能。 如果第三方提供扩展会话状态管理器,该管理器将会话数据存储在轻型目录访问协议 (LDAP) 目录(如 Netscape LDAP 目录)中,则可以替换默认 ASP.NET 会话状态实现。

总结

如你所看到的,ASP.NET 会话状态与 ASP 会话状态大不相同。 未绑定到 ASP.NET 进程的会话状态的新功能意味着开发人员可以开始在服务器场环境中使用会话状态,而无需担心客户端是否通过代理服务器。 此外,借助无 Cookie 状态功能,可以更轻松地使用会话状态,并保证所有客户端都可以利用会话状态功能。

在下一篇文章中,我们将介绍 ASP.NET 中的新跟踪功能。

Rob Howard 是 .NET Frameworks 团队 ASP.NET 项目经理。 他花任何业余时间,要么和家人在一起,要么在华盛顿东部钓鱼。