近日在对一个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模块实现了一个写入锁,并对其进行排队处理,因此同一SESSION下的全部请求都会被串行执行。事件
解决方案也很简单,在页面上增长EnableSessionState="ReadOnly"指令便可。 固然,增长了这个指令后,这个页面也就不能修改SESSION值了。资源
GOOGLE的过程当中,发现.NET MVC一样也有这个问题,其解决方案是在controller上增长特性[SessionState(SessionStateBehavior.ReadOnly)]
随手实验一番,不加以上特性时,在有SESSION的状况下,同SESSION的请求会被串行处理。增长SessionStateBehavior.ReadOnly后不一样action中,请求会被并行处理,可是相同action仍然是串行处理的。
即便是Task<ActionResult>
,任然没法逃脱串行执行的魔掌。