【译文】漫谈ASP.NET中的Session

  最近这两天被一个Web Farm环境下的Session处理问题虐得很痛苦,网上到处找解决方案,在无意中翻看到这篇文章,感觉很不错,顺手查了一下,貌似没有现成的译文,于是一咬牙一跺脚把这篇文章翻译出来了,文章应该是作者的一个ASP.NET Session基础知识的一个合集,有的地方感觉是有重复,比较啰嗦,我基本上按照原文将他翻译出来了,小弟程序水平不高,英语水平更差(09年高考英语65分,满分150),自我感觉Session基础内容是讲清楚了,我粗浅的理解下,没有发现有什么错误了,文章较浅,请各位发现有什么不对的地方告诉我,我一定尽快处理,这篇文章很适合初学者看,作者说的很清楚,能把ASP.NET下Session的玩法看得较为清晰。另外我会在我另一篇博文中将我所遇到的问题以及解决办法和大家共享。原文地址:http://www.codeproject.com/Articles/32545/Exploring-Session-in-ASP-Net

  

介绍

首先,我非常感谢阅读我这篇文章的读者,在初学者系列中,我写了很多篇关于Session状态管理的文章,也许这是我最后一篇关于Session状态管理的文章了。

这篇文章将使你非常好地理解Session,在这篇文章中,我会包含Session的基础知识,用不同的方式储存Session对象,包含Web园(Web Garden)和Web农场(Web Farm)以及负载均衡等等情境。我也将详细阐明Session在实际生产环境中的应用。希望您能喜欢这篇文章,欢迎您反馈您的看法和建议。

什么是Session

         Web是无状态的,他提供了一种新的方式:每次都通过用户对服务器提交请求而渲染新的网页。众所周知,HTTP是一种无状态协议,他不能通过页面和客户端保持连接。如果用户需要增加一些信息和跳转到了另外的页面,原有的数据将会丢失,用户将无法恢复这些信息。我们需要这玩意儿干嘛呢?我们需要保存信息!Session提供了一个在服务器端保存信息的方案。他能支持任何类型对象和用户对象信息作为对象保存起来。Session为每一个客户端都独立地保存,这意味着Session数据存储着每个客户端的基础信息。请看下图:

 

每一个客户端都有一份独立的Session

         用Session进行状态管理是ASP.NET最好的特性之一,因为它是安全的,对于客户端是透明的,并且他能存储任何类型的对象。而在这些优点之外,有时Session会导致一些对性能要求较高的网站的性能问题。因为他消耗服务器的内存存储用户访问网站所需的数据,现在让我们来看一看Session对于您Web 应用的利弊。

Session的利弊

         接下来我们讨论普通情况下使用Session的利弊,我会描述每一种Session的使用情境。

优点:

         他能在整个应用中帮助维护用户状态和数据。

         他能让我们简单地实现存储任何类型的对象。

         独立地保存客户端数据。

         对于用户来说,Session是安全的、透明的。

缺点:

         因为Session使用的是服务器的内存,所以在用户量大的时候会成为性能瓶颈。

         在序列化和反序列化的过程中他也会成为性能瓶颈,因为在StateServer(状态服务)模式和SQL Server模式下我们需要对我们存储的数据进行序列化和反序列化我们所存储的数据。

         除此之外,Session的各种模式都有其利弊。接下来我们将讨论各种Session模式。

对Session进行读/写

读/写Session是非常简单的,就像使用ViewState一样,我们能使用System.Web.SessionState.HttpSessionState 这个类来与Session进行交互,这个类在ASP.NET页面内内建(提供)了Session。下面的代码就是使用Session进行存储的例子:

//Storing UserName in Session

Session["UserName"] = txtUser.Text;

 

接下来让我们来看如何从Session读取数据:

//Check weather session variable null or not
if (Session["UserName"] != null)
{
    //Retrieving UserName from Session
    lblWelcome.Text = "Welcome : " + Session["UserName"];
}
else
{
 //Do Something else
}

 

我们也能存储其他对象,下面的例子展示了如何存储一个DataSet到Session里

//Storing dataset on Session
Session["DataSet"] = _objDataSet;

 

下面的代码展示了如何从Session内读取DataSet

//Check weather session variable null or not
if (Session["DataSet"] != null)
{
    //Retrieving UserName from Session
    DataSet _MyDs = (DataSet)Session["DataSet"];
}
else
{
    //Do Something else
}

 

参考文献:

MSDN (read the session variable section)

Session ID

ASP.NET使用了120bit的标识符用以标识每个Session。这是足够安全的、不可逆的设计。当客户端和服务端进行通信的时候,在他们之间需要传输这个Session ID,当客户端发送request(请求)数据时,ASP.NET搜索Session ID,通过Session ID检索数据。这个过程通过以下步骤进行:

         客户端点击网站->客户端信息被Session储存

         服务端为客户端创建一个唯一的Session ID,并在服务端存储这个ID

         客户端通过发送带有SessionID的请求以获取在服务端保存的信息

         服务器端通过Session Provider从状态服务(State Server)中获取序列化后的数据并且进行类型强制转换成对象

以下为流程图片:

 

客户端、Web服务器、Session Provider的通信

 

参考文献:

SessionID in MSDN

Session模式和Session Provider

在ASP.NET中,有以下几种Session模式可以使用

InProc

StateServer

SQLServer

Custom

每一种Session State都有一种Session Provider。以下的图形将展示他们的关系:

 

Session state体系图

我们能在这些基础的Session State Provider中进行选择。当ASP.NET接收到带有Session ID的信息请求时Session State和他相应的Provider负责提供和存储对应的信息。下面的表展示了Session 模式以及Provider的名称:

Session State 模式

State Provider

InProc

In-memory object(内置对象)

StateServer

Aspnet_state.exe

SQLServer

SQL Server Database

Custom

Custom provider

除此之外,还有另一个模式:“OFF”,如果我们选择这个选项,Session将不能为这个应用提供服务。但是我们的目标是使用Session,所以我们将讨论上面四种的Session模式。

Session States

Session State模式基本上可以认为把所有的Session配置、维护都交给了Web应用。Session State他本身就是一个大东西,他基本上意味着你所有关于Session 的配置无论实在web.config或者页面后端代码。在web.config里<SessionState> 元素被用作Session的配置。在元素中可以配置的有Mode(模式)Timeout(超时)StateConnectionStringState连接字符串)CustomProvider(自定义的Provider等等。我们已经讨论过了每个部分的连接字符串在我们讨论Session mode之前,接下来我们简述以下Session的一些事件:

Session 事件

在ASP.NET中有两个可以使用的Session事件:

Session_Start

Session_End

你能处理应用中的这两个事件在global.asax这个文件里,当一个新的Session开启时session_start事件被触发,当Session被回收或是过期时Session_End 被触发:

void Session_Start(object sender, EventArgs e) 
{
    // Code that runs when a new session is started
}
 
void Session_End(object sender, EventArgs e) 
{
    // Code that runs when a session ends. 
}

 

参考文献:

Application and Session Events

Session 模式

我们已经讨论过Session模式,接下来说说这些模式的不同:

Off

InProc

StateServer

SQLServer

Custom

 

如果我们在web.config内设定Session Mode="off",Session将在应用中不可用,他的设置是这样的:

 

InProc Session 模式:

这是ASP.NET默认的Session模式,他在当前的应用程序域中存储Session信息。这是性能最好的Session模式。但是他最大的缺点在于:当我们重启服务的时候Session数据将会丢失。InProc模式有一些优缺点,接下来我们将详细这些点。

InProc概述:

我们已经说过,InProc模式Session数据将会储存在当前应用程序域中,所以他是最简单、快速、好用的。

 

InProc模式Session数据保存在应用程序域内的一个集合对象,他在一个应用程序池中进行工作,如果我们重启服务,我们将丢失Session数据。正常情况下客户端发送请求,State Provider从内存对象中读取数据并返回给客户端,在web.config中我们必须提供Session模式和设置过期时间

 

上面的设置中,设置了Session的过期时间为30分钟,这也可以从后台代码中进行配置。

Session.TimeOut=30;

 

在ASP.NET中有两个Session事件可以进行使用:Session_Start()  Session_End()而这种模式(后端代码控制)只支持Session_End()事件。这个事件在Session超时时被调用,一般情况下,InProc Session模式是这样的:

 

当Session过期时Session_End()事件被调用。InProc是一个非常快的处理机制,因为没有序列化地读/写过程,并且数据保存在相同的域内。

什么时候我们使用InProc模式呢?

InProc是默认的Session模式,他对小型应用程序和用户量比较小的程序非常合适,我们应尽量避免在Web园(Web Garden)和Web农场(Web Farm)情境下使用他(以后我会讲到这个情境)

优缺点:

优点:

         他把Session数据存储在当前应用程序域内,所以访问数据会非常的快速、简单、高效。

         在InProc模式中不需要对对象进行序列化存储。

         使用起来非常简单,就像ViewState一样。

缺点:

         虽然InProc是最快的,最通用的,也是默认的机制,但是他有许多限制:

         如果工作的应用进程被回收,Session数据将全部丢失。

         虽然他是最快的,但是当Session数据太大和用户过多时,他会由于内存的大量使用而影响整个程序的性能。

         我们不能在Web园环境中使用这种模式。

         这种模式不适合用于Web农场(Web Farm)环境中。

现在,我们来看看其他可用的方法来规避这些缺点,首先是StateServer模式:

StateServer Session模式

StateServer模式概述

这也叫做Out-Proc Session模式。StateServer使用了一个独立的Windows服务来提供Session服务,他独立于IIS,也能独使用一台服务器。StateServer的服务来自于aspnet_state.exe提供。这个服务也能和您的应用服务共同运行在同一台服务器上,注意他是独立于Web应用程序域的一个服务。这意味着你重启你的Web服务后Session数据依然存在。这个方案的缺点在于有一个性能瓶颈:数据读写需要进行序列化和反序列化,因为不是同一个应用程序域,所以他也增加了数据读写的性能消耗,因为他们是两个不同的进程。

 

配置StateServer Session模式

在StateServer模式里,Session数据存储在独立于IIS的一个服务里。这个进程作为一个Windows服务运行,你能在Windows服务管理器(MMC)或者命令行中进行启动。

 

默认情况下,ASP.NET StateServer(中文名:ASP.NET状态服务)默认情况下启动方式是“手动”我们必须将他设置为自动。

 

如果从命令行启动的化只需要输入:"net start aspnet_state";默认情况下,这个服务监听TCP端口42424,但是我们可以在注册表里改变这个设置,如图:

 

现在,我们来看一看web.config对StateServer的设置,在StateServer的设置里我们需要指定StateServer连接字符串stateConnectionString:指向运行StateServer的系统。默认设置下,StateConnectionString使用IP127.0.0.1(localhost)端口使用42424。

 

当我们使用StateServer,我们还能设置超时stateNetworkTimeOut 特性指定等待服务响应的秒数,即发出请求到取消响应的事件时间间隔。默认情况下是10秒。

 

当使用StateServer进行存储时对象将被序列化进行储存,而读取对象时,将对数据进行反序列化,我们来看下面的例子:

StateServer是如何工作的

我们使用StateServer来避免当重启Web服务时无谓的Session数据丢失。StateServer是在aspnet_state.exe进程作为一个服务来进行维护的,这个进程维护着所有的Session数据,但是在存储到StateServer之前我们需要对数据进行序列化。

 

如上图所示,客户端发送请求到Web服务器,Web服务器将Session数据存储在StateServer里,StateServer也许在当前的系统里,也可能在另一个系统里,但他一定是独立于IIS的,为了实现他,我们必须在web.config里进行配置stateConnectionString。例如我们设置指向127.0.0.1:42424,这将把数据存储在本地的系统内,为了实现改变StateServer指向的目的,我们改变了IP,并且确定aspnet_state.exe正常运行于这个系统上,接下来当你需要读写Session时(也就是通过修改IP来导致一个错误的指向),你就会引发下图这样的异常:

 

当我们存储一个对象到Session,对象将被序列化。系统利用State Provider将数据存储进StateServer。当读取数据时,State Provider将返回数据,完整的流程图如下图:

 

StateServer Session模式例子:

这是一个简单的使用StateServer Session模式的例子,我直接在IIS里创建这个例子,能轻松地明白他的用法:

步骤1:打开Visual Studio>文件>新建>网站。选择HTTP作为web应用的位置。

 

现在你打开IIS,你将会看到创建了一个虚拟目录,名字是你的应用名,在我的例子中是StateServer。

 

步骤2:创建一个简单的UI:他将获取一个学生的角色编号和名字,我们将保存名字和编号到StateServer Session里。我也将创建一个类:StudentInfo,这个类的定义如下:

[Serializable]
public class StudentInfo
{
    //Default Constructor
    public StudentInfo()
    {
       
    }
    ///<summary>
    /// Create object of student Class
    ///</summary>
    ///<paramname="intRoll">Int RollNumber</param>
    ///<paramname="strName">String Name</param>
    public StudentInfo(int intRoll, string strName)
    {
        this.Roll = intRoll;
        this.Name = strName;
    }
 
    private int intRoll;
    private string strName;
    public int Roll
    {
        get
        {
            return intRoll;
        }
        set
        {
            intRoll = value;
        }
    }
 
    public string Name
    {
        get
        {
            return strName;
        }
        set
        {
            strName = value;
        }
    }
}

 

现在来看后端代码,我增加了两个Button:一个是保存Session,另一个是获取Session:

protected void btnSubmit_Click(object sender, EventArgs e)
{
    StudentInfo _objStudentInfo = 
      new StudentInfo(Int32.Parse( txtRoll.Text) ,txtUserName.Text);
    Session["objStudentInfo"] = _objStudentInfo;
    ResetField();
}
protected void btnRestore_Click(object sender, EventArgs e)
{
    StudentInfo _objStudentInfo = (StudentInfo) Session["objStudentInfo"];
    txtRoll.Text = _objStudentInfo.Roll.ToString();
    txtUserName.Text = _objStudentInfo.Name;
}

 

步骤3:配置你的 web.config 的StateServer,在之前介绍过,请确保 web.config 在配置所指向的服务器上的State Server是处于开启并运行的状态。

步骤4:运行应用。

 

输入数据,点击Submit。

接下来的测试,我将完整的解释如何使用StateServer

首先:移除StudentInfo 类[Serializable ] 特性,然后运行应用。当你点解Submit按钮,你将看到如下的错误:

 

清晰地指出了在存储之前你必须序列化你的对象。

第二:运行程序,在点击了Submit按钮保存数据后,重启IIS

 

如果在InProc中,我保证你的Session数据将会丢失,但是在StateServer中,点击Restore Session按钮,你将获取你的原始数据,因为StateServer数据不依赖于IIS,它独立地保存数据。

第三:在Windows 服务管理程序(MMC)中停止StateServer服务,你再点击Submit按钮,你将看到如下错误:

 

因为你的StateServer进程没有运行,所以当你在使用StateServer的时候,请牢记这三点。

优点和缺点

基于上述讨论:

优点:

         StateServer独立于IIS运行,所以无论IIS出什么问题都影响不到StateServer的数据。

         他能在Web Farm和Web Garden环境中使用。

缺点:

         要进行序列化和反序列化,拖慢速度。

         StateServer需要保证正常运行。

我在这里停止StateServer的讲述,你将在负载均衡中看到他更多更有趣的点,Web Farm,Web Garden情境下。

         参考文献:

State Server Session Mode

ASP.NET Session State

SQL Server Session模式

SQL Server模式简介

ASP.NET这个Session模式提供给我们了更强的安全性和可靠性,在这个模式下,Session数据被序列化并存储到一个SQL Server的数据库中,这个模式缺点在于Session需要序列化和反序列化的读写方式成为了主要的性能瓶颈,他是Web Farm的最佳选择。

 

设置SQL Server,我们需要这些SQL脚本:

安装: InstallSqlState.sql

卸载UninstallSQLState.sql

最简单的配置方式是利用aspnet_regsql命令。

之前已经解释过了如何配置,这是最有用的状态管理方法在web Farm模式里。

我们为何使用SQL Server模式?

SQL Server Session模式提供了更安全、更可靠的Session管理。

他保证了数据在一个集中式的环境中(数据库)。

当我们需要更安全地实现Session时就应该使用SQL Server模式。

假如服务器经常需要重启,这是一个完美的解决方案。

这是一个完美解决web Farm和web园的方案(这个我将在后面详细解释)。

当我们需要在两个应用间共享Session时我们需要使用SQL Server模式。

配置SQL Server Session模式

在SQL Server模式中,我们的数据保存在SQL Server中,所以我们首先要在web.config里提供数据库连接字符串,sqlConnectionString 是被用来做这事的。

在连接字符串配置完成后,我们将要配置SQL Server,我将在这里演示如何用aspnet_regsql命令进行数据库配置。

第一步:进入命令行,进入到Framework version目录E.g. : c:\windows\microsoft.net\framework\<version>

第二步,带参运行aspnet_regsql命令。

 

下面是参数的使用:

Parameters

Description

-ssadd

增加 SQLServer 模式 session state.

-sstype p

P 持久化.将这些数据持久化存储于数据库中

-S

服务器名

-U

用户名

-P

密码.

运行结束后,你见看到如下的信息:

 

配置结束。

第三步:

打开SQL Server,查看数据库ASPState库,将有两张表:

ASPStateTempApplications

ASPStateTempSessions

 

更改设置中的连接字符串,建立一个像StateServer例子中那样的应用

点击Submit时保存Roll Number和用户名,打开数据库,进入ASPStateTempSessions 表,这是你保存的Session数据:

 

现在我们再来讨论以下StateServer模式中所讨论的几个问题:

1、从StydentInfo 类中移除Serialize 特性(keyword)

2、重启IIS再读取Session数据

3、停止SQL Server服务

我想这些问题我已经在StateServer解释得很清楚了。

(注:第一种将导致无法序列化对象,会抛出异常,第二种无影响,第三种,在关闭数据库服务时会有影响,而重启数据库服务将找回Session内的数据,因为他是持久化储存的。)

优缺点

优点:

         Session数据不受IIS重启的影响

         最可靠和最安全的Session管理模式

         他在本地中心化保存Session数据,能使其他应用方便地进行访问

         在Web Farm 和Web Garden情境下非常实用

缺点:

         和默认模式比较起来,会显得很慢

         对象的序列化和反序列化会成为性能瓶颈

         因为需要在不同的服务器上访问SQL Server,我们必须保证SQL Server的稳定运行。

参考资料:

         Read more about SQLServer mode

自定义Session模式

通常情况下,我们使用InProc模式、StateServer模式、SQL Server模式就够了,可是我们还是需要了解一些用户自定义Session模式的相关知识。这是一种相当有趣的Session模式,因为用户的Session全部交由了我们进行控制,甚至Session ID,你都能通过自己写算法来生成Session ID。

你能够容易地从基类SessionStateStoreProviderBase 开发出自定义的Provider,你也能通过实现ISessionIDManager接口来产生SessionID。

下图是自定义方法的处理过程:

 

Initialize 方法中,我们能设置一个自定义Provider。他将提供给Provider初始化连接。SetItemExpireCallback 被用作提供SessionTimeOut(Session过期),当Session过期时我们能注册一个方法进行调用。InitializeRequest 在请求发起的时候被调用,CreateNewStoreData 在创建一个SessionStateStoreData(Session数据存储类)实例时候被调用。

我们何时使用自定义Session模式?

1、  当我们想将Session数据存储在SQL Server之外的数据库内时。

2、  当我们必须使用一个已存在的(特定的)表来存储Session数据的时候。

3、  当我们需要使用自定义的SessionID的时候

如何配置自定义Session模式?

         我们需要在web.config里进行这样的配置:

 

如果你想了解更多的关于自定义模式的信息,请查阅参考资料。

优缺点:

优点:

1、  我们能使用一个已存在的表(指定的表)来存储Session数据。当我们使用一个之前使用的数据库时,这样做是很有用的。

2、  他独立于IIS运行,所以重启服务器对他也没有影响。

3、  我们能建立自己的Session ID逻辑来分配Session ID。

缺点:

1、  处理数据很慢。

2、  创建一个自定义的Session状态Provider是一个基础性(low-level)任务,他需要小心处理各种情况以及保证数据安全。

我推荐您使用第三方提供的Provider而不是自己写一套Provider。

参考资料:

Custom Mode

生产部署的概述:

在实际的生产工作环境中部署我们的应用对于一个Web开发者来说是一个非常重大的挑战。因为在大的生产环境中,有大量的用户数据需要处理,数据量大到一台服务器难以负载这么巨大的数据处理量。这个概念来自于Web Farm,Web Garden,负载均衡的使用。

         在几个月前,我部署了一个实际环境:这个环境要处理百万级的用户访问以及超过10个域控制器,通过负载均衡搭载了超过10台服务器和服务数据库。例如交易服务器、LCS服务器。最大的挑战来自于跨多个服务器的Session管理。下图对这个生产环境展示了一个简单的图形:

 

我将试着解释并让您记住各个不同应用场景。

应用程序池

这是当您在创建一个实际生产环境时最重要的一个东西。应用程序池是用在IIS里用来分隔不同的工作进程的应用程序的,应用程序池能分隔我们的应用程序,使其获得更好的安全性,可靠性和有效性。应用程序池的应用在服务器中当一个进程出现问题,或者被回收时其他进程不受影响。

        

     应用程序池的角色:

         应用程序池的配置角色是一个重要的安全措施,在IIS6和IIS7里。因为当应用程序访问资源时他指定了应用程序的身份。在IIS7里,有三种预定义的身份指定方式,这和IIS6是一样的。

        

应用程序池角色

描述

LocalSystem

内建于服务器上管理权限的账户. 他能访问本地和远程资源. 任何服务器的文件或者资源, 我们必须把应用程序的身份设置为 LocalSystem.

LocalServices

内置的本地身份验证. 他不能进行任何网络访问。

NetworkServices

这是应用程序池的默认身份, NetworkServices 是一个经过验证的本地用户账户权限。

建立和指定应用程序池

         打开IIS管理页面,右键单击应用程序池目录->新建

 

给应用程序池一个ID,然后点击OK。

 

现在,右键单击一个虚拟目录(我正在使用的StateServer站点)分配StateServerAppPool给StateServer虚拟目录。

 

现在这个StateServer站点运行在了一个指定的独立的应用程序池StateServerAppPool里。其他任何应用都不会影响到这个程序。这是独立应用程序池的主要优点。

      Web Garden

         默认情况下,每一个应用程序池都运行在一个独立的工作进程里(W3Wp.exe)。我们能分配多个进程给单个应用程序池,一个应用程序池跑多个进程,这样的情况叫做Web Garden(Web园),多个工作进程单个应用程序在很多情况下都能够有更优秀的输出性能和更少的相应时间,每一个工作进程都会有他们自己的线程和内存空间。

 

         如上图所示,在IIS里,将会有多个应用程序池,并且每个应用程序池至少有一个工作进程,而一个Web Garden将有多个工作进程。

         在你的应用程序里,使用Web园将必然出现一个限制条件:如果我们使用InProc模式,我们的应用程序将无法正确的工作,因为Session将工作在不同的进程里。为了避免这样的问题,我们将使用进程外(OurProc)的Session模式,我们可以使用State Server或者SQL Server Session模式。

      主要优点:

         在Web园内的工作进程对每个进程都共享请求,如果一个进程挂了,其他的进程还能正常工作,继续处理请求。

如何建立一个Web Garden?

右键单击程序池->Performance(性能?)选项卡->选择Web Garden(Web园)部分

 

默认情况下他的值为1,现在把他改为一个比1大的数字。

如何在Web园内指定Session?

我已经解释过InProc模式是在单个工作进程中进行处理,在进程内存储对象,现在,如果我们要处理多个进程,Session处理将会变得很困难,因为每个工作进程独享自己的内存。那么假如第一个请求数据到了WP1并且保存了Session数据,第二个请求到了WP2我将无法正确获得Session的数据,取值的话将会抛出异常。所以,请避免在Web Garden模式下使用InProc模式。

我们使用StateServer或者SQLServer模式对这种情况进行处理,之前解释过,这两种模式不依赖于工作进程,在之前的例子里也说过当IIS重启你依然能访问到Session数据。

Session 模式

是否推荐

InProc

No

StateServer

Yes

SQLServer

Yes

Web Farm和负载均衡

         这是在生产环境中最常见的情形,当你需要在多台服务器上部署你的应用时,使用这种模式的主要原因是我们要将负载均衡到多台服务器上,一个负载均衡器被用于分发负载到多台服务器上。

 

         我们来看上图,客户端通过URL发送请求时先到负载均衡器,然后通过负载均衡器将请求分发给服务器,负载均衡器将在不同的服务器之间进行请求的分发。

         现在我们如何处理我们的Session呢?

     在WEB Farm和负载均衡情况下处理Session

在Web Farm中处理Session是一个有挑战性的工作。

InProc:InProc Session模式,Session数据以对象形式被存储在工作进程中,每个服务器将有他自己的工作进程,并将保持Session数据在内存中。

 

         假如一台服务器down了,那么请求将会访问其他服务器,而其他服务器里是不存在相应Session数据的。所以在Web Farm情形下不推荐使用InProc模式。

         State Server:之前已经解释过如何使用和配置StateServer模式了,在WebFarm的环境下你将了解他是多么的重要,因为所有Session数据将在一个位置进行存储。

 

         记住,在web Farm环境里,你必须保证你有相同的<machinekey> 节在你所有的web服务器上,其他配置和之前描述的一致,所有的web.config文件都要有相同的配置属性(stateConnectionString)在Session State里。

         SQL Server:这是另一个选择,这也是在Web Farm环境里的最佳选择,我们首先需要配置数据库,接下来的步骤之前已经说过了。

 

如上图所示,所有的web服务器Session数据都将被存储于一个SQL Server数据库。请记住一点,在StateServer模式和SQL Server模式下你都将把对象进行序列化存储。当一台Web服务器挂掉的时候,负载均衡器将把请求分发到其他服务器他将能从数据库里取出Session数据,因为所有Session数据都是存放于数据库里的。

总之,我们能用StateServer和SQL Server模式来进行Web Farm的部署,我们需要尽量避免使用InProc模式。

Session和Cookie

         客户端使用Cookie来配合使用Session,因为客户端需要给每个请求提供合适的Session ID,我们可以使用下列的方法:

     使用Cookie

ASP.NET使用了一个特定的Cookie名叫作:ASP.NET_SessionId这是当Session集合被创建的时候自动提供的,这是默认设置,Session ID通过Cookie进行传送。

Cookie Munging 

         当用户向服务器发送一个请求时,服务器解码Session ID并将他加入到每个页面的链接里,当用户点击链接,ASP.NET编码Session ID并传送到用户所请求的页面,现在,请求的页面可以获取Session变量了。这一切都是自动完成的,当ASP.NET发现用户浏览器不支持Cookie时。

如何实现Cookie Munging 

         为了这个,我们必须保证我们的Session State为Cookie-less。

移除Session

         下面的方法被用来移除Session

方法

描述

Session.Remove(strSessionName)

从Session State中移除一个项目

Session.RemoveAll()

从Session集合中移除所有项目

Session.Clear()

从Session集合中移除所有项目. Note: Clear 和 RemoveAll. RemoveAll()没有区别Clear()是内部的.

Session.Abandon()

取消当前的Session。

启用和禁用Session

         从性能优化来说,我们可以启用或禁用Session,因为每个页面都进行读写Session会出现一些性能开销,所以,更合适地启用或者禁用Session,而不是使用他的默认配置:always。我们启用和禁用Session可以采取两种方式:

         页面级

         应用级

页面级

         我们能禁用Session在页面指令的EnableSessionState 属性中

 

         同样的,我们可以让他成为只读的,这将只允许访问Session而禁止写入信息到Session

 

应用级

         通过设置web.config的属性EnableSessionState 可以让Session在整个应用程序内被禁用,

 

         一般我们都是采用页面级的限制,这样能灵活控制Session的使用。

参考文献:

         How to Disable ASP.NET Session State

总结

         希望你现在能更熟悉Session了,如何使用Session,以及如何在Web Farm中使用,总结如下:

1、  InProc Session Provider是最快的,因为所有数据都存在应用程序的内存里,Session数据在IIS重启,或者站点被回收的情况下丢失,你可以在用户量较小的网站上使用这种模式,但别在Web Farm下使用。

2、  State Server模式:Session数据被存储于aspnet_state.exe应用中,他在Web服务之外保存Session数据,所以Web服务出现问题不会对他的Session数据造成影响,在将Session数据存储到StateServer之前需要序列化对象,在Web Farm中我们能安全地使用这个模式。

3、  SQL Server模式:他将Session数据保存到SQL Server中,我们需要提供连接串,我们存储时也需要对对象进行序列化,这种模式在实际Web Farm的生产环境中是非常有用的。

4、  我们也能使用自定义模式,当我们需要使用一个已经存在的表来存储Session数据时,在自定义模式中,我们也能创建自定义的Session ID,但是不推荐你自己来实现Provider,推荐使用第三方的Provider。

希望您能喜欢这篇文章,希望您能给我宝贵建议帮助大家共同提高,再次感谢您的阅读。

 

深入学习和参考文献

         我也增加了一些其他内容,这是我提供的一小部分链接以帮助您之后的学习。

ASP.NET Session Overview

ASP.NET Session State Overview

Different Session Modes

Web Farm-Load Balancing in ASP.NET

Enabling and Disabling Session Mode

Configuring Session Modes

 

许可证

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

译者注:本文章欢迎转载,但转载时请注明出处,以及遵守原作者协议。

关于作者

About the Author

 

Abhijit Jana

Technical Lead 
India 

.NET Consultant | Former Microsoft MVP - ASP.NET | CodeProject MVP, Mentor, Insiders| Technology Evangelist | Author | Speaker | Geek | Blogger | Husband
 
Blog : http://abhijitjana.net
Web Site : http://dailydotnettips.com
Twitter : @AbhijitJana
My Kinect Book : Kinect for Windows SDK Programming Guide

Follow on    Twitter

 

posted @ 2013-12-07 22:32  ULiiAn·竹  阅读(2916)  评论(14编辑  收藏  举报