天天看點

一起談.NET技術,ASP.NET中如何正确使用Session

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

  我們知道Session與Cookie最大的差別在于:Cookie資訊全部存放于用戶端,Session則隻是将一個ID存放在用戶端做為與服務端驗證的标記,而真正的資料都是放在服務端的記憶體之中的。

  在傳統web程式設計語言(比如asp)中,session的過期完全是按照TimeOut來老老實實處理的,逾時值預設是20分鐘,但問題是:通常有很多使用者隻看一眼網頁,然後就關浏覽器走人了,這種情況下,服務端記憶體裡還長久儲存着Session的資料,如果這種使用者很多,對伺服器資源無疑是一種浪費。

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

一起談.NET技術,ASP.NET中如何正确使用Session

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

一起談.NET技術,ASP.NET中如何正确使用Session

  當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對應的機器上該服務已經啟動。

一起談.NET技術,ASP.NET中如何正确使用Session

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

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

  session資訊甚至還能儲存到SqlServer資料庫中:

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

一起談.NET技術,ASP.NET中如何正确使用Session

  即aspnet_regsql -S 資料庫執行個體名 -ssadd -U 連接配接使用者名。注意:資料庫伺服器得先啟動Sql Server代理服務:

一起談.NET技術,ASP.NET中如何正确使用Session

  該指令運作後,将會自動建立一個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是唯一的内置方案。