天天看點

Session伺服器配置指南與使用經驗

所有Web程式都會使用Session儲存資料. 使用獨立的Session伺服器可以解決負載均衡場景中的Session共享問題.本文介紹.NET平台下建立Session伺服器的幾種辦法, 并介紹在使用Session時的各種經驗和技巧.

Session資料儲存在伺服器端, 但是每一個用戶端都需要儲存一個SessionID, SessionID儲存在Cookies中, 關閉浏覽器時過期.

在向伺服器發送的HTTP請求中會包含SessionID, 伺服器端根據SessionID擷取擷取此使用者的Session資訊.

很多初級開發人員不知道SessionID和Cookies的關系, 是以常常認為兩者沒有聯系. 這是不正确的. 正是因為SessionID儲存在Cookies中, 是以在我們儲存Cookies的時候,一定要注意不要因為Cookies的大小和個數問題而導緻SessionID對象. 在我們的程式中, 對SessionID的Cookies有特殊的處理:

将Session儲存在獨立的伺服器中可以實作在多台Web伺服器之間共享Session.雖然我們也可以自己開發Session存儲系統, 但是使用ASP.NET自帶的存儲機制将更加便捷.

.NET提供了5種儲存Seission的方式:

方式名稱

存儲方式

性能

Off

設定為不使用Session功能

InProc

設定為将Session存儲在程序内,就是ASP中的存儲方式,這是預設值。

性能最高

StateServer

設定為将Session存儲在獨立的狀态服務中。通常是aspnet_state.exe程序.

性能損失10-15%

SQLServer

設定将Session存儲在SQL Server中。

性能損失10-20%

Customer

自定制的存儲方案

由實作方式确定

我們可以在Web.Config中配置程式使用的Session存儲方式.預設情況下是InProc, 即儲存在IIS程序中. 關于Off, InProc和Customer本文不做講解. 相關文章大家都可以在網上搜尋到.

下面主要講解 StateServer 和 SQLServer 的應用.

1.啟動 Asp.net State service服務.(這個服務預設的狀态為手動.修改為自動并啟動.)

2.修改系統資料庫: [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\aspnet_state\Parameters]

設定 AllowRemoteConnection = 1 , 設定 Port = 42424 (十進制,預設即為42424)

Port是服務的端口号

AllowRemoteConnection 表示是否允許其他機器連接配接,0為僅能本機使用,1為可以供其他機器使用.

在Web應用程式的Web.Config中, 我們需要修改 <configuration> / <system.web> 的<sessionState>節點.如果沒有

沒有則添加(預設使用的是InProc方式)

上面的參數我們可以根據需要修改.

使用SqlServer模式搭建Session伺服器端有兩種方式. ASP.NET 1.0和1.1版本請使用方式a, 2.0即以上版本請使用方式b.

在ASP.NET 1.0和1.1 版本中, 隻能使用這種方式.對于2.0及其以上版本,請使用aspnet_regsql.exe工具.(當然此方法也通用2.0版本)

.net提供了資料庫安裝腳本,可以在機器的windows檔案夾中找到:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ InstallSqlState.sql

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ InstallSqlStateTemplate.sql

根據ASP.NET的版本不同, 需要使用不同的SQL腳本. ASP.NET主要有1.1和2.0兩個版本,可以在不同的版本檔案夾找到這兩個SQL.

InstallSqlState.sql 是建立預設名稱的資料庫"[ASPState]".此SQL可以直接運作.

InstallSqlStateTemplate.sql 可以使用自己指定的資料庫儲存資料.此SQL需要自己修改後運作, 打開SQL檔案将其中 [DatabaseNamePlaceHolder] 替換為自己指定的資料庫名稱.

執行installsqlstate.sql時不需要指定資料庫,可以在任意資料庫上執行.此SQL會自己建立新的資料庫

ASP.NET 2.0版本後微軟提供了aspnet_regsql.exe工具可以友善的配置Session資料庫.該工具位于 Web 伺服器上的"系統根目錄\Microsoft.NET\Framework\版本号"檔案夾中.

使用舉例:

aspnet_regsql.exe -S . -U sa -P 123456 -ssadd -sstype p

-S參數:

表示資料庫執行個體名稱. 可以用"."表示本機.

-U和-P參數:

表示使用者名和密碼.

-E參數:

可以再-U –P 與 -E中選擇一組. –E表示以目前系統使用者通過windows身份驗證登入資料庫, -U -P則是使用SqlServer使用者登入資料庫.

-ssadd / –ssremove 參數:

-ssadd表示是添加Session資料庫, -ssremove表示移除Session資料庫.

sstype 參數:

選項

說明

t

将會話資料存儲到 SQL Server tempdb 資料庫中。這是預設設定。如果将會話資料存儲到 tempdb 資料庫中,則在重新啟動 SQL Server 時将丢失會話資料。

p

将會話資料存儲到 ASPState 資料庫中,而不是存儲到 tempdb 資料庫中。

c

将會話資料存儲到自定義資料庫中。如果指定 c 選項,則還必須使用 -d 選項包括自定義資料庫的名稱。

此房是同樣需要Web應用程式修改Web.Config中的<sessionState>節點.如果使用預設的資料庫(ASPState庫), 則配置如下:

如果使用了自定義的資料庫名稱,則還需要制定allowCustomSqlDatabase屬性并在資料庫連接配接串中指定資料庫:

下面是SessionID, Session_End時間, StatServer模式 和 SqlServer模式的各種經驗和技巧總結.

1.在web farm中,請确認在所有的web伺服器上有相同的<machineKey>

2. 要儲存在Session中的對象是可序列化的。

3.為了在web farm中的不同web伺服器上維護session state,IIS Metabase中的網站應用程式路徑(如\LM\W3SVC\2)應該在所有的伺服器上保持一緻(大小寫敏感).

4. ASP.NET處理Session是在Machine.Config中配置的HttpModuel子產品, 在.NET的安裝目錄下的Config檔案夾中, 檢視Web.Config(1.1版本是在Machine.Config):

确認此子產品是否存在.

5.StateServer不支援負載均衡, 是以如果大并發推薦使用SqlServer模式, 可以享受到SqlServer的高性能和安全性.雖然存儲效率會有下降.

6.需要讓所有機器的MachineKey相同.在Machine.Config中配置:

1. 要儲存在Session中的對象是可序列化的。

2. 如果使用了預設是資料庫, 則在用戶端配置檔案中的資料庫連結字元串的使用者,需要擁有ASPState和tempdb兩個庫的dbowner權限.

3. 在SQLServer模式下,session過期是由SQL Agent使用一個注冊任務完成的,要确認SQL Agent已經運作。否則無法清理過期的Session資料, 會導緻資料庫資料一直增加.

4. 如果使用SqlServer模式時, 對于Web場中的各伺服器的 ASP.NET 應用程式路徑必須是相同的。請在 IIS 配置資料庫中對 Web 場中的所有 Web 伺服器進行 Web 站點的應用程式路徑同步。大小寫一定要相同,因為 Web 站點的應用程式路徑是區分大小寫的。

5.需要讓所有機器的MachineKey相同.在Machine.Config中配置:

1. 不能直接通過Session伺服器在ASP.NET和ASP之間共享Session. 請使用微軟提供的解決方案: 

<a href="http://msdn.microsoft.com/zh-cn/library/aa479313.aspx">http://msdn.microsoft.com/zh-cn/library/aa479313.aspx</a>

2. 在不同的應用程式或一個網站的不同虛拟目錄之間無法共享Session

3. Session的過期時間是滑動時間.

4. Session存儲.NET自帶的值類型性能最優. 存儲對象會降低性能.

1.SessionID 還可以儲存在URL上, 設定Web.Config檔案中的System.Web/sessionState節點的Cookiesless屬性即可:

2. 一般在Session逾時或删除之後,SessionID保持不變. 因為Session過期後會在伺服器端清除資料, 但是SessionID儲存在使用者浏覽器上, 是以隻要浏覽器不關閉則HTTP頭中的SessionID保持不變.

3.關閉浏覽器後再通路, SessionID會不同.

4.每打開一個IE6視窗, SessionID都不同, 在IE6中兩個視窗的Session不能共享.

5.FireFox的标簽頁和新的FireFox視窗, SessionID都相同, 在FF的視窗和标簽頁上Session能共享.

6.對于包含FrameSet的頁面,比如:

如果字尾名是.htm并且.htm檔案沒有交給ASP.NET的ISAPI處理, 那麼根據伺服器速度在每個Frame頁面生成不同的SessionID, 再重新整理後相同都等于最後一個SessionID.

解決辦法是将.htm字尾改成.aspx, 或者将.htm檔案交給ASP.NET的ISAPI處理. 

1. Session_End僅在InProc模式中可用

2. 關閉浏覽器,Session_End是不會觸發的。HTTP是一種無狀态協定,伺服器沒有辦法知道你的浏覽器是否已經關閉。

3. 當Session因為時間過期或調用Session.Abandon時,Session_End才會觸發.Session.Clear()僅僅是清除資料,但沒有删除session。

4. Session_End由一個背景線程觸發,使用工作者程序賬号運作. 是以程式不會通知發生的錯誤.

5. 在Session_End通路資料庫要考慮權限問題. Session_End是用運作工作者程序(aspnet_wp.exe)的帳号運作的,這個賬号可以在machine.config中指定。是以,在Session_End中,如果使用integrity security連接配接SQL,它将使用工作者程序賬号身份連接配接,這可能會引起登入失敗.

6.因為Session_End是有獨立線程出發的, 是以在Session_End中無法使用HttpContext對象(Request,Response,Server等對象都在HttpContext中),  即無法使用 Response.Redirect 和Server.Transfer等方法.

我已經使用SqlServer模式對公司的多台伺服器實作了Session共享, 伺服器重新開機也不會導緻使用者預定過程重新開始(預定過程需要的Session不會丢失).  希望本文對具體的Session伺服器搭建人員有所幫助. 

參考文獻:

使用一個 SQL 資料庫 SQL Server 會話狀态的所有應用程式可能導緻瓶頸

ASP.NET 中 Session 實作原理淺析 [1] /[2]

<a href="http://www.cnblogs.com/flier/archive/2004/08/04/30226.html">http://www.cnblogs.com/flier/archive/2004/08/04/30226.html</a>

了解Session State模式+ASP.NET SESSION丢失FAQ [翻譯]

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。