请求偶尔在chrome中停滞很长时间

Posted

技术标签:

【中文标题】请求偶尔在chrome中停滞很长时间【英文标题】:request stalled for a long time occasionally in chrome 【发布时间】:2015-02-28 16:45:37 【问题描述】:

Ajax 请求偶尔会在 chrome 中停滞很长时间。

如果有人可以帮助我,我终于设法复制并保存了所有必要的相关数据,以便在此处发布。

Chrome 开发工具的时间线显示请求停滞了 42.62 秒,如以下屏幕截图所示:

chrome://net-internals/#events(事件日志请到最后)页面中,我发现最多的时间是两个事件:

+HTTP_TRANSACTION_READ_HEADERS [dt=21301] +HTTP_TRANSACTION_READ_HEADERS [dt=21304]

两者都得到ERR_CONNECTION_RESET

我认为错误是请求停滞这么久的原因。

任何人都可以解释错误?

以下是请求的事件日志,我还将完整的事件导出为 json,您可以从 here 获取,然后在 Chrome chrome://net-internals/#events 页面中恢复。请注意,请求 url 是内部的,因此可能无法从公共网络访问:

193486: URL_REQUEST
http://qa.tieba.baidu.com/release/getReleaseHistory?projectId=fum1.0.593
Start Time: 2015-01-02 17:51:05.323

t=    1 [st=    0] +REQUEST_ALIVE  [dt=42741]
t=    1 [st=    0]    URL_REQUEST_DELEGATE  [dt=0]
t=    1 [st=    0]   +URL_REQUEST_START_JOB  [dt=42740]
                      --> load_flags = 339804160 (BYPASS_DATA_REDUCTION_PROXY | MAYBE_USER_GESTURE | REPORT_RAW_HEADERS | VERIFY_EV_CERT)
                      --> method = "GET"
                      --> priority = "LOW"
                      --> url = "http://qa.tieba.baidu.com/release/getReleaseHistory?projectId=fum1.0.593"
t=    2 [st=    1]      URL_REQUEST_DELEGATE  [dt=0]
t=    2 [st=    1]      HTTP_CACHE_GET_BACKEND  [dt=0]
t=    2 [st=    1]      HTTP_CACHE_OPEN_ENTRY  [dt=0]
t=    2 [st=    1]      HTTP_CACHE_ADD_TO_ENTRY  [dt=0]
t=    2 [st=    1]      HTTP_CACHE_READ_INFO  [dt=0]
t=    2 [st=    1]      URL_REQUEST_DELEGATE  [dt=0]
t=    2 [st=    1]     +HTTP_STREAM_REQUEST  [dt=2]
t=    4 [st=    3]        HTTP_STREAM_REQUEST_BOUND_TO_JOB
                          --> source_dependency = 193488 (HTTP_STREAM_JOB)
t=    4 [st=    3]     -HTTP_STREAM_REQUEST
t=    4 [st=    3]     +HTTP_TRANSACTION_SEND_REQUEST  [dt=0]
t=    4 [st=    3]        HTTP_TRANSACTION_SEND_REQUEST_HEADERS
                          --> GET /release/getReleaseHistory?projectId=fum1.0.593 HTTP/1.1
                              Host: qa.tieba.baidu.com
                              Connection: keep-alive
                              Accept: application/json, text/plain, */*
                              User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/39.0.2171.95 Safari/537.36
                              Referer: http://qa.tieba.baidu.com/project/
                              Accept-Encoding: gzip, deflate, sdch
                              Accept-Language: en-US,en;q=0.8
                              Cookie: [268 bytes were stripped]
t=    4 [st=    3]     -HTTP_TRANSACTION_SEND_REQUEST
t=    4 [st=    3]     +HTTP_TRANSACTION_READ_HEADERS  [dt=21301]
t=    4 [st=    3]        HTTP_STREAM_PARSER_READ_HEADERS  [dt=21301]
                          --> net_error = -101 (ERR_CONNECTION_RESET)
t=21305 [st=21304]        HTTP_TRANSACTION_RESTART_AFTER_ERROR
                          --> net_error = -101 (ERR_CONNECTION_RESET)
t=21305 [st=21304]     -HTTP_TRANSACTION_READ_HEADERS
t=21305 [st=21304]     +HTTP_STREAM_REQUEST  [dt=3]
t=21307 [st=21306]        HTTP_STREAM_REQUEST_BOUND_TO_JOB
                          --> source_dependency = 193494 (HTTP_STREAM_JOB)
t=21308 [st=21307]     -HTTP_STREAM_REQUEST
t=21308 [st=21307]     +HTTP_TRANSACTION_SEND_REQUEST  [dt=3]
t=21308 [st=21307]        HTTP_TRANSACTION_SEND_REQUEST_HEADERS
                          --> GET /release/getReleaseHistory?projectId=fum1.0.593 HTTP/1.1
                              Host: qa.tieba.baidu.com
                              Connection: keep-alive
                              Accept: application/json, text/plain, */*
                              User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
                              Referer: http://qa.tieba.baidu.com/project/
                              Accept-Encoding: gzip, deflate, sdch
                              Accept-Language: en-US,en;q=0.8
                              Cookie: [268 bytes were stripped]
t=21311 [st=21310]     -HTTP_TRANSACTION_SEND_REQUEST
t=21311 [st=21310]     +HTTP_TRANSACTION_READ_HEADERS  [dt=21304]
t=21311 [st=21310]        HTTP_STREAM_PARSER_READ_HEADERS  [dt=21304]
                          --> net_error = -101 (ERR_CONNECTION_RESET)
t=42615 [st=42614]        HTTP_TRANSACTION_RESTART_AFTER_ERROR
                          --> net_error = -101 (ERR_CONNECTION_RESET)
t=42615 [st=42614]     -HTTP_TRANSACTION_READ_HEADERS
t=42615 [st=42614]     +HTTP_STREAM_REQUEST  [dt=12]
t=42627 [st=42626]        HTTP_STREAM_REQUEST_BOUND_TO_JOB
                          --> source_dependency = 193498 (HTTP_STREAM_JOB)
t=42627 [st=42626]     -HTTP_STREAM_REQUEST
t=42627 [st=42626]     +HTTP_TRANSACTION_SEND_REQUEST  [dt=2]
t=42627 [st=42626]        HTTP_TRANSACTION_SEND_REQUEST_HEADERS
                          --> GET /release/getReleaseHistory?projectId=fum1.0.593 HTTP/1.1
                              Host: qa.tieba.baidu.com
                              Connection: keep-alive
                              Accept: application/json, text/plain, */*
                              User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
                              Referer: http://qa.tieba.baidu.com/project/
                              Accept-Encoding: gzip, deflate, sdch
                              Accept-Language: en-US,en;q=0.8
                              Cookie: [268 bytes were stripped]
t=42629 [st=42628]     -HTTP_TRANSACTION_SEND_REQUEST
t=42629 [st=42628]     +HTTP_TRANSACTION_READ_HEADERS  [dt=112]
t=42629 [st=42628]        HTTP_STREAM_PARSER_READ_HEADERS  [dt=112]
t=42741 [st=42740]        HTTP_TRANSACTION_READ_RESPONSE_HEADERS
                          --> HTTP/1.1 200 OK
                              Date: Fri, 02 Jan 2015 09:51:48 GMT
                              Content-Type: application/json; charset=UTF-8
                              Transfer-Encoding: chunked
                              Connection: keep-alive
                              Cache-Control: no-cache
                              tracecode: 31079600320335034634010217
                              tracecode: 31079600320537995786010217
                              Server: Apache
t=42741 [st=42740]     -HTTP_TRANSACTION_READ_HEADERS
t=42741 [st=42740]      HTTP_CACHE_WRITE_INFO  [dt=0]
t=42741 [st=42740]      HTTP_CACHE_WRITE_DATA  [dt=0]
t=42741 [st=42740]      HTTP_CACHE_WRITE_INFO  [dt=0]
t=42741 [st=42740]      URL_REQUEST_DELEGATE  [dt=0]
t=42741 [st=42740]   -URL_REQUEST_START_JOB
t=42741 [st=42740]    URL_REQUEST_DELEGATE  [dt=0]
t=42741 [st=42740]    HTTP_TRANSACTION_READ_BODY  [dt=0]
t=42741 [st=42740]    HTTP_CACHE_WRITE_DATA  [dt=0]
t=42741 [st=42740]    HTTP_TRANSACTION_READ_BODY  [dt=0]
t=42741 [st=42740]    HTTP_CACHE_WRITE_DATA  [dt=0]
t=42742 [st=42741] -REQUEST_ALIVE

编辑:相关问题 Issue 447463: Chrome-network: Long delay before RST message on stale sockets results in slow page loads.

【问题讨论】:

这仍然是个问题吗?我尝试访问qa.tieba.baidu.com/release/… 和qa.tieba.baidu.com/release 和qa.tieba.baidu.com 等变体,但都超时。如果您在本地网络上浏览,我建议您尝试相同的方法,看看这些链接是否也超时。请更新我们。 @Drakes,网址是内部访问,这就是你超时的原因。但这与这个问题无关。 我想知道 1) 当你直接访问它时这个 url 是否超时,2) 当你直接访问它时响应头是什么(检查 FF 或 Chrome),以及 3) json、jsonp还是其他ajax调用? 试了几次,直接访问无法重现,可能是ajax调用问题,我们使用json作为响应。 @Wayou,你得到答案了吗?我也遇到了同样的问题。 【参考方案1】:

我曾经遇到过类似的问题。问题的原因是每个浏览器都对与服务器的最大 TCP 连接数有限制。对于 chrome,限制为六个。当您使用代理服务器时问题更加突出,因为所有请求都通过同一台服务器(代理服务器)。

Chrome 不允许您更改此限制。事实上不应该。如果您想进一步了解为什么存在这个限制,以及其他浏览器的限制是什么,可以阅读this article。

这个限制很少成为问题的原因是,对同一主机的多个 HTTP 请求大多是连续发送的,而不是并行发送的,最好是通过同一个 TCP 连接发送。

如果你经常出现这个问题,那么原因可能是:

    服务器不支持持久 TCP 连接:如果问题仅在访问特定服务器时出现,原因可能是 chrome 正在获取多个资源(如图像、CSS 文件、等)在并行连接。由于在您的情况下,服务器位于您的本地网络上,您可能需要请求服务器管理员添加对持久 TCP 连接的支持。

    多个持久连接已打开:如果您在代理服务器后面工作,那么同时下载多个文件或打开保持 TCP 连接打开的站点可能是导致问题的原因。要摆脱它,你所能做的就是不要同时下载很多东西(或者如果必须的话,在不同的浏览器中下载)。

PS:错误net_error = -101 (ERR_CONNECTION_RESET)不是因为headers无效,是因为超时,等待一些之前的连接到服务器关闭。

【讨论】:

我现在看到了同样的行为,但是对于我的初始页面加载,不是 AJAX 调用,所以连接限制不是问题。我只打开了一个与站点的连接,即第一个请求。 @Sparr 你在代理服务器后面吗?问题是否仅出现在特定主机或所有网站上? 我不在代理服务器后面。问题发生在我们发现的几十台主机上,而不是大多数主机。 正如我报告的 chrome 问题中的讨论,似乎合理的解释是浏览器使用无效套接字发送请求。您提到的tcp连接的限制是另一种可能,但从日志文件中我们无法判断。 我的连接少于六个【参考方案2】:

这里有类似的问题,似乎过了一段时间,大约 3 分钟后,一个套接字 chrome 尝试使用被操作系统关闭(我假设)。

这在铬论坛中也被列为错误。我猜缺少某种“保持活力”机制。: https://code.google.com/p/chromium/issues/detail?id=447463

我的错误消息略有不同,但这可能是由于我的应用程序通过 SSL 进行调用。这是我在 chrome://net-internals 中看到的:

第一个 chrome 找到一个现有的套接字并将请求与之关联(HTTP_STREAM_JOB):

    t=1572 [st=0]    HTTP2_SESSION_POOL_FOUND_EXISTING_SESSION
                     --> source_dependency = 1347215 (HTTP2_SESSION)
    t=1572 [st=0]    HTTP_STREAM_JOB_BOUND_TO_REQUEST
                     --> source_dependency = 1348612 (URL_REQUEST)
    t=1572 [st=0] -HTTP_STREAM_JOB

然后返回 (URL_REQUEST) 你会看到它超时,注意从 t=1572 到 t=11573 的 10 秒时间流逝:

    t= 1572 [st=    0]  HTTP2_SESSION_SEND_DATA
                        --> fin = true
                        --> size = 48
                        --> stream_id = 3
    t= 1572 [st=    0]  HTTP2_SESSION_UPDATE_SEND_WINDOW
                        --> delta = -48
                        --> window_size = 2147483551
    t=11573 [st=10001]  HTTP2_SESSION_CLOSE
                        --> description = "Failed ping."
                        --> net_error = -352 (ERR_SPDY_PING_FAILED)

当 chrome 尝试调整现有套接字上的窗口大小时,显然存在超时。我认为这是由于套接字不活动造成的。

我将尝试以大约 60 秒的间隔执行某种心跳请求,以查看问题是否仍然存在。我将发布更新结果。

更新:

将以下代码添加到每个页面上加载的 javascript。这是从公共根目录检索一个空的 html 文档:

    $(document).ready(function() 
        $.keepalive =     
                setInterval(function() 
                   $.ajax(
                      url: '/ping.html',
                      cache: false
                   );         
                , 60000);    
    );

这似乎有助于保持套接字打开,即使下面的示例显示“真实”调用之间大约有 6 分钟:

在 60 秒间隔内每次调用 570B 时,ping 调用每 24 小时(每个浏览器会话)会增加大约 800kb 的带宽使用量。我不确定这会在服务器上造成多少 CPU 开销。

为了比较,之前:

必须有更好的解决方案,但我还没有找到。

【讨论】:

【参考方案3】:

我也遇到过类似的问题,已经解决了!

我的问题是小文件上传是好的,但是对于大文件它会停滞很长时间,并且从网络日志查看器中我发现文件数据的完整大小实际上是上传的,但不知何故 tcp 连接自动之后关闭,

然后从https://netlog-viewer.appspot.com/#sockets发现http请求要经过代理服务器,

于是我再次使用firefox用no-proxy设置绕过,但还是不成功,然后从firefox about:networking#dns我发现实际上域并没有直接解析到web服务器而是解析到一堆ip地址,原来是WAF,

最后我把hosts设置点域名直接改成web服务器ip地址,问题就解决了! 所以我确定根本原因是代理服务器和waf!他们可能有某种默认超时

【讨论】:

以上是关于请求偶尔在chrome中停滞很长时间的主要内容,如果未能解决你的问题,请参考以下文章

Chrome 事件触发在大型 DOM 中需要很长时间

Android Chrome:音频对象需要很长时间才能开始流式传输 mp3

偶尔会遇到长时间的垃圾收集延迟,为啥?

Spring mysql连接长时间断掉的问题

Python 请求很慢并且需要很长时间才能完成 HTTP 或 HTTPS 请求

当 uWSGI 处理请求需要很长时间时 Nginx 超时