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

12 Comments

  1. SMS Gateway
    SMS Gateway November 26, 2018

    It is important to check the global reach before choosing an SMS gateway provider. If you own a website or mobile application, the SMS gateway should have international range so you can send messages to customers, users and affiliates.

  2. 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.

  3. 齐萌
    齐萌 February 4, 2012

    1.只要把浏览器的缓存禁用,就会发现不存在串行化的问题
    这时多次请求是同时发起的,5s后同时结束
    2.如果浏览器的缓存不禁用
    浏览器是期望相同的URL服务器返回304的响应,但可惜的是第一次响应内容没有缓存,因此每次请求都是串行,执行顺序是 5s+5s+5s
    但如果浏览器发送了cache响应,那么
    第一次执行5s,之后均为缓存 那么执行顺序是是 5s +0 +0
    总结,这个功能其实是给网页上的图片准备的

  4. 齐萌
    齐萌 February 4, 2012

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

  5. Anonymous
    Anonymous November 16, 2011

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

  6. Lukin
    Lukin October 20, 2011

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

  7. laruence
    laruence September 21, 2011

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

  8. phptea
    phptea September 21, 2011

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

  9. Anonymous
    Anonymous July 26, 2011

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

  10. 雪候鸟
    雪候鸟 July 17, 2011

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

  11. 冬眠
    冬眠 July 17, 2011

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

  12. xufan
    xufan July 16, 2011

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

Comments are closed.