認識ASP.NET會話狀態
一、會話狀態的功能
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。
下面顯示了進程內模式的一個配置設置示例。
2、狀態服務器模式
若要使用狀態服務器,必須首先確保 ASP.NET 狀態服務運行在用于會話存儲的遠程服務器上。此服務與ASP.NET 和 Visual Studio .NET 一起安裝在以下位置:
systemrootMicrosoft.NETFrameworkversionNumberaspnet_state.exe
然后,在應用程序的 Web.config 文件中,將 <sessionState> 元素的 mode 屬性設置為 StateServer。最后,將 connectionString 屬性設置為 tcpip=serverName:portNumber。
下面是狀態服務器模式的一個配置設置示例。
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 模式的一個配置設置示例。
在 SQL Server 模式中,也可以將會話狀態配置為在故障轉移群集中工作。故障轉移群集是兩個或更多相同的冗余 Web 服務器,它們將會話數據存儲在一臺單獨的計算機上的 SQL Server 數據庫中。如果一個 Web 服務器出現故障,群集中的另一個服務器會接管它的工作,為請求提供服務,會話數據不會丟失。
若要配置故障轉移群集,請將 Web 服務器的 Web.config 文件中的 <machinekey> 元素設置為相同的值。
然后將 Web 服務器的 SQL 連接字符串設置為指向計算機上存儲會話數據的 SQL Server 數據庫。
五、會話狀態的訪問
你可以直接通過Session集合來實現對會話狀態的訪問。為了與 ASP 的早期版本兼容,還可以通過應用程序對象上的 Session.Contents 屬性來實現對會話狀態的訪問。
下面的示例顯示在第一個網頁將兩個值寫入Session集合,然后再在第二個網頁讀取Session集合。注:此處省略了頁代碼。
第一個網頁,將值寫入Session集合
注意,在進程內模式,未發生真正的序列化和反序列化,所以對象作為各自類的活動實例存儲在會話狀態中。
而在進程外會話模式,因為使用了序列化和反序列化,所以你要根據情況對數據類型進行轉換。
如對日期值執行序列化操作,日期應為 Int64 類型。
六、會話生存期管理事件
會話生存期管理事件有兩個Session_OnStart事件和Session_OnEnd事件,你可以在Global.asax.vb文件中對它們進行設置
1、Session_OnStart事件
當從單個瀏覽器客戶端連接到服務器上時,就會觸發Session_OnStart事件,它標志著會話的開始,在此后的瀏覽過程中,將不在觸發該事件,除非此次會話超時或被放棄。Session_OnStart 事件是設置會話期變量的最佳時機,因為在訪問任何頁之前都會先設置它們。
示例:下面的示例是比較常用到的統計在線人數的Session_OnStart 事件代碼:
2、Session_OnEnd事件
Session_OnEnd 事件在會話被放棄或超時發生,它標志著事件的結束。但請注意,只有 InProc 模式支持該事件。你可以通過Web.config文件的<sessionState>節的timeout屬性來指定超時時限,如果用戶在該超時時限之內(以分鐘為單位,默認是20分
鐘)不刷新或請求網頁,則該會話將終止。可以利用Session_OnEnd 事件做一些清理工作。
示例:下面的示例是比較常用到的統計在線人數的Session_OnEnd 事件代碼:
有關會話狀態的具體應用實例見:
簡單的論壇程序
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。
下面顯示了進程內模式的一個配置設置示例。
<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 |
有關會話狀態的具體應用實例見:
簡單的論壇程序