Ajax异步请求阻塞情况的解决办法

情况:同事在写Webform页面程序发现这样一个现象:在做导出功能时,由于导出数据的处理时间比较长,就在客户端加一个定时器通过ajax不间断查询导出进度。然后发现了一个情况,这个请求一直是阻塞的状态,直到导出事件处理完成之后。才去执行这个请求,也就是说如果响应时间长的请求还在进行中,短的请求却被挂起了。
 

连续用了两个异步请求去获取资源为什么反而加载更慢了呢?

原来是在进行异步请求时访问了session,为了安全考虑(避免单个用户并发请求导致的session数据错乱),.net中session实现了Reader/Writer的锁机制,当session具有读写功能时,采用排它锁来互斥的访问session数据,也就是说开启了session后,单个用户只能串行的访问这个站点,直到这个访问结束前,其他的请求都会进入等待状态,从而进入线程的顺序执行。

SessionReader/Writer的锁机制原理:当页面对Session具有可写功能(即页面有<%@Page EnableSessionState="True" %>标记),此时直到请求完成该页面的Session持有一个写锁定。

当页面对Session具有只读功能(即页面有<%@Page EnableSessionState="ReadOnly" %>标记),此时知道请求完成该页面的Session持有一个读锁定。

  读锁定将阻塞一个写锁定;读锁定不会阻塞读锁定;写锁定将阻塞所有的读写锁定。这就是为什么两个框架中的同一个页面都去写同一个Session时,其中一个要等待另一个(稍快的那个)完成后,才开始写。

解决方案: 

写锁定将阻塞所有的读写锁定”,也就是说页面在EnableSessionState="True"的情况下没返回输出时,一直持着Session写操作,其他页面对Session的读操作必须等待,而asp.net的aspx页面默认是EnableSessionState="True",每个页面从请求开始至返回一直持着Session写操作,需验证页面必须读取Session值判断,这就是为什么需验证的页面请求被阻塞的原因。只要耗时页面(A页面)没有Session的写操作,也就不会阻塞其他页面的请求,于是修改A页面的EnableSessionState="ReadOnly",例如:

<%@ Page Language="C#" AutoEventWireup="true"CodeFile="TBS_Monitor_List.aspx.cs"EnableSessionState="ReadOnly" Inherits="TBS_Monitor_List" %>

,问题解决。


 

结论:也就是说,在无需对session进行写操作的页面,在Page指令加上EnableSessionState="ReadOnly"属性,就不会造成Request阻塞的情况了。同样的,访问其他实现了锁机制的资源时也要注意锁造成的Request阻塞的情况。

你可能感兴趣的:(bug回顾,并发编程,servlet,asp.net,服务器,ajax,前端)