Press "Enter" to skip to content

浏览器多tab打开同一URL串行化的问题

最近同事”神经病”同学的项目中, 发现一个问题.

用firefox打开多个tab, 每个tab都去请求同一个URL(尽量同时), 会发现, 这些请求, 会被浏览器串行化.

也就是说, 浏览器会在第一个页面请求结束以后, 再发起第二个请求,

比如对于如下脚本:

<?php
error_log("start . " . getmypid(). "\n");
sleep(5);
error_log("end . " . getmypid() . "\n");

用firefox打开多个tab同时请求这个脚本, 观察error_log

start . 3734\n
end . 3734\n
start . 3733\n
end . 3733\n
start . 3733\n
end . 3733\n

多方求证这个问题, 但无果, 得到的都是对这个现象的描述, 但没有得到为什么浏览器会这么做, 或者是什么让它们这么设计, 后来得到在mod_perl中的一段叙说:

Certain browsers will serialize requests to the same URL if accessed from different windows. For example if you have a CGI script that does:

for (1..100) {
print “$$: $_\n”;
warn “$$: $_\n”;
sleep 1;
}
And two concurrent requests are issued from different windows of the same browser (for those browsers that have this bug/feature), the browser will actually issue only one request and won’t run the second request till the first one is finished. The debug printing to the error_log file helps to understand the serialization issue.

Solution? Find a UA that doesn’t have this feature, especially if a command line UA will do (LWP comes to mind). As of this writing, opera 6, mozilla 1.0 on linux have this problem, whereas konqueror 3 and lynx don’t.

随后, 我验证了chrome也有这个问题, 不过上面的文字也说了, 这些是特定浏览器的特定行为, 比如命令行的wget, ab之类的就没有这个特定行为.

我也尝试翻看HTTP 1.1RFC和webkit的源代码, 不过也无奈找不到线索…

bitbull说可能是为了复用一个链接, 不过此时通过netstat, 会发现本地确实是打开了多个链接, 所以应该不是为了复用一个链接而这么设置的.

各位如果有对这个特性详细描述, 并且解释为什么这么设计的文档, 请一定转发一个给我.

thanks

11 Comments

  1. Do you have a spam issue on this website; I also am a blogger, and I was curious about your situation; many of us have created some nice methods and we are looking to trade strategies with other folks, please shoot me an e-mail if interested.

  2. 齐萌
    齐萌 2012-02-04

    1.只要把浏览器的缓存禁用,就会发现不存在串行化的问题
    这时多次请求是同时发起的,5s后同时结束

    2.如果浏览器的缓存不禁用
    浏览器是期望相同的URL服务器返回304的响应,但可惜的是第一次响应内容没有缓存,因此每次请求都是串行,执行顺序是 5s+5s+5s

    但如果浏览器发送了cache响应,那么

    第一次执行5s,之后均为缓存 那么执行顺序是是 5s +0 +0

    总结,这个功能其实是给网页上的图片准备的

  3. 齐萌
    齐萌 2012-02-04

    好吧,这个问题我来解释下

  4. Anonymous
    Anonymous 2011-11-16

    这个是浏览器的设计问题,首先是持久连接问题,在连接的超时时间范围内(一般是1分钟),浏览器会重用一个连接发送请求,另外是多线程问题,以前的浏览器可能不支持多线程,也就是同时发送多个HTTP连接。现在的浏览器都支持多线程,但是都有一个限制,一般都在10个以内,像firefox可以用about:config配置,如果达到线程限制肯定会串行化

  5. Lukin
    Lukin 2011-10-20

    phptea 说的对,就是这个原因,多个ajax请求如果开启session也会遇到这个问题。

  6. laruence
    laruence 2011-09-21

    @phptea 测试代码已经包含在文章中, 没有Session, 另外,这是client的序列化, 不是Server的序列化.

  7. phptea
    phptea 2011-09-21

    服务端session如果以文件方式存放,会锁文件,加锁了,所以这些请求会串行化

  8. Anonymous
    Anonymous 2011-07-26

    看看是否用了session,如果设置了自动开启session,那么会这样被阻塞的。

  9. 雪候鸟
    雪候鸟 2011-07-17

    @xufan hi, 大方向上应该是有关的,不过具体的这个问题上, 是没有关系的, 呵呵

  10. 冬眠
    冬眠 2011-07-17

    自己的一点想法:如果开多个socket,那么cookie等登录信息的维护是一个很麻烦的事,比如请求URL A 与URL B,B是一个登录请求,而A不是,如果A比B后返回,那么这时Cookie的信息就会乱掉。

  11. xufan
    xufan 2011-07-16

    HTTP 1.1里面有一个Connection: Keep-Alive header,是否与这个有关?浏览器对同时连接数有限制,为了处理keep-alive,浏览器对于一个网站的请求会排队,服务器接收请求也是排队的(Keep-Alive的请求是同一个socket,新的请求时继续从原来的socket读,上一个请求没返回,由于处理是while循环,下一个请求是没法读取的)。例如浏览器限制为最大连接数为2,如果同时有3个请求,服务器端不返回,第3个请求浏览器是不会发出的。像wget类似的客户端一般会主动断开连接,而且每次是用新的socket发送请求。

Leave a Reply

Your email address will not be published. Required fields are marked *