ASP.NET 使用mode=”InProc”方式保存Session老是丟失,無奈改成StateServer 模式。
session是工作在你的應用程序進程中的。asp.net進程、iis往往會在20分鐘之後重啓相關的應用程序,緩衝池滿了(例如100個之 後)也會重啓,各種進程保護措施都會隨時重新啓動,因此InProc方式丟失session是很正常的事。上明確告訴了這種模式只能保存“易失 的、暫時的 ”變量,這是cache沒有之前的一種解決方案。而長期保持的數據就要保存在外部數據源中。狀態服務器就是一種進程外的數據源。
StateServer 模式的實質是,把Session 存放在一個單獨的進程裏,此進程獨立於 aspnet_wp.exe 或 w3wp.exe 。啓用此服務後,在“任務管理器”中可以看到一個名為 aspnet_state.exe 的進程,下面開始説明一下設置的具體步驟:
1、 修改註冊表(關鍵步驟,如下圖)
運行 regedit → 打開註冊表 → 找到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state \Parameters 節點 → 將 AllowRemoteConnection 的鍵值設置成“1”(1 為允許遠程電腦的連接,0 代表禁止)→ 設置 Port (端口號)
注意事項:
a)、若ASP.NET State Service 正在運行,修改註冊表內容後,則需要重新啓動該服務
b)、注意端口號的鍵值是以十六進制儲存的,可以使用十進制進行修改,42424 是默認的端口
c)、AllowRemoteConnection 的鍵值設置成“1”後,意味着允許遠程電腦的連接,也就是説只要知道你的服務端口,就可享用你的ASP.NET State Service,即把 Session 存放在你的電腦進程內,因此請大家慎用;鍵值為“0”時,僅有stateConnectionString 為“tcpip=localhost: 42424”與“tcpip=127.0.0.1:42424”的情況,方可使用ASP.NET State Service
2、 開啓 ASP.NET State Service
右鍵點擊“我的電腦”→ 管理 → 服務與應用程序 → 服務 → 雙擊“ASP.NET State Service” → 啓動(可設為“自動”)
説明:只要安裝了 .Net Framework ,都擁有此服務。
3、 更改 Web.config
打開 Web.config → 找到 <sessionState> 節點內容
<sessionState
mode=”InProc”
stateConnectionString=”tcpip=127.0.0.1:42424″
sqlConnectionString=”data source=127.0.0.1;Trusted_Connection=yes”
cookieless=”false”
ASP.NET Session丟失解決辦法:
這兩種存Session的方法都是進程外的,所以當aspnet_wp.exe重起的時候,不會影響到Session。
1) StateServer是本機的一個服務,可以在系統服務裏看到服務名為ASP.NET State Service的服務,默認情況是不啓動的。當我們設定mode為StateServer之後,請手工將該服務啓動。這樣,我們就能利用本機的StateService服務來存儲Session了,除非電腦重啓或者StateService崩掉,否則Session是不會丟的(因Session超時被丟棄是正常的)。
除此之外,我們還可以將Session通過其他電腦的StateService來保存。具體的修改是這樣的。在 sessionState標籤中,有stateConnectionString='tcpip=127.0.0.1:42424'屬性,其中有個ip地 址,默認為本機(127.0.0.1),你可以將其改成你所知的運行了StateService服務的電腦IP,這樣就可以實現位於不同電腦上的 Asp.net程序互通Session了。
將mode屬性設為StateServer,也就是將會話數據存儲到單獨的內存緩衝區中,再由單獨一台機器上運行的Windows服務來控制這個緩衝區。 狀態服務全稱是“ASP.NET State Service ”(aspnet_state.exe),計算機管理-服務 裏面即可看到此服務,啓動該服務它由Web.config文件中的stateConnectionString屬性來配置。該屬性指定了服務所在的服務 器,以及要監視的端口:
<sessionState mode="StateServer"
stateConnectionString="tcpip=myserver:42424"
cookieless="false" timeout="20" />
在這個例子中,狀態服務在一台名為myserver的機器的42424端口(默認端口)運行。要在服務器上改變端口,可編輯HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters註冊表項中的Port值。
顯然,使用狀態服務的優點在於進程隔離,並可在Web farm(網站羣)中共享。使用這種模式,會話狀態的存儲將不依賴於iis進程的失敗或者重啓,然而,一旦狀態服務中止,所有會話數據都會丟失。換言之,狀態服務不像SQL Server那樣能持久存儲數據;它只是將數據存儲在內存中。
2) 如果你有更高的要求,需要在其他服務重啓時Session也不丟失,可以考慮將mode設定成SQLServer,同樣需要修改sqlConnectionString屬性。
在使用StateServer或者SQLServer存儲Session時,所有需要保存到Session的對象除了基本數據類型(默認的數據類型,如int、string等)外,都必須序列化。只需將[Serializable]標籤放到要序列化的類前就可以了。
如:
[Serializable]
public class MyClass
{
......
}
ASP.NET還允許將會話數據存儲到一個 數據庫服務器中,方法是將mode屬性變成SqlServer。 在這種情況下,ASP.NET嘗試將會話數據存儲到由sqlConnectionString屬性(其中包含數據源以及登錄服務器所需的安全憑證)指定的 SQL Server中。
為了用恰當的數據庫對象來配置SQL erver,管理員還需要創建ASPState數據庫,
方法是運行WinDir\Microsoft.Net\Framework\Version(如:v3.0)文件夾中的 InstallSqlState.sql腳本(WinDir是服務器的Windows文件夾,而Version是你使用的.NET框架版本的安裝文件 夾)。要配置SQL服務器,可以在命令行中運行SQL Server 提供的命令行工具osql.exe
osql -S [ server name] -U [user] -P [password] -i InstallSqlState.sql
例如osql -S (local)\NetSDK -U sa -P "" -i InstallSqlState.sql
在這裏用户名必須是SQL服務器上的sa帳號,或者具有同等權限的其他帳號。有興趣的讀者可以打開這個腳本文件來了解 ASP.NET是如何和SQL Server配合實現狀態管理的。 卸載這些表和存儲過程,可以使用UninstallSqlState.sql腳本,使用方法與上面類似。做好必要的 數據庫準備工作後,將web.config 文件中的sessionstate 元素的mode改為"sqlserver",並且指定SQL連接字符串。具體如下:
mode="sqlserver" sqlConnectionString="data source=127.0.0.1; userid=sa; password="";
配置好SQL Server後,應用程序代碼運行時就和InProc模式沒有什麼區別。但要注意的是,由於數據不存儲在本地內存,所以存儲會話狀態的對象需要進行序列化和反序列化,以便通過網絡傳給數據庫服務器,以及從數據庫服務器傳回。這當然會影響性能。通過在數據庫中存儲會話狀態,可分別針對擴展性及可靠性來有效地平衡性能。另外,可以利用SQL Server的集羣,使狀態存儲不依賴於單個的SQL Server,這樣就可以為應用程序提供極大限度的可靠性。
ASP.NET Session丟失問題解決經驗:
1) 判斷是不是原因1造成的,可以在每次刷新頁面的時候,跟蹤bin中某個文件的修改時間.
2) 做Session讀寫日誌,每次讀寫Session都要記錄下來,並且要記錄SessionID、Session值、所在頁面、當前函數、函數中的第幾次Session操作,這樣找丟失的原因會方便很多.
3) 如果允許的話,建議使用state server或sql server保存session,這樣不容易丟失.
4) 在global.asa中加入代碼記錄Session的創建時間和結束時間,超時造成的Session丟失是可以在SessionEnd中記錄下來的。
<sessionState> 元素設置:
<system.web>
<sessionState mode="Off|InProc|StateServer|SQLServer"
cookieless="true|false"
timeout="number of minutes"
stateConnectionString="tcpip=server:port"
sqlConnectionString="sql connection string"
stateNetworkTimeout="number of seconds"/>
</system.web>
|
mode |
描述 |
|
Off |
指示會話狀態沒有啓用。 |
|
InProc |
默認情況下是InProc,保存20分鐘。也就是將Session保存在進程內(IIS5是aspnet_wp.exe,而IIS6是W3wp.exe),這個進程不穩定,在某些事件發生時,進程會重起,所以造成了存儲在該進程內的Session丟失。 |
|
StateServer |
指示在本地或遠程服務器上存儲會話狀態。mode為StateServer之後,手工將該服務啓動。這樣,我們就能利用StateServer來存儲Session了,除非電腦重啓或者StateService崩掉,否則Session是不會丟的(因Session超時被丟棄是正常的) |
|
SQLServer |
指示在 SQL Server? 上存儲會話狀態 |
|
屬性 |
描述 |
|
cookieless |
默認不用Cookie來傳遞會話ID【<sessionStatemode="InProc"cookieless="false"/>cookieless="false" :表示Session不需要Cookie傳遞;如果修改為cookieless="true":表示Session的ID在Cookie中傳遞,這樣訪問時地址欄中會出現多餘的文字如:http://localhost:11209/Web/(S(lsua21yjunmcf245wnkogy55))/Index.aspx】。採取這種方式,不管Cookie還是隱藏表單字段都用不着了。所以,即使網頁中沒有使用表單,也能加入會話。但是這種方法,應用程序的狀態將依賴於進程,當IIS進程崩潰或者正常重啓時,保存在進程中的狀態將丟失。 |
|
stateConnectionString |
指定遠程存儲會話狀態的服務器名稱或地址以及端口。端口值默認為 %SystemRoot%\Microsoft.NET\Framework\VersionNumber\aspnet_state.exe。 默認值為 "tcpip=127.0.0.1:42424"。 |
|
sqlConnectionString
|
為運行 SQLServer 值時是必需的 默認值為 "data source=127.0.0.1;Integrated Security=SSPI"。 |
|
allowCustomSqlDatabase |
指定會話狀態 ASPState數據庫。有關更多信息,請參見會話狀態模式。默認值為 false。 |
|
timeout
|
指定在放棄一個會話前該會話可以處於空閒狀態的分鐘數。對於進程內和狀態服務器模式,timeout屬性不能設置為大於1年)的值。 會話 20 分鐘。 |
|
stateNetworkTimeout |
當使用 10。 |
|
cookieName |
指定存儲會話標識符的 "ASP.NET_SessionId"。 |
|
regenerateExpiredSessionId |
指定當客户端指定了過期的會話 此屬性是 true。 |
|
< xmlnamespace prefix ="v" ns ="urn:schemas-microsoft-com:vml" />注意 |
|
若要在使用 StateServer 模式時提高您的應用程序的安全性,請使用受保護的配置來加密配置的<sessionState> 節,以幫助保護 stateConnectionString值。 |
使用模式:
<Drive>:\systemroot\Microsoft.NET\Framework\version\aspnet_state.exe。
使用模式:
ASPState 的數據庫。
不常用屬性:
|
customProvider |
可選的 String 屬性。 指定用於存儲和檢索會話狀態數據的自定義會話狀態提供程序的名稱。該提供程序在providers 元素中指定。僅當會話狀態模式設置為 Custom值時,才使用該提供程序。有關更多信息,請參見會話狀態模式。 此屬性是 .NET Framework 2.0 版中的新屬性。 默認值為空字符串 ("")。 |
|
partitionResolverType |
可選的 String 屬性。 指定在哪裏存儲會話狀態。如果 stateConnectionString 屬性。PartitionResolverType屬性返回的連接字符串將用於每個請求,為請求的其餘部分連接到適當的服務器位置。如果連接字符串無效,ASP.NET將引發一個異常,該異常與當配置的服務器連接字符串無效時引發的異常相同。該屬性用於在 SQL或狀態服務器模式下在多個後端節點上劃分會話狀態數據。 此屬性是 .NET Framework 2.0 版中的新屬性。 默認值為空字符串。 |
|
sqlCommandTimeout |
可選的 TimeSpan 屬性。 指定使用 SQL 命令可以處於空閒狀態的時間(秒),超過此時間之後,該命令將被取消。 此屬性是 .NET Framework 2.0 版中的新屬性。 默認值為30秒)。 |
|
useHostingIdentity |
可選的 Boolean 屬性。 指定會話狀態將恢復為宿主標識還是使用客户端模擬。 如果為ASP.NET將使用下列進程憑據之一來連接會話狀態存儲區: 宿主進程;對於 NETWORK SERVICE。 應用程序模擬標識,當使用了以下配置時使用此憑據: <identity impersonate="true" userName="user" password="pwd" /> 如果為ASP.NET將使用目前與當前請求的操作系統線程關聯的憑據來連接會話狀態存儲區。對於客户端模擬,ASP.NET將使用與瀏覽器協商的安全憑據來連接會話狀態存儲區。如果為ASP.NET在連接會話狀態存儲區時不會恢復為進程標識或應用程序模擬標識。有關更多信息,請參見ASP.NET模擬。 此屬性是 .NET Framework 2.0 版中的新屬性。 默認值為 true。 |
|
注意 |
|
在 SQL Server的計算機。 |
timeout=”20″ />
→ 將其改為以下內容
<sessionState mode=”StateServer” stateConnectionString=”tcpip=192.168.0.2:42424″ timeout=”20″ />
注意事項:
1、timeout=”20″為Session 20分鐘超時
2、IP 地址(可以是遠程計算機 IP、計算機名稱、域名)與端口號,端口號需與ASP.NET State Service 的服