为什么多个同时的AJAX调用同一个ASP.NET MVC动作会导致浏览器阻塞?
为什么多个同时的AJAX调用同一个ASP.NET MVC动作会导致浏览器阻塞?
几天前我问了这个问题:为什么$.getJSON()会阻塞浏览器?我同时向同一个控制器动作发出了六个jQuery异步Ajax请求。每个请求需要10秒才能返回。通过调试和记录对该动作方法的请求,我注意到这些请求是串行化的,从未并行运行。也就是说,我在log4net日志中看到的时间轴如下所示:
2010-12-13 13:25:06,633 [11164] INFO - Got:11562010-12-13 13:25:16,634 [11164] INFO - Returning:1156
2010-12-13 13:25:16,770 [7124] INFO - Got:1426
2010-12-13 13:25:26,772 [7124] INFO - Returning:1426
2010-12-13 13:25:26,925 [11164] INFO - Got:1912
2010-12-13 13:25:36,926 [11164] INFO - Returning:1912
2010-12-13 13:25:37,096 [9812] INFO - Got:1913
2010-12-13 13:25:47,098 [9812] INFO - Returning:1913
2010-12-13 13:25:47,283 [7124] INFO - Got:2002
2010-12-13 13:25:57,285 [7124] INFO - Returning:2002
2010-12-13 13:25:57,424 [11164] INFO - Got:1308
2010-12-13 13:26:07,425 [11164] INFO - Returning:1308
在Firefox的网络时间轴中,我看到了这个:上述日志示例和Firefox的网络时间轴都是针对同一组请求的。来自同一页面的对同一动作的请求会被串行化吗?我知道在同一个会话中对Session
对象的访问是串行的,但是这里没有触及到任何会话数据。我将客户端代码简化为仅包含一个请求(运行时间最长的请求),但这仍然会阻塞浏览器,即只有当Ajax请求完成后,浏览器才会响应任何链接点击。在这里,我还观察到(在Chrome的开发者工具中),当一个长时间运行的Ajax请求正在执行时,点击链接时立即报告了一个Failed to load resource
错误,这表明浏览器已经终止(或正在尝试终止并等待?)Ajax请求:然而,浏览器仍然需要很长时间才能重定向到新页面。Ajax请求真的是异步的吗,还是这只是因为JavaScript实际上是单线程的?我的请求是否只是花费的时间太长而无法工作?这个问题在Firefox和IE中也存在。我还更改了脚本,直接使用$.ajax
并明确设置async: true
。我在IIS7.5上运行,无论是Windows 2008R2还是Windows 7版本都会出现同样的问题。调试和发布版本的行为也相同。
多个同时的AJAX调用同一个ASP.NET MVC操作引起浏览器阻塞的原因是访问ASP.NET会话状态是每个会话独占的。这意味着如果两个不同的用户同时发出请求,每个独立的会话都会同时被授予访问权限。然而,如果两个并发的请求对于同一个会话(使用相同的SessionID值)进行访问,第一个请求将独占地访问会话信息。只有在第一个请求完成后,第二个请求才会执行。
解决方法是在ASP.NET MVC3中创建无会话控制器。可以通过在需要的控制器上使用`[SessionState(SessionStateBehavior.Disabled)]`装饰器来解决问题。
不过需要注意的是,使用`[SessionState(SessionStateBehavior.Disabled)]`可能会在应用程序中引入安全漏洞,例如在多个同时请求中访问私有数据,因为这样你无法知道用户是否已登录,是否有活动会话等等。如果需要访问会话,可以使用`[SessionState(SessionStateBehavior.ReadOnly)]`,这样仍然可以访问会话,但不能对其进行编辑,但在许多情况下仍然有用。
总之,多个同时的AJAX调用同一个ASP.NET MVC操作引起浏览器阻塞的问题可以通过创建无会话控制器或使用只读会话状态来解决。
多个同时的AJAX调用同一个ASP.NET MVC action会导致浏览器阻塞的原因是:请求被排队处理。这可能是由于浏览器的并发请求限制导致的。解决这个问题的方法是设置AJAX请求的缓存选项为false,或者使用$.get()方法替代$.getJSON()方法。
以下是问题的原因和解决方法的整理:
原因:
- 浏览器的并发请求限制导致请求被排队处理。
解决方法:
- 设置AJAX请求的缓存选项为false。
- 使用$.get()方法替代$.getJSON()方法。
示例代码:
$.ajax({ url: '/home/ajax', cache: false, success: function (result) { $('#result').append($('').html( result.startTime + ' | ' + result.endTime )); } });
希望通过以上的解决方法可以解决多个同时的AJAX调用同一个ASP.NET MVC action导致浏览器阻塞的问题。