在 Web 應用程式這樣的無狀態環境中,瞭解工作階段狀態的概念並沒有實際的意義。儘管如此,有效狀態管理對於大多數 Web 應用程式來說都是一個必備的功能。Microsoft ASP.NET 以及許多其他伺服器端編程環境都提供了一個抽象層,允許應用程式基底於每個使用者和每個應用程式儲存持久性資料。
需要特別注意的是,Web 應用程式的工作階段狀態是應用程式在不同的請求中緩衝和檢索的資料。會話表示使用者在與該網站串連期間發送的所有請求,工作階段狀態是使用者在會話期間產生和使用的持久性資料的集合。每個會話的狀態都彼此獨立,而且在使用者會話結束時就不複存在了。
工作階段狀態與構成 HTTP 協議和規範的任何邏輯實體都沒有對應關係。會話是由伺服器端開發環境(例如傳統的 ASP 和 ASP.NET)構建的抽象層。ASP.NET 展示工作階段狀態的方式以及工作階段狀態的內部實現方式都取決於平台的基礎結構。因此,傳統的 ASP 和 ASP.NET 以完全不同的方式來實現工作階段狀態,預計在下一版的 ASP.NET 中會有進一步的改進和增強。
本文討論如何在 ASP.NET 1.1 中實現工作階段狀態,以及如何在被管理的 Web 應用程式中最佳化工作階段狀態管理。
ASP.NET 工作階段狀態概述
工作階段狀態並不是 HTTP 基礎結構的一部分。也就是說,應該有一個結構組件將工作階段狀態與每個傳入請求綁定在一起。運行時環境(傳統的 ASP 或 ASP.NET)能夠接受 Session 之類的關鍵字,並使用它指示伺服器上儲存的資料區塊。要成功解析 Session 對象的調用,運行時環境必須將工作階段狀態添加到正在處理的請求的調用上下文中。完成此操作的方式因平台而異,但它是有狀態 Web 應用程式的基礎操作。
在傳統的 ASP 中,工作階段狀態是作為 asp.dll 庫中包含自由線程 COM 物件來實現的。(您對此很好奇嗎?其實該對象的 CLSID 是 D97A6DA0-A865-11cf-83AF-00A0C90C2BD8。)此Object Storage Service以成對的名稱和數值集合的方式組織的資料。“名稱”預留位置表示用來檢索資訊的關鍵字,而“值”預留位置表示工作階段狀態中儲存的內容。成對的名稱和數值按照會話 ID 進行分組,這樣,每個使用者看到的只是他/她自己建立的成對的名稱和數值。
在 ASP.NET 中,工作階段狀態的編程介面與傳統的 ASP 幾乎是相同的。但它們的基礎實現是完全不同的,前者比後者更具有靈活性、可擴充性和更強的編程功能。深入研究 ASP.NET 工作階段狀態之前,讓我們簡單回顧一下 ASP.NET 會話基礎結構的某些結構功能。
根據 mode 特性的值,將通過不同的步驟從不同的進程中檢索工作階段狀態並將其儲存到不同的進程中。預設情況下,工作階段狀態儲存在本地的 ASP.NET 輔助進程中。特殊情況下,會將其儲存在 ASP.NET Cache 對象的專用槽中(不能通過編程方式訪問)。也可以將工作階段狀態儲存在外部,甚至是遠程進程中(例如,名為 aspnet_state.exe 的 Windows NT 服務中)。第三個選項是將工作階段狀態儲存到由 SQL Server 2000 管理的專用資料庫表中。
到目前為止,InProc 可能是最快的訪問選項。但請記住,會話中儲存的資料越多,Web 服務器所消耗的記憶體就越多,這樣會潛在地增加效能降低的風險。如果您計劃使用任何進程外解決方案,應該認真考慮一下序列化和還原序列化可能帶來的影響。進程外解決方案使用 Windows NT 服務 (aspnet_state.exe) 或 SQL Server 表來儲存會話值。因此,工作階段狀態保留在 ASP.NET 輔助進程之外,並且需要使用額外的代碼層,在工作階段狀態和實際的儲存介質之間進行序列化和還原序列化操作。只要處理請求就會發生此操作,而且隨後必須對其進行最高程度的最佳化。
在進程外儲存方案中,工作階段狀態存活的時間較長,使應用程式的功能更強大,因為它可以防止 Microsoft? Internet 資訊服務 (IIS) 和 ASP.NET 失敗。通過將工作階段狀態與應用程式相分離,您還可以更容易地將現有應用程式擴充到 Web Farm 和 Web Garden 體繫結構中。另外,工作階段狀態儲存在外部進程中,從根本上消除了由於進程迴圈而導致的周期性資料丟失的風險。
下面介紹如何使用 Windows NT 服務。正如上文所述,NT 服務是一個名為 aspnet_state.exe 的進程,通常位於 C:\WINNT\Microsoft.NET\Framework\v1.1.4322 檔案夾中。
實際目錄取決於您實際啟動並執行 Microsoft? .NET Framework 版本。使用狀態伺服器之前,應確保該服務就緒並正運行在用作會話存放裝置的本地或遠端電腦上。狀態服務是 ASP.NET 的組成部分並與之一起安裝,因此您無需運行其他安裝程式。預設情況下,狀態服務並沒有運行,需要手動啟動。ASP.NET 應用程式將在載入狀態伺服器之後立即嘗試與之建立串連。因此,該服務必須準備就緒且正在運行,否則將引發 HTTP 異常。下圖顯示了該服務的屬性對話方塊。
圖 2:ASP.NET 狀態伺服器的屬性對話方塊
ASP.NET 應用程式需要指定工作階段狀態服務所在的電腦的 TCP/IP 位址。必須將以下設定輸入該應用程式的 web.config 檔案中。
當頁面將資料儲存到 Session 中時,會將值載入到 HttpSessionState 類包含的特製的詞典類中。完成當前處理的請求時,會將詞典的內容載入到狀態供應器中。如果由於未通過編程方式將資料放入詞典而導致工作階段狀態為空白,則不會將資料序列化到儲存介質中,而且更重要的是,不會在 ASP.NET Cache、SQL Server 或 NT 狀態服務中建立槽來跟蹤當前會話。這是出於效能方面的原因,但會對處理會話 ID 的方式產生重要影響:將為每個請求產生一個新的會話 ID,直到將某些資料存放區到會話詞典中。
工作階段狀態最初由傳統的 ASP 引入,它是基於詞典的 API,使開發人員能夠儲存會話期間的自訂資料。在 ASP.NET 中,工作階段狀態支援以下兩種主要功能:Cookieless 會話 ID 儲存和傳輸,以及會話資料實際儲存的狀態供應器。為實現這兩種新功能,ASP.NET 利用 HTTP 模組控制工作階段狀態與正在處理的請求上下文之間的綁定。
在傳統的 ASP 中,使用工作階段狀態就是指使用 Cookie。在 ASP.NET 中已不再如此,因為可以使用 Cookieless 架構。藉助 HTTP 模組的力量,可以分解請求的 URL 以使其包含會話 ID,然後將其重新導向。接下來,HTTP 模組會從該 URL 中提取會話 ID 並使用它檢索任何儲存的狀態。
會話的物理狀態可以儲存在三個位置:進程內記憶體、進程外記憶體和 SQL Server 表。資料必須經過序列化/還原序列化處理,才能供應用程式使用。HTTP 模組會在請求開始時將會話值從提供者複製到應用程式的記憶體中。請求完成後,修改後的狀態將返回提供者。這種資料通訊會對效能產生不同程度的不利影響,但是會大大增強可靠性和穩定性,也使對 Web Farm 和 Web Garden 體繫結構的支援更容易實現。