AJAX调用慎用POST方式,有严重的问题或者BUG

这个问题只存在客户端是IE或IE内核的情况,但是你无法控制客户端使用什么浏览器,所以仍然会给你的应用造成很大的性能问题。

我们先说现象:

服务端:我们只用一个静态的HTML页面ok.html,内容只返OK.

然后我们写一个ajax调用的html在客户端访问:

<script> function send_request(method,url,param) { http_request = false; if (window.XMLHttpRequest) { http_request = new XMLHttpRequest(); } else if (window.ActiveXObject) { try { http_request = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { http_request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { } } } if (!http_request) { return; } http_request.open(method, url,true); http_request.send(param); } function get(){ var url = "http://myhost/ok.html?name=axman&test=123"; for(var i=0;i<1000;i++){ send_request("GET",url,null); } } function post(){ var url = "http://myhost/ok.html"; for(var i=0;i<1000;i++){ send_request("POST",url,'name=axman&test=123'); } } </script> <input type="button" name="b1" value="get" οnclick="get()"> <input type="button" name="b2" value="post" οnclick="post()">
这个页面上两种方式访问和传递的参数完全一致,当我按下get按钮后,服务端收到了1000个访问记录。

[admin@vm-platform access_log]$ cat apache_access.log.4 |wc -l
1000
然后我统计访问时间大于1ms的记录:

[admin@vm-platform access_log]$ cat apache_access.log.4 |awk '{if($12 > 1000) print $0}'

结果是空。

现在我们再按下POST按钮:

[admin@vm-platform access_log]$ cat apache_access.log.4 |wc -l
2000

当服务端显示2000时,说明访问完成。

[admin@vm-platform access_log]$ cat apache_access.log.4 |awk '{if($12 > 1000) print $0}'的结果:


10.16.14.82 - - - [24/Nov/2011:16:08:55 +0800] "POST /myhost/ok.html HTTP/1.1" 200 20 696078 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)" - - "a=-; b=-; c=-" -
10.16.14.82 - - - [24/Nov/2011:16:08:55 +0800] "POST /myhost/ok.html HTTP/1.1" 200 20 696045 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)" - - "a=-; b=-; c=-" -
10.16.14.82 - - - [24/Nov/2011:16:08:55 +0800] "POST /myhost/ok.html HTTP/1.1" 200 20 695776 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)" - - "a=-; b=-; c=-" -
10.16.14.82 - - - [24/Nov/2011:16:08:55 +0800] "POST /myhost/ok.html HTTP/1.1" 200 20 695332 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)" - - "a=-; b=-; c=-" -
10.16.14.82 - - - [24/Nov/2011:16:08:55 +0800] "POST /myhost/ok.html HTTP/1.1" 200 20 696500 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)" - - "a=-; b=-; c=-" -
10.16.14.82 - - - [24/Nov/2011:16:08:55 +0800] "POST /myhost/ok.html HTTP/1.1" 200 20 696484 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)" - - "a=-; b=-; c=-" -
10.16.14.82 - - - [24/Nov/2011:16:08:55 +0800] "POST /myhost/ok.html HTTP/1.1" 200 20 696215 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)" - - "a=-; b=-; c=-" -
10.16.14.82 - - - [24/Nov/2011:16:08:55 +0800] "POST /myhost/ok.html HTTP/1.1" 200 20 696235 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)" - - "a=-; b=-; c=-" -
10.16.14.82 - - - [24/Nov/2011:16:08:55 +0800] "POST /myhost/ok.html HTTP/1.1" 200 20 696182 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)" - - "a=-; b=-; c=-" -
10.16.14.82 - - - [24/Nov/2011:16:08:55 +0800] "POST /myhost/ok.html HTTP/1.1" 200 20 694964 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)" - - "a=-; b=-; c=-" -
10.16.14.82 - - - [24/Nov/2011:16:08:58 +0800] "POST /myhost/ok.html HTTP/1.1" 200 20 1274 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)" - - "a=-; b=-; c=-" -
10.16.14.82 - - - [24/Nov/2011:16:08:59 +0800] "POST /myhost/ok.html HTTP/1.1" 200 20 1019 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)" - - "a=-; b=-; c=-" -

请注意apache %D记录的时间是从第一个头域(读到第一个换行回车开始)记时到响应输出(协议层,只要写到BUFF中,不一定已经发送到客户端)。这个时间单位是

微秒,请看一下其中有10条记录近700ms,是get方式的千倍。

因为这个现象给我们的两个应用带来性能问题,我开始分析这个原因,后来从网上搜索到文章说IE内核的浏览器在AJAX调用时,对POST方式采用两步发送,第一次发送

头域,第二次发送BODY。中间有很大的延迟,有时还会造成BODY包丢失,我们从网络抓包的情况看,确实存在只发送了HEADER,后面只有服务端超时返回的错误数据包,再也没有BODY的数据。这样的机率大约有1%.

这个问题在apache作为proxy时,proxy就不能在有效的时间内将客户端请求发送给backend,造成大量的内部错误输出。如果是SS还会引起数据时序混乱。在发送\r\n\r\n后头域还有尾巴没有发送完成,这些现象都是从网络抓包监控到的。

如果换成fireFox,同样的AJAX代码执行POST就没有问题,关键是你根本无法控制用户不使用IE。

网上给出的解决方案试了一下根本不起作用(也许IE6可以起作用,我用的IE8就没有细测IE6),关键是只要部分浏览器发生这个情况,就会给应用带来很大的性能问题。

所以尽量少使用AJAX的POST方式提交数据,但是有时服务端为了安全的原因只允许POST提交,可以动态构造FORM表单,而尽量少使用AJAX来调用POST。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值