Rob Howard
Microsoft Corporation
2000 年 12 月 28 日
注意 本文中的程式碼是以 Microsoft .NET 的 Beta 版本為目標。 某些程式碼可能需要重新工作,才能在更新版本的 .NET Framework上正常運作。
在此月份的資料行中,我們將挑選一些步調,並直接探討 ASP.NET 的一些新功能。 我們將從比較 ASP.NET 會話狀態與傳統 ASP 開始,然後顯示如何設定和使用 ASP.NET 會話狀態的程式碼和範例。
會話定義為唯一使用者與 Web 應用程式互動的時間週期。 Active Server Pages (ASP) 想要保留唯一使用者會話資料的開發人員,可以使用稱為會話狀態的內建功能。
以程式設計方式,會話狀態不只是字典或雜湊表圖形中的記憶體,例如索引鍵/值組,可在使用者會話期間設定和讀取。 例如,使用者選取要追蹤的股票,而 Web 應用程式可以將這些值儲存在使用者的 ASP 會話實例中:
Session("Stocks") = "MSFT; VRSN; GE"
在後續的頁面上會讀取這些值,而且 Web 應用程式可以存取這些值,而不需要使用者重新輸入這些值:
' Get Stocks, split string, etc.
Dim StockString
StockString = Session("Stocks")
ASP 會藉由提供用戶端在會話開始時指派給使用者的唯一金鑰來維護會話狀態。 此金鑰會儲存在用戶端在每個要求上傳送至伺服器的 HTTP Cookie 中。 然後伺服器可以從 Cookie 讀取金鑰,並重新擴充伺服器會話狀態。
ASP 會話狀態的問題
ASP 開發人員知道會話狀態是絕佳的功能,但有些限制。 這些限制包括:
- 程式相依。 ASP 會話狀態存在於裝載 ASP 的進程中;因此,影響進程的動作也會影響會話狀態。 當進程回收或失敗時,會話狀態會遺失。
- 伺服器陣列限制。 當使用者從伺服器移至 Web 服務器陣列中的伺服器時,其會話狀態不會遵循它們。 ASP 會話狀態是電腦特定的。 每個 ASP 伺服器都會提供自己的會話狀態,除非使用者返回相同的伺服器,否則會話狀態無法存取。 雖然網路 IP 層級路由解決方案可以解決這類問題,但藉由確保用戶端 IP 路由傳送到原始伺服器,有些 ISP 會選擇為其用戶端使用 Proxy 負載平衡解決方案。 這些最不具名的就是 AOL。 AOL 之類的解決方案會防止將要求的網路層級路由傳送到伺服器,因為要求者的 IP 位址不保證是唯一的。
- Cookie 相依。 不接受 HTTP Cookie 的用戶端無法利用會話狀態。 有些用戶端認為 Cookie 會危害安全性和/或隱私權,因此會停用伺服器上的會話狀態。
這些是 ASP.NET 會話狀態設計中考慮的幾個問題集。
ASP.NET 會話狀態
ASP.NET 會話狀態可解決與傳統 ASP 會話狀態相關聯的上述所有問題:
- 與進程無關。 ASP.NET 會話狀態能夠在與 ASP.NET 主機進程不同的進程中執行。 如果會話狀態是在不同的進程中,則 ASP.NET 進程可以在會話狀態進程保持可用時進入。 當然,您仍然可以在與傳統 ASP 類似的進程中使用會話狀態。
- 支援伺服器陣列組態。 藉由移至跨進程模型,ASP.NET 也會解決伺服器陣列問題。 新的跨進程模型可讓伺服器陣列中的所有伺服器共用會話狀態進程。 您可以將 ASP.NET 組態變更為指向一般伺服器,藉以實作此動作。
- 與 Cookie 無關。 雖然傳統 ASP 確實存在無 Cookie 狀態管理問題的解決方案,但實作並不簡單。 另一方面,ASP.NET 會將無 Cookie 會話狀態的複雜度減少為簡單的組態設定。
讓我們更詳細地查看這些功能,包括設定方式。
使用 ASP.NET 會話狀態
ASP.NET 中的會話狀態設定是透過 ASP.NET XML 組態檔 config.web進行設定。 我們將在稍後的資料行中更詳細地查看 config.web ,但在此會話狀態的討論中,讓我們簡短查看。
Config.web
組態檔有兩種類型:電腦群組態檔和應用程式組態檔,兩者都命名為 config.web。 兩者完全相同,不同之處在于電腦群組態檔會將設定套用至所有應用程式,但應用程式組態檔會限制或依應用程式擴充。
在 Beta 1 中,電腦 config.web 檔案位於 WinNT\Microsoft.NET\Framework\v1.0.2204 目錄中,而選擇性的應用程式組態檔則存在於應用程式的目錄中。 應用程式 config.web 檔案是選擇性的,也就是說,如果應用程式 config.web 檔案不存在,則會改用電腦 config.web 設定。 ASP.NET 會話狀態設定可以在電腦 config.web 檔案中建立,並在特定應用程式的 config.web 檔案中覆寫。
注意:config.web所做的變更會立即套用,不同于傳統 ASP,伺服器必須停止並啟動,設定才會生效。
工作階段組態
以下是用來設定 ASP.NET 應用程式的會話狀態設定的範例 config.web 檔案:
<configuration>
<sessionstate
mode="inproc"
cookieless="false"
timeout="20"
sqlconnectionstring="data source=127.0.0.1;user id=<user id>;password=<password>"
server="127.0.0.1"
port="42424"
/>
</configuration>
上述設定可用來設定會話狀態 ASP.NET。 讓我們更詳細地查看每個專案,並在之後涵蓋各種用途。
- 模式。 模式設定支援三個選項:inproc、sqlserver 和 stateserver。 如先前所述,ASP.NET 支援兩種模式:進程和進程外。 跨進程狀態管理也有兩個選項:記憶體型 (狀態器) ,以及以 sqlserver) SQL Server為基礎的 (。 我們很快就會討論如何實作這些選項。
- 無 Cookie。 ASP.NET 的 cookieless 選項是使用這個簡單的布林值設定來設定。
- 逾時。 此選項可控制會話視為有效的時間長度。 會話逾時是滑動值;在每個要求上,逾時期間會設定為目前時間加上逾時值
- Sqlconnectionstring。 sqlconnectionstring 會識別資料庫連接字串,該連接字串會命名用於模式 sqlserver 的資料庫。
- 伺服器。 在跨進程模式狀態器中,它會命名執行必要 Windows NT 服務的伺服器:ASPState。
- 連接埠。 伺服器設定隨附的埠設定會識別對應至模式狀態器之伺服器設定的通訊埠號碼。
範例會話狀態應用程式
在使用會話狀態之前,我們需要應用程式來測試它。 以下是一個簡單的 Visual Basic® 應用程式程式碼,可寫入會話狀態和從會話狀態讀取 SessionState.aspx:
<Script runat=server>
Sub Session_Add(sender As Object, e As EventArgs)
Session("MySession") = text1.Value
span1.InnerHtml = "Session data updated! <P>
Your session contains: <font color=red>" +
Session("MySession").ToString() + "</font>"
End Sub
Sub CheckSession(sender As Object, e As EventArgs)
If (Session("MySession") = Isnull) Then
span1.InnerHtml = "NOTHING, SESSION DATA LOST!"
Else
span1.InnerHtml = "Your session contains:
<font color=red>" +
Session("MySession").ToString() + "</font>"
End If
End Sub
</Script>
<form runat=server>
<input id=text1 type=text runat=server>
<input type=submit runat=server
OnServerClick="Session_Add" Value="Add to Session State">
<input type=submit runat=server
OnServerClick="CheckSession" Value="View Session State">
</form>
<hr size=1>
<font size=6><span id=span1 runat=server/></font>
這個簡單的頁面會連接兩個 [ 新增 ] 和 [ 檢視 ] 按鈕的伺服器端事件,並直接將會話狀態設定為文字方塊中的值。
我們可以更詳細地查看四個一般組態設定:進程內模式、跨進程模式、SQL Server模式和 Cookieless。
進程內模式
同進程模式只是表示以與傳統 ASP 會話狀態類似的方式使用 ASP.NET 會話狀態。 也就是說,會話狀態是在進程中管理,如果進程重新迴圈,狀態就會遺失。 假設 ASP.NET 提供的新設定,您可能會想知道為何要使用此模式。 原因相當簡單:效能。 會話狀態的效能,例如從會話狀態字典讀取和寫入會話狀態字典所花費的時間,在記憶體讀取和寫入處理中時,跨進程呼叫會增加額外負荷,因為跨進程呼叫會在資料來回封送處理或可能從SQL Server讀取時增加額外負荷。
進程內模式是 ASP.NET 的預設設定。 使用此設定時,唯一使用的會話 config.web 設定是無 Cookie 和逾時。
如果我們呼叫 SessionState.aspx、設定會話狀態值,並停止並啟動 ASP.NET 進程 (iisreset) ,則會遺失在進程迴圈之前設定的值。
跨進程模式
.NET SDK 隨附于 Windows® NT 服務:ASPState。 此 Windows 服務是 ASP.NET 用於跨進程會話狀態管理的功能。 若要使用此狀態管理員,您必須先啟動服務。 若要啟動服務,請開啟命令提示字元並輸入:
net start aspstate
您會看到的內容如下:
.gif)
圖 1. 在命令提示字元啟動 Windows NT 服務 ASPState
此時,Windows NT 服務 ASPState 已啟動,可供 ASP.NET 使用。 接下來,我們需要設定 ASP.NET 來利用這項服務。 若要這樣做,我們需要設定 config.web:
<configuration>
<sessionstate
mode="stateserver"
cookieless="false"
timeout="20"
sqlconnectionstring="data source=127.0.0.1;user id=<user id>;password=<password>"
server="127.0.0.1"
port="42424"
/>
</configuration>
我們只會從 inproc 模式變更為 stateserver mode 。 此設定會告訴 ASP.NET 在 和 port 設定中指定的 server 伺服器上尋找 ASP 狀態服務,在此案例中為本機伺服器。
我們現在可以呼叫 SessionState.aspx、設定會話狀態值、停止並啟動 IIS 進程 (iisreset) ,並繼續存取目前狀態的值。
SQL Server模式
SQL Server模式選項與 Windows NT 服務的選項類似,不同之處在于資訊會保存到SQL Server,而不是儲存在記憶體中。
若要使用SQL Server作為會話狀態存放區,我們必須先建立必要的資料表和預存程式,ASP.NET 會尋找所識別SQL Server。 .NET SDK 提供 SQL 腳本 (state.sql) 來執行此動作。
state.sql
state.sql檔案包含用來建立 ASPState 資料庫的 SQL 命令。 此腳本會建立兩個數據表和數個預存程式。 ASP.NET 會使用資料表和程式,將資料儲存在SQL Server中。 建議您閱讀 state.sql ,以深入瞭解其運作方式。
state.sql 檔案可以在[system drive]\winnt\Microsoft.NET\Framework\[version]\中找到
套用 state.sql 腳本
若要套用state.sql腳本,請使用命令列工具SQL Server提供: osql.exe。 使用 sa 對等 SQL 使用者時,會使用下列語法:
osql –S [server name] –U [user] –P [password] <state.sql
注意:安裝 .NET SDK 時,會安裝輕量型版本的 SQL Server。
以下是您應該會看到的內容:
.gif)
圖 2. 使用 SQL Server 命令列工具來套用 state.sql 腳本
執行 osql 之後,啟動和停止SQL Server;狀態.sql新增的一部分是需要執行的一些啟動預存程式。 接下來,修改組態設定,將模式 sqlserver 設定為 ,並修改 sqlconnectionstring 以識別提供 ASPState 資料庫的適當SQL Server。 例如:
<configuration>
<sessionstate
mode="sqlserver"
cookieless="false"
timeout="20"
sqlconnectionstring="data source=MySqlServer;
user id=ASPState;
password=1Gr8State"
server="127.0.0.1"
port="42424"
/>
</configuration>
同樣地,與 Windows NT 服務狀態管理員類似,我們現在可以呼叫 SessionState.aspx、設定會話狀態值、停止並啟動 IIS 進程 (iisreset) ,並繼續存取目前狀態的值。 事實上,我們可以將 SQL Server 叢集,如此一來,如果某個SQL Server發生無法使用的情況,另一部正在複寫其資料的伺服器可能會發生其位置。 這會提供 ASP 中無法使用的可靠性層級。
無 Cookie 狀態
我們可以設定 ASP.NET 會話狀態的最後一項新功能是無 Cookie 會話狀態。 基本上,此功能可讓用戶端選擇不使用 Cookie 的網站利用 ASP.NET 會話狀態。
做法是使用可唯一識別會話的識別碼來修改 URL:
https://localhost/(lit3py55t21z5v55vlm25s55)/Application/SessionState.aspx
ASP.NET 會修改頁面內找到的相對連結,並內嵌此識別碼。 因此,只要使用者遵循網站提供的連結路徑,就可以維護會話狀態。 不過,如果使用者重新寫入 URL,則會話狀態實例很可能遺失。
IIS 4.0 資源套件提供類似的功能。 它實作為 ISAPI 篩選準則,可修改傳入和傳出位元組資料流程來寫入和讀取必要的資訊。 這項功能與 ASP.NET 功能之間的差異是使用此功能所需的工作。 在 ASP.NET 中,只需要在 config.web 檔案中翻轉布林值即可:
<configuration>
<sessionstate
mode="stateserver"
cookieless="true"
timeout="20"
sqlconnectionstring="data source=127.0.0.1;user id=<user id>;password=<password>"
server="127.0.0.1"
port="42424"
/>
</configuration>
當 cookieless 設定為 true 之後,ASP.NET 會執行啟用無 Cookie 會話狀態所需的工作。 另請注意,無 Cookie 會話支援所有模式。
效能和可靠性考慮
這值得一提的是,在 ASP.NET 會話狀態模式時,您應該考慮的一些效能和可靠性問題。
- 處理中。 在進程中會執行最佳效能,因為會話狀態記憶體會保留在 ASP.NET 進程中。 對於裝載于單一伺服器上的 Web 應用程式,使用者保證會重新導向至正確的伺服器,或當會話狀態資料不是重要的 (,因為它可以重新建構或重新填入) ,這是選擇的模式。
- 進程不足。 當效能很重要時,最好使用此模式,但您無法保證使用者將從哪個伺服器要求應用程式。 透過跨進程模式,您可以取得從記憶體讀取的效能,以及管理所有伺服器狀態的個別進程可靠性。
- SQL Server。 當資料的可靠性是應用程式穩定性的基礎時,最好使用此模式,因為資料庫可以針對失敗案例進行叢集處理。 效能不如程式外快,但取捨是更高的可靠性層級。
可分解性
本文未涵蓋的內容,以及未來文章中將探討的一些內容,就是 ASP.NET 的可因素。 基本上,這是擴充或取代 ASP.NET 功能的能力,例如會話狀態。 如果協力廠商提供擴充會話狀態管理員,可將會話資料儲存在輕量型目錄存取通訊協定 (LDAP) 目錄,例如 Netscape LDAP 目錄,則可以取代預設 ASP.NET 會話狀態實作。
總結
如您所見,ASP.NET 會話狀態與 ASP 會話狀態相當不同。 未系結至 ASP.NET 程式的會話狀態新功能表示開發人員可以在伺服器陣列環境中開始使用會話狀態,而不必擔心用戶端是否透過 Proxy 伺服器。 此外,使用無 Cookie 狀態功能,使用會話狀態也更容易,並保證所有用戶端都可以利用會話狀態功能。
在下一篇文章中,我們將探討 ASP.NET 中的新追蹤功能。
Rob Howard 是 .NET Frameworks 小組上 ASP.NET 的程式經理。 他會花他與家庭一起擁有的任何備用時間,或是在美國東部釣魚。