使用StateServer儲存Session,解決Session過期問題
正常操作情況下Session會無故丟失。因為程式是在不停的被操作,排除Session超時的可能。另外,Session超時時間被設定成60分鐘,不會這麼快就超時的。
這次到CSDN上搜了一下帖子,發現好多人在討論這個問題,然後我又google了一下,發現微軟網站上也有類似的內容。
現在我就把原因和解決辦法寫出來。
由於Asp.net程式是預設配置,所以Web.Config檔案中關於Session的設定如下:
<sessionState mode='InProc' stateConnectionString='tcpip=127.0.0.1:42424' sqlConnectionString='data source=127.0.0.1;Trusted_Connection=yes' cookieless='true' timeout='60'/>
我們會發現sessionState標籤中有個屬性mode,它可以有3種取值:InProc、StateServer?SQLServer(大小寫敏感) 。預設情況下是InProc,也就是將Session儲存在程序內(IIS5是aspnet_wp.exe,而IIS6是W3wp.exe),這個程序不穩定,在某些事件發生時,程序會重起,所以造成了儲存在該程序內的Session丟失。
哪些情況下該程序會重起呢?微軟的一篇文章告訴了我們:
1、配置檔案中processModel
2、Global.asax或者Web.config檔案被更改
3、Bin資料夾中的Web程式(DLL)被修改
4、防毒軟體掃描了一些.config檔案。
更多的資訊請參考PRB: Session variables are lost intermittently in ASP.NET applications
解決辦法:
前面說到的sessionState標籤中mode屬性可以有三個取值,除了InProc之外,還可以為StateServer、SQLServer。這兩種存Session的方法都是程序外的,所以當aspnet_wp.exe重起的時候,不會影響到Session。
現在請將mode設定為StateServer。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了。
如果你有更高的要求,需要在服務期重啟時Session也不丟失,可以考慮將mode設定成SQLServer,同樣需要修改sqlConnectionString屬性。關於使用SQLServer儲存Session的操作,請訪問這裡。
在使用StateServer或者SQLServer儲存Session時,所有需要儲存到Session的物件除了基本資料型別(預設的資料型別,如 int、string等)外,都必須序列化。只需將[Serializable]標籤放到要序列化的類前就可以了。
如:
[Serializable]
public class MyClass
{ ...... }
具體的序列化相關的知識請參這裡。
至此,問題解決。
ASP.NET 使用mode=”InProc”方式儲存Session老是丟失,無奈改成StateServer 模式。
session是工作在你的應用程式程序中的。asp.net程序、iis往往會在20分鐘之後重啟相關的應用程式,緩衝池滿了(例如100個之後)也會重啟,各種程序保護措施都會隨時重新啟動,因此InProc方式丟失session是很正常的事。csdn上明確告訴了這種模式只能儲存“易失的、暫時的 ”變數,這是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 (埠號,在web.config中要設定的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”
timeout=”20″ />
→ 將其改為以下內容(注意:當發生“無法向會話狀態伺服器發出會話狀態請求。"異常時,將mode="InProc",其他不變)
<sessionState mode=”StateServer” stateConnectionString=”tcpip=192.168.0.2:42424″ timeout=”20″ />
注意事項:
1、timeout=”20″為Session 20分鐘超時
2、IP 地址(可以是遠端計算機 IP、計算機名稱、域名)與埠號,埠號需與ASP.NET State Service 的服務埠一致