溫故而知新:Asp.Net中如何正確使用Session


原文鏈接作者:菩提樹下的楊過
出處:http://yjmyzz.cnblogs.com 

 

Asp.Net中的Session要比Asp中的Session靈活和強大很多,同時也復雜很多;看到有一些Asp.Net開發人員報怨說Session不穩定,莫名其妙的丟失,其實這正是Asp.Net改進的地方之一.

 

我們知道Session與Cookie最大的區別在於:Cookie信息全部存放於客戶端,Session則只是將一個ID存放在客戶端做為與服務端驗證的標記,而真正的數據都是放在服務端的內存之中的。

 

在傳統web編程語言(比如asp)中,session的過期完全是按照TimeOut來老老實實處理的,超時值默認是20分鍾,但問題是:通常有很多用戶只看一眼網頁,然后就關瀏覽器走人了,這種情況下,服務端內存里還長久保存着Session的數據,如果這種用戶很多,對服務器資源無疑是一種浪費。

 

而在Asp.Net中,Session的存儲策略有好幾種:

默認情況下,系統采用的是InProc模式,即進程內模式。

這種情況下,Session是保存在Asp.Net工作進程映射的內存中的,問題是Asp.Net工作進程為了維護良好的平均性能,會被系統經常回收。我們在IIS里可以配置自動回收(比如按時間周期回收,或者當內存使用達到多少值時自動回收),如下圖即為IIS7中配置應用程序池回收參數的界面

 

當Asp.Net工作進程被回收時,其映射的內存全部被清空並初始化,以便其它程序可以使用,所以Session也跟着一並消失了,就這是為什么Sesssion會無故消失的主要原因。

 

當然默認的InProc模式也是性能最高的一種模式,如果您不能忍受這種“不穩定”,可以在web.config中把mode設置為StateServer模式

<sessionState  mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424"></sessionState>

這種情況下Session會被保存在Asp.Net進程之外的aspnet_state.exe進程中,這個進程不受asp.net進程回收的影響。

但要注意:aspnet_state是以windows服務形式運行的,所以請先確保127.0.0.1對應的機器上該服務已經啟動

另外,我們也必須意識到:雖然StateServer模式下session會穩定很多,但是性能相對InProc而言是有損耗的(大概在15%~25%左右),因為系統內部要將session值序列化以后,保存到aspnet_state進程映射的內存中,讀取的時候還要反序列化。

這種模式還有一個優點:如果tcpip=127.0.0.1:42424中的IP地址指定為另外一台服務器,意味着可以將session保存在web服務器以外的機器上。

 

session信息甚至還能保存到SqlServer數據庫中:

進入vs命令行模式,輸入以下命令:

即aspnet_regsql -S 數據庫實例名 -ssadd -U 連接用戶名

注意:數據庫服務器得先啟動Sql Server代理服務

該命令運行后,將會自動創建一個AspState數據庫,同時會在tempdb數據庫下創建二張表ASPStateTempApplications與ASPStateTempSessions

對應的web.config配置為:

<sessionState mode="SQLServer" sqlConnectionString="data source=JIMMYT61P;uid=sa;pwd=***"></sessionState>

注:如果想把表直接創建在數據庫ASPState中,剛才的命令行中,再加一個參數 -sstype p ,即:

aspnet_regsql -S 數據庫實例名 -ssadd -sstype p -U 連接用戶名

同樣SqlServer模式在保存讀取Session數據時,相對InProc模式也會有性能損耗(大約在25%左右),但利用SqlServer能實現Session數據的持久保存.

 

最后再來看看mode中的另外二個值: Off與Custom

Off 相當於禁用了session,就不多說了

Custom 允許開發人員自己定義Session如何存儲,相當於提供了一個可供編程的開發接口(我從來沒用過,所以...也談不出很深的道道來,呵呵)

 

綜合一下:

InProc性能最高,但是有可能會使session無故丟失,而且這種模式無法適用於web服務器集群或負載均衡場景(因為多台服務器之間無法實現Session同步),StateServer與SqlServer可應用於web服務器集群場景,但是性能有所降低;如果希望Session能持久化保存,SqlServer是唯一的內置方案。

 

最后談點個人經驗:

一般情況下,我傾向於使用cookie,從而減少對服務器資源的消耗,但是這也要找一個平衡點,因為服務端代碼中要得到客戶端的cookie,也就意味着cookie文件必須通過瀏覽器傳遞到服務器,同樣會消耗網絡帶寬。

另外:在一些博客系統中,比如用戶寫文章時,如果中途離開了下,然后繼續寫,等到保存時會發現session已經失效,頁面跳到登錄頁,辛苦打了N多字卻沒了!這時可考慮用代碼一直維系session,即麒麟兄弟的心跳思想:讓你的網站"心跳"起來 ,或者用ajax每隔幾分鍾自動保存一次

再者:從安全性上講,偽造session要比cookie難得多,相對更安全一些。

 

作者:菩提樹下的楊過
出處:http://yjmyzz.cnblogs.com 
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM