Chrome在向同一资源发出多个请求时会出现停顿?

66
我正在尝试首次实现长轮询,并使用XMLHttpRequest对象来执行。到目前为止,我成功地在Firefox和Internet Explorer 11中获取了事件,但是Chrome这一次变得异常。
我可以加载一个页面,它可以正常运行。它立即发出请求并开始处理和显示事件。如果我在第二个标签中打开页面,则其中一个页面开始接收事件的延迟。在开发工具窗口中,我看到多个具有此类型计时的请求:

screenshot

"Stalled" 最多会持续 20 秒。这种情况不会在每个请求中发生,但通常会在一段时间内的多个请求中连续出现,并且仅在一个标签页中发生。
一开始我以为这是我的服务器出了问题,但是我打开了两个 IE 标签页和两个 Firefox 标签页,它们都可以连接并接收相同的事件而没有停顿。只有 Chrome 出现了这种问题。
我认为这很可能是由于我发起或提供请求的方式所导致的问题。供参考的是,请求头如下:
Connection: keep-alive
Last-Event-Id: 530
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
Accept: */*
DNT: 1
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8

响应如下:
HTTP/1.1 200 OK
Cache-Control: no-cache
Transfer-Encoding: chunked
Content-Type: text/event-stream
Expires: Tue, 16 Dec 2014 21:00:40 GMT
Server: Microsoft-HTTPAPI/2.0
Date: Tue, 16 Dec 2014 21:00:40 GMT
Connection: close

尽管涉及标题,但我没有使用浏览器的原生EventSource,而是使用了一个可以让我设置额外标题的polyfill。该polyfill在底层使用XMLHttpRequest,但我认为无论请求是如何进行的,它都不应该停顿20秒钟。可能是什么原因导致Chrome这样停滞吗? 编辑: Chrome的chrome://net-internals/#events页面显示存在超时错误。
t=33627 [st=    5]      HTTP_CACHE_ADD_TO_ENTRY  [dt=20001]
                --> net_error = -409 (ERR_CACHE_LOCK_TIMEOUT)

错误信息是指向六个月前Chrome添加的一个补丁 (https://codereview.chromium.org/345643003),该补丁在同一资源被多次请求时实现了 20 秒超时。事实上,补丁试图修复的一个错误 (bug number 46104) 涉及类似的情况,而该补丁旨在 减少 等待时间。
可能的答案(或解决方法)是使请求看起来不同,尽管也许 Chrome 可以尊重我设置的“no-cache”头。

它说数字46104没有问题。 - B T
请跟随我上面链接的问题底部的BUG链接,该链接带有相应的编号。 - mrdecemberist
或者让我看看现在能否直接链接:https://code.google.com/p/chromium/issues/detail?id=46104 - mrdecemberist
这与我在这里的体验相同吗?使用Chrome 42 https://www.youtube.com/watch?v=PYorlA63ZzI&feature=youtu.be&hd=1 - nitech
在 Chrome 75.0.3770.100 中,没有任何一种提到的方法起作用 - 有什么想法来解决这个问题吗? - user3579222
4个回答

56

是的,这种行为是由Chrome锁定缓存并等待在请求相同资源之前看到一个请求结果引起的。解决方法是找到一种使请求唯一的方法。我在查询字符串中添加了一个随机数,现在一切都正常了。

供参考,这是Chrome 39.0.2171.95版本。

编辑: 自从回答这个问题后,我了解到"Cache-Control: no-cache"并不像我原先想象的那样起作用。尽管它的名称是no-cache,但带有此标题的响应可能会被缓存。我没有尝试过,但我想知道是否使用"Cache-Control: no-store"可以解决这个问题,因为它确实可以防止缓存。


1
这是否意味着,如果您通过在键盘上不断按[F5]来垃圾邮件式地请求您的网站,Chrome会在加载时出现视觉“挂起”? - Tomasz Kowalczyk
4
“Cache-Control: no-store” 对我很有帮助!非常好的答案,谢谢 :D - mpyw
3
我遇到了这个问题,使用 Cache-Control: no-cache, no-store 对我很有帮助。非常感谢! - Michael Tiller
3
我在服务器中故意放置了一个10秒的“休眠”,发现如果我同时在两个具有相同网址的chrome窗口中刷新,第一个窗口需要10秒钟,而第二个窗口需要20秒钟。从服务器日志中可以看到,即使在第二个窗口中显示状态为“挂起”,chrome也不会在第一个请求完成之前发送第二个请求,并且整个过程都需要20秒钟。这与HTTP头部无关。如果URL不同或使用Firefox,则不会出现此问题。 - Andy
2
接受的答案实际上已经不再起作用了。在较新版本的Chrome中(我检查了100版),添加缓存控制并不能允许并行请求。 - Sly
显示剩余15条评论

2

我决定保持简单,并检查了一个没有这个问题的网站的响应头,然后我改变了我的响应头以匹配他们的响应头:

Cache-Control: max-age=3, must-revalidate

2

在我的情况下,添加Cache-Control: no-cache, no-transform就解决了问题。


0
我遇到了相同的问题。缓存控制标头没有帮助。但是我只是添加了额外的查询参数,使用随机值使所有请求都变得独特。这样就可以解决了。
GET /long-polling?rand=123

GET /long-polling?rand=456

Chrome认为它们是不同的请求。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接