ASP.NET SessionState 解惑


踩坑

近日在對一個ASP.NET WEBFORM項目進行調優過程中,偶然發現頁面POSTBACK事件是串行處理的,甚至不同頁面的請求都是串行處理的(一個頁面加載完畢后,才開始加載第二個頁面)。但是網站明明是並發處理請求的啊,當時十分不解,把代碼翻來覆去排查了大半天,尋找業務框架中什么地方是不是鎖了資源。各種斷點、調試、日志全部用上,還是找不到原因。
仔細思考了一下,ASP.NET肯定不會是串行處理的,難道是某一個Session中,ASP.NET對其串行處理請求?

排雷

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

  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源碼

原來SessionStateModule模塊實現了一個寫入鎖,並對其進行排隊處理,所以同一SESSION下的所有請求都會被串行執行。

解決方案也很簡單,在頁面上增加EnableSessionState="ReadOnly"指令即可。 當然,增加了這個指令后,這個頁面也就不能修改SESSION值了。

衍生

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

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


免責聲明!

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



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