【譯文】漫談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-Netweb

  

介紹

首先,我很是感謝閱讀我這篇文章的讀者,在初學者系列中,我寫了不少篇關於Session狀態管理的文章,也許這是我最後一篇關於Session狀態管理的文章了。算法

這篇文章將使你很是好地理解Session,在這篇文章中,我會包含Session的基礎知識,用不一樣的方式儲存Session對象,包含Web園(Web Garden)和Web農場(Web Farm)以及負載均衡等等情境。我也將詳細闡明Session在實際生產環境中的應用。但願您能喜歡這篇文章,歡迎您反饋您的見解和建議。sql

什麼是Session

         Web是無狀態的,他提供了一種新的方式:每次都經過用戶對服務器提交請求而渲染新的網頁。衆所周知,HTTP是一種無狀態協議,他不能經過頁面和客戶端保持鏈接。若是用戶須要增長一些信息和跳轉到了另外的頁面,原有的數據將會丟失,用戶將沒法恢復這些信息。咱們須要這玩意兒幹嗎呢?咱們須要保存信息!Session提供了一個在服務器端保存信息的方案。他能支持任何類型對象和用戶對象信息做爲對象保存起來。Session爲每個客戶端都獨立地保存,這意味着Session數據存儲着每一個客戶端的基礎信息。請看下圖:數據庫

 

每個客戶端都有一份獨立的Sessionwindows

         用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模式中所討論的幾個問題:

一、從StydentInfo 類中移除Serialize 特性(keyword)

二、重啓IIS再讀取Session數據

三、中止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模式?

一、  當咱們想將Session數據存儲在SQL Server以外的數據庫內時。

二、  當咱們必須使用一個已存在的(特定的)表來存儲Session數據的時候。

三、  當咱們須要使用自定義的SessionID的時候

如何配置自定義Session模式?

         咱們須要在web.config裏進行這樣的配置:

 

若是你想了解更多的關於自定義模式的信息,請查閱參考資料。

優缺點:

優勢:

一、  咱們能使用一個已存在的表(指定的表)來存儲Session數據。當咱們使用一個以前使用的數據庫時,這樣作是頗有用的。

二、  他獨立於IIS運行,因此重啓服務器對他也沒有影響。

三、  咱們能創建本身的Session ID邏輯來分配Session ID。

缺點:

一、  處理數據很慢。

二、  建立一個自定義的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中使用,總結以下:

一、  InProc Session Provider是最快的,由於全部數據都存在應用程序的內存裏,Session數據在IIS重啓,或者站點被回收的狀況下丟失,你能夠在用戶量較小的網站上使用這種模式,但別在Web Farm下使用。

二、  State Server模式:Session數據被存儲於aspnet_state.exe應用中,他在Web服務以外保存Session數據,因此Web服務出現問題不會對他的Session數據形成影響,在將Session數據存儲到StateServer以前須要序列化對象,在Web Farm中咱們能安全地使用這個模式。

三、  SQL Server模式:他將Session數據保存到SQL Server中,咱們須要提供鏈接串,咱們存儲時也須要對對象進行序列化,這種模式在實際Web Farm的生產環境中是很是有用的。

四、  咱們也能使用自定義模式,當咱們須要使用一個已經存在的表來存儲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

相關文章
相關標籤/搜索