ASP.NET SessionState 解惑

踩坑

近日在對一個ASP.NET WEBFORM項目進行調優過程當中,偶然發現頁面POSTBACK事件是串行處理的,甚至不一樣頁面的請求都是串行處理的(一個頁面加載完畢後,纔開始加載第二個頁面)。可是網站明明是併發處理請求的啊,當時十分不解,把代碼翻來覆去排查了大半天,尋找業務框架中什麼地方是否是鎖了資源。各類斷點、調試、日誌所有用上,仍是找不到緣由。
仔細思考了一下,ASP.NET確定不會是串行處理的,難道是某一個Session中,ASP.NET對其串行處理請求?瀏覽器

排雷

在項目中新增一個頁面,只能加最簡單的事件代碼:session

log.Info("start");
  System.Threading.Thread.Sleep(5000);
  log.Info("end");

瀏覽器中開打兩個標籤頁同時訪問該頁面,結果請求時並行處理的。併發

16:24:44[9]start
16:24:45[10]start
16:24:49[9]end
16:24:50[10]end

接着先訪問下登錄頁面,而後再重複上次動做,請求變成串行處理了!框架

16:26:11[9]start
16:26:16[9]end
16:26:16[10]start
16:26:21[10]end

換成兩個瀏覽器,分別登錄後訪問該頁面,請求被並行處理。
自此確認確定是SESSION的問題!網站

GOOGLE搜索了一番,找到緣由及解決方案:調試

The session state module implements a locking mechanism and queues the access to state values. A page that has session-state write access will hold a writer lock on the session until the request finishes. A page gains write access to the session state by setting the EnableSessionState attribute on the @Page directive to True. A page that has session-state read access -- for example, when the EnableSessionState attribute is set to ReadOnly -- will hold a reader lock on the session until the request finishes.日誌

SessionStateModule源碼code

原來SessionStateModule模塊實現了一個寫入鎖,並對其進行排隊處理,因此同一SESSION下的全部請求都會被串行執行。事件

解決方案也很簡單,在頁面上增長EnableSessionState="ReadOnly"指令便可。 固然,增長了這個指令後,這個頁面也就不能修改SESSION值了。資源

衍生

GOOGLE的過程當中,發現.NET MVC一樣也有這個問題,其解決方案是在controller上增長特性[SessionState(SessionStateBehavior.ReadOnly)]

隨手實驗一番,不加以上特性時,在有SESSION的狀況下,同SESSION的請求會被串行處理。增長SessionStateBehavior.ReadOnly後不一樣action中,請求會被並行處理,可是相同action仍然是串行處理的。
即便是Task<ActionResult>,任然沒法逃脫串行執行的魔掌。

相關文章
相關標籤/搜索