ASP.NET Session会导致的性能问题(2)

Concurrent Requests and Session State
Access to ASP.NET session state is exclusive per session, which means that if two different users make concurrent requests, access to each separate session is granted concurrently. However, if two concurrent requests are made for the same session (by using the same SessionID value), the first request gets exclusive access to the session information. The second request executes only after the first request is finished. (The second session can also get access if the exclusive lock on the information is freed because the first request exceeds the lock time-out.) If theEnableSessionState value in the @ Page directive is set to ReadOnly, a request for the read-only session information does not result in an exclusive lock on the session data. However, read-only requests for session data might still have to wait for a lock set by a read-write request for session data to clear.


       也就是说,对于页面,我们可以简单的在Aspx上的<% @Page %>内设置EnableSessionState=”false”,或者EnableSessionState=”ReadOnly”,就可以减轻这种问题的症状。前一种设置将会禁止对Session的访问,而后一种设置则只能允许只读访问(你不能够对Session进行写操作)。正好,我们刚才提到的IHttpHandler中,对图片进行处理的部分,是不需要对Session进行写操作的,但是却需要读取Session(根据状态不同,而需要获取一些特殊信息),因此可以采取上述的措施来解决问题。 

       上述参考文献中,并没有说明如何对不是Page的IHttpHandler如何设置,这里我特别说明一下。对于自定义的一个实现了IHttpHandler接口的类,只要同时实现IReadOnlySessionState,即可达到EnableSessionState="ReadOnly"的效果。同时,如果没有实现IRequiresSessionState,则等价于EnableSessionState=”false”的效果。

注意:本文所说的,不是说你在代码里面有没有用到Session,Asp.Net不会扫描你的代码看看有没有访问Session,或者在你第一次访问Session的时候才会加锁。Asp.Net是在AcquireRequestState事件之前就首先申请这个锁——只要你的页面没有设置EnableSessionState=”false”或EnableSessionState=”ReadOnly”,或者你的IHttpHandler实现了IRequiresSessionState却没有实现IReadOnlySessionState接口就会这样。回复中有很多同学说“只要我不用Session不就行了吗?”或者“我从来不用Session”,这么想完全是错误的,只能说你没有理解这背后的机制,甚至可能连Asp.net生命周期都不太清楚。Asp.Net之所以在你的页面代码开始执行之前就锁定,是要保证整个环境的完整性,避免部分执行的情况。当然,也正如上面的一些引用中所提到的,你可以自己写一个SessionProvider而不做任何的锁工作,但这样做肯定有不确定性的风险,到时候只能你自己承担,并且更难复现和调试。

后记:
 
       可能有不少人都知道Session是什么,也有很多人知道Asp.net的生命周期都包含哪些,比如一搜索"PostMapRequestHandler AcquireRequestState",就会出来很多中文的页面介绍HttpApplication类都有哪些事件,以及生命周期等等。而说到Session会造成特殊情况下站点性能问题的,似乎中文界我这还真是第一篇。当然了,这个问题可能比较偏,因为一般大家都只会处理Aspx页面而不会处理图片,甚至用Aspx页面来动态输出图片的机会都比较少,英文的似乎也只有文中提到的唯一一个同志提出来了。 

       不过,有一个很常见的场景会受这个问题的影响,那就是“验证码”。如果验证码生成速度很慢,同时客户端浏览器选择长连接而服务器也接受长连接,则可能会影响在输出验证码完毕之前访问下一个页面的速度。反过来,我们也经常可以体验到,验证码出来的速度总是特别慢,总是“蹦”出来的,尤其是当前页面特别复杂的时候,似乎页面没有加载完就总不会出现验证码。估计我说的问题就是原因之一。 

       不过验证码的问题还不是特别好解决,因为为了避免信息泄露的问题,验证码的答案通常是存在在Session里面的,而通常的设计也是一访问验证码图片,就会将验证码答案写到Session里面。所以,很不幸,文中提到的那个解决办法是行不通的,至少不是能够直接行得通的。这个问题有没有救药?有,当然有了。怎么救?哈,那就有劳你自己开动脑筋了,我这里算是点到即止了。

您可能感兴趣的文章:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wjfyfz.html