認識asp.net會話狀態
作者:Eve Cole
更新時間:2009-07-01 16:44:49
一、會話狀態的功能
HTTP 是一個無狀態的協議,所以它不會自動指示一個請求序列是否都來自相同的客戶端,甚至不指示單一瀏覽器實例是否仍活躍地查看某個頁或網站。而使用ASP.net內建的會話狀態功能,可以使用我們做到
1、對從單一瀏覽器用戶端到伺服器上邏輯應用程式會話的請求進行自動識別和分類。
2、將會話範圍的資料儲存在伺服器上以供跨多個瀏覽器請求使用。
3.引發適當的可在應用程式程式碼中處理的會話生存期管理事件(Session_OnStart、Session_OnEnd 等)
二、會話狀態的標識
在建立會話時,伺服器會為每個會話產生一個單獨的識別。此標識以120 位元的SessionID 字串表示,該字串只包含URL 中所允許使用的ASCII 字元。 SessionID 值是使用保證唯一性和隨機性的演算法產生的,其中保證唯一性的目的是確保會話不衝突,保證隨機性的目的是確保懷有惡意的用戶不能使用新的SessionID 來計算現有會話的SessionID。
三、會話狀態的儲存方式
會話狀態有三種儲存方式
1.進程內會話狀態模式(Inproc):當我們新建一個Web程式後預設的採用的進程內會話狀態模式,這也是大家所普遍採用的模式。在這種模式下會話狀態儲存在本機的ASP.NET 輔助進程中,可以說到目前為止,進程內會話狀態模式可能是最快的存取選項。但會話中儲存的資料越多,Web 伺服器所消耗的記憶體就越多,這會潛在地增加效能降低的風險。
2、.NET 狀態伺服器模式(StateServer):會話狀態儲存在遠端進程中(例如,名為aspnet_state.exe的indows NT 服務中)
3、SQL 模式(SQLServer):會話狀態儲存到由SQL Server 管理的專用資料庫表中。
.NET 狀態伺服器模式和SQL 模式都可以稱為進程外會話模式,當儲存資料時,需要將資料序列化儲存到外部儲備庫,當讀取和資料時,需要將資料反序列化,複製到本地在會話字典中,所以請求導致效能下降了15%(進程外)到25% (SQL Server)。注意這只是一種粗略的估計。但在進程外儲存方案中,會話狀態存活的時間較長,使應用程式的功能更強大,因為它可以防止Microsoft? Internet 資訊服務(IIS) 和ASP.NET 失敗。透過將會話狀態與應用程式分離,您還可以更輕鬆地將現有應用程式擴展到Web Farm 和Web Garden 體系結構中。另外,會話狀態儲存在外部進程中,從根本上消除了由於進程循環而導致的周期性資料遺失的風險。
四、會話狀態的配置
會話狀態的設定是透過設定Web.config檔的<sessionState>節來實現的。以下介紹三種會話狀態的具體配置方法
1.進程內模式
進程內模式是預設的會話狀態模式。若要使用進程內模式,請將<sessionState> 元素的mode 屬性設為Inproc。
下面顯示了一個在進程內模式的設定範例。 http://www.downcodes.com
<configuration>
<system.web>
<sessionState mode="Inproc"
cookieless="false"
timeout="20"/>
</sessionState>
</system.web>
</configuration>
2、狀態伺服器模式
若要使用狀態伺服器,必須先確保ASP.NET 狀態服務運行在用於會話儲存的遠端伺服器上。此服務與ASP.NET 和Visual Studio .NET 一起安裝在下列位置:
systemrootMicrosoft.NETFrameworkversionNumberaspnet_state.exe
然後,在應用程式的Web.config 檔案中,將<sessionState> 元素的mode 屬性設為StateServer。最後,將connectionString 屬性設定為tcpip=serverName:portNumber。
下面是狀態伺服器模式的一個設定範例。
<configuration>
<system.web>
<sessionState mode="StateServer"
stateConnectionString="tcpip=dataserver:42424"
cookieless="false"
timeout="20"/>
</sessionState>
</system.web>
3、SQL Server 模式
若要使用SQL Server,首先在將儲存會話狀態的SQL Server 電腦上,執行InstallSqlState.sql 或InstallPersistSqlState.sql。兩個腳本都建立一個名為ASPState 的資料庫,它包含若干預存程序。
兩個腳本間的差異在於放置ASPStateTempApplications 和ASPStateTempSessions 表的位置。 InstallSqlState.sql 腳本將這些表新增至TempDB 資料庫,該資料庫會在電腦重新啟動時遺失資料。相反,InstallPersistSqlState.sql 腳本將這些表新增至ASPState 資料庫,該資料庫允許在電腦重新啟動時保留會話資料。
預設情況下,兩個腳本檔案均安裝在下面的位置:
systemrootMicrosoft.NETFrameworkversionNumber
然後,在應用程式的Web.config 檔案中,將<sessionState> 元素的mode 屬性設定為SQLServer。最後,將sqlConnectionString 屬性設定為Integrated Security=SSPI;data source=serverName;。
下面顯示了SQL Server 模式的一個設定範例。
<configuration>
<system.web>
<sessionState mode="SQLServer"
sqlConnectionString=" Integrated Security=SSPI;data source=dataserver;"
cookieless="false"
timeout="20"/>
</sessionState>
</system.web>
</configuration>
在SQL Server 模式中,也可以將會話狀態設定為在故障轉移群集中工作。故障轉移群集是兩個或更多相同的冗餘Web 伺服器,它們將會話資料儲存在單獨的電腦上的SQL Server 資料庫中。如果一個Web 伺服器發生故障,叢集中的另一個伺服器會接管它的工作,為請求提供服務,會話資料不會遺失。
若要設定故障轉移群集,請將Web 伺服器的Web.config 檔案中的<machinekey> 元素設定為相同的值。
然後將Web 伺服器的SQL 連線字串設定為指向電腦上儲存會話資料的SQL Server 資料庫。
五、會話狀態的訪問
你可以直接透過Session集合來實現對會話狀態的存取。為了與ASP 的早期版本相容,還可以透過應用程式物件上的Session.Contents 屬性來實現對會話狀態的存取。
下面的範例顯示在第一個網頁將兩個值寫入Session集合,然後再在第二個網頁讀取Session集合。註:此處省略了頁碼。
第一個網頁,將值寫入Session集合
dim name as string = "a"
dim id as integer = "1"
session("name") = name
session("id") = id
第二個網頁,從Session集合取得值
dim name as string = session("name")
dim id as integer = session("id")
'取得取得會話狀態集合中的項目數
dim i as integer = session.count
請注意,在進程內模式,未發生真正的序列化和反序列化,所以物件作為各自類別的活動實例儲存在會話狀態中。
而在進程外會話模式,因為使用了序列化和反序列化,所以你要根據情況對資料類型進行轉換。
如對日期值執行序列化操作,日期應為Int64 類型。
六、會話生存期管理事件
會話生存期管理事件有兩個Session_OnStart事件和Session_OnEnd事件,你可以在Global.asax.VB檔案中對它們進行設置
1、Session_OnStart事件
當從單一瀏覽器用戶端連接到伺服器上時,就會觸發Session_OnStart事件,它標誌著會話的開始,在此後的瀏覽過程中,將不會觸發該事件,除非此次會話逾時或被放棄。 Session_OnStart 事件是設定會話期變數的最佳時機,因為在造訪任何頁面之前都會先設定它們。
範例:以下的範例是比較常用到的統計線上人數的Session_OnStart 事件程式碼:
Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
'當事件發生時,將線上用戶的人數加1
Application("usercount") = Application("usercount") + 1
End Sub
2、Session_OnEnd事件
Session_OnEnd 事件在會話被放棄或逾時發生,它標誌著事件的結束。但請注意,只有InProc 模式支援該事件。你可以透過Web.config檔的<sessionState>節的timeout屬性來指定超時時限,如果使用者在該超時時限之內(以分鐘為單位,預設為20分
鐘)不刷新或請求網頁,則該會話將終止。可以利用Session_OnEnd 事件做一些清理工作。
範例:以下的範例是比較常用到的統計線上人數的Session_OnEnd 事件程式碼:
Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
Application("usercount") = Application("usercount") - 1
End Sub