"百年一遇"奇怪问题的进展:找到原因,ajax请求中断引起
注:该问题已解决,详见终于解决“百年一遇”奇怪问题。
问题原因
经过昨天一天的奋战,终于在吃晚饭前找到了"百年一遇"奇怪问题的原因。(问题详情见前一篇博文:百年一遇的奇怪问题:当IE遇上.NET Framework 4.5)
问题原因是:当服务器安装了 .NET Framework 4.5 之后,在IE中,如果 ASP.NET MVC 处理的 ajax 请求未执行完成时,连接被中断(比如F5刷新浏览器),接下来的请求就会被卡住。
问题验证
用 IE 访问闪存(http://home.cnblogs.com/ing/),按 F12 打开开发者工具,等所有 ajax 请求执行完成再刷新浏览器,问题就不会出现。
我们在测试环境中,取消所有 ajax 请求,问题就不会出现。
问题分析
为什么 ajax 请求被中断后会出现这个问题?
我的猜测是:ajax 请求被中断后,服务器端 ASP.NET Runtime 处理该请求的线程继续保留着(可能在刷新时, IE 继续保持着连接),接下来的请求继续由这个线程处理,于是卡住。所以,重启 IE 问题会消失就是因为这时 IE 发起了新的连接,服务器端用新的线程进行处理,这同时也解释了第一次请求总是不会出现问题。
下面针对前一篇博文中问题的五个奇怪之处逐一进行分析:
1、“问题奇怪之一:服务器是微软的 ASP.NET 环境,出问题的不是其他浏览器,而是微软自己的 IE 浏览器。”
猜测:在刷新时,IE 可能与其他浏览器的处理方式不一样,IE 会继续保持着同一个 HTTP 连接。服务器端 ASP.NET Runtime 对这个连接使用之前为之服务的一个线程处理(可能是 .NET Framework 4.5 的一个改变)。
2、“问题奇怪之二:IE 第一次请求不会出现问题,问题只出现在后续请求中。”
因为问题只会在 ajax 请求被中断后的请求中出现。
3、“问题奇怪之三:同一台服务器,有多个站点,只有这一个站点会出现这个问题。同一个站点(home.cnblogs.com),只有主页与闪存相关页面会出现这个问题。”
出现问题的页有个特征 —— ajax 请求特别多,问题可能与 ajax 请求的数量有关。
4、“问题奇怪之四:WebForms 与 MVC 都会出现这个问题。”
问题在服务器端 ASP.NET Runtime 处理该请求的线程,所以与是 WebForms 还是 MVC 无关。
5、“问题奇怪之五:在 Global.asax 中取消所有 MVC 的路由注册(routes.MapRoute),问题就消失。”
由于 ajax 请求是由 MVC 处理的,取消 MVC 的路由注册也就不存在 ajax 请求被中断的情况。
继续奋战
进一步的原因以及解决方案还要继续努力研究。。。
最新进展
将 ajax 请求的处理由 MVC 改为 Web Service(.asmx) 之后,问题不再出现。由此可见,与浏览器、与 js 一点关系没有。