1. 程式人生 > >asp.net mvc session鎖問題 (轉載)

asp.net mvc session鎖問題 (轉載)

一、會話狀態Session



Session用於伺服器端狀態管理,使用Session之後,每個客戶端都可以將實際的資料儲存在伺服器上,對於每個客戶端的資料,將會生成一個對應的唯一的key(儲存在客戶端)。客戶端與伺服器端就是通過這個key來確認客戶端的身份,通常這個key為SessionID。
一般情況下,SessionID以Cookie的形式儲存在瀏覽器中,在不使用Cookie的情況下,也可以將這個SessionID嵌入到訪問網頁的URL中。

 

 

二、伺服器端Session



在頁面物件或者HttpContext物件中,都有一個名為Session的屬性,在一次會話中,它們引用的都是同一個物件。

public HttpSessionState Session { get; }

Session物件是HttpSessionState類的例項。Session是儲存在伺服器端的,對每個登入到網站的使用者都有一份,是獨有的,而其他使用者無法共享。

 

HttpSessionState來自於HttpModule的SessionStateModule。在每次請求處理過程中,HttpApplication的請求的處理管道中會檢查當前請求的處理程式是否實現了介面IRequiresSessionState,如果實現的話,那麼SessionStateModule將為這個請求分配HttpSessionState。同時SessionStateModule還負責SessionID的生成、Cookieless會話管理、從外部狀態提供程式中檢索會話資料以及將資料繫結到請求的呼叫上下文。

  • 對於一般處理程式,預設情況下沒有實現IRequiresSessionState介面。所以如果想要在一般處理程式中使用Session,可以通過實現IRequiresSessionState介面來解決這個問題,這個介面是一個標記介面,並沒有定義任何內容。
  • 對於頁面處理程式,可以將頁面指令@Page的EnableSessionState屬性設定為true,以允許頁面可以請求會話狀態的寫入許可權。這是預設的設定。還可以將EnableSessionState屬性設定為ReadOnly,此時派生的實際頁面類將會實現介面IReadOnlySessionState,在這種情況下,頁面可以擁有會話狀態的只讀許可權。

SessionStateModule模組從特定狀態提供程式中讀取資料。在程式程式碼中實際上訪問的是會話資料在本地記憶體中的副本,如果其他頁面也檢視同步訪問該會話狀態就可能會導致資料衝突。為了避免這種情況,SessionStateModule模組實現了一個讀取器/寫入器的鎖定機制,並對狀態值的訪問進行排隊。對會話狀態具有寫入許可權的頁面將保留該會話的寫入器鎖定,直到請求終止。


如果頁面請求設定一個讀取器鎖定,同一會話中同時處理的其他請求將無法更新會話狀態,但是至少可以進行讀取。如果頁面請求為會話狀態設定一個寫入鎖,那麼所有其他頁面都被阻止,無論他們是否要讀取或寫入內容。例如,如果同時有兩段程式檢視在同一個Session中寫入內容,一段程式必須等到另一段程式完成後才能寫入。在AJAX程式設計中,必須注意這種情況的發生。


網上查了一下 基本上的解決方案 如下

對於Asp.net MVC:
可以為本Controller增加以下特性,但是本Controller都不能修改Session了,只能讀取
[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
對於Asp.net WebForm:
在Web.config 檔案裡面新增EnableSessionState="ReadOnly" // 僅僅載入那個阻塞頁面

 

經過測試上面的方法並未有卵用  已將session 改為 System.Web.Caching.Cach 或者 Redis 或者 memcached來實現
大概實現邏輯就是 自己生成一個key 這個key可以是使用者Id 然後 通過cookie的方式寫到客戶端  每次客戶端訪問伺服器都攜帶這個cooike 就可以實現自己的會話變量了
其主要目的是為個規避session鎖的問題 尤其是頁面使用了進度條的 .... 特此筆記記錄

 

 

原文連結