node.js http.get 在向远程站点发出 5 次请求后挂起
Posted
技术标签:
【中文标题】node.js http.get 在向远程站点发出 5 次请求后挂起【英文标题】:node.js http.get hangs after 5 requests to remote site 【发布时间】:2013-06-02 16:01:16 【问题描述】:我正在编写一个简单的 api 端点来确定我的服务器是否能够访问互联网。它工作得很好,但是在 5 个请求之后(每次都是 5 个)请求挂起。当我将 Google 切换到 Hotmail.com 时也会发生同样的事情,这让我觉得这是我的目标。我需要关闭 http.get 请求吗?我的印象是这个函数会自动关闭请求。
// probably a poor assumption, but if Google is unreachable its generally safe to say that the server can't access the internet
// using this client side in the dashboard to enable/disable internet resources
app.get('/api/internetcheck', function(req, res)
console.log("trying google...");
http.get("http://www.google.com", function(r)
console.log("Got status code!: " +r.statusCode.toString());
res.send(r.statusCode.toString());
res.end();
console.log("ended!");
).on('error', function(e)
console.log("Got error: " + e.message);
);
);
【问题讨论】:
具有“res.end()”行似乎会使浏览器“挂起”(即 Chrome 会在加载页面时卡住)。删除将导致状态代码成功呈现(无论这些请求发出多少次或多快 - 我在 for 循环中尝试了 100 次,一切顺利)。 【参考方案1】:这是 “正好 5”的原因:https://nodejs.org/docs/v0.10.36/api/http.html#http_agent_maxsockets
在内部,http
模块使用代理类来管理 HTTP 请求。默认情况下,该代理最多允许 5 个打开的连接到同一 HTTP 服务器。
在您的代码中,您不会使用 Google 发送的实际响应。因此代理假定您尚未完成请求,并将保持连接打开。因此,在 5 次请求之后,代理将不再允许您创建新连接,并将开始等待任何现有连接完成。
显而易见的解决方案是只使用数据:
http.get("http://www.google.com", function(r)
r.on('data', function() /* do nothing */ );
...
);
如果您遇到/api/internetcheck
路由被大量调用的问题,因此您需要允许超过 5 个并发连接,您可以增加连接池大小,或者完全禁用代理(尽管您在这两种情况下仍需要使用数据);
// increase pool size
http.globalAgent.maxSockets = 100;
// disable agent
http.get( hostname : 'www.google.com', path : '/', agent : false , ...)
或者也许使用HEAD
请求而不是GET
。
(PS:如果http.get
产生错误,你仍然应该使用res.end()
或类似的东西来结束HTTP响应)。
注意:在 Node.js 版本 >= 0.11 中,maxSockets
设置为 Infinity
。
【讨论】:
只是为了补充这个出色的答案 - 我的问题是当我从远程服务器加载 PNG blob 时,在没有匹配的博客的情况下,我默认为默认二进制 blob 而不是返回404 错误。我遇到了这个问题,因为我没有使用加载的数据......非常聪明!所以如上所述 - include r.on('data', function() /* do nothing */ );它会欺骗它认为你这样做并关闭连接! 恢复一个相当老的帖子,但是,消费要求是否也适用于非 200 响应?如果你得到类似 4xx 或 5xx 的东西并且不使用 r.on('data') 进行消费,那么该连接是否没有关闭? @Johnny 我想这将取决于(某种程度上)远程服务器,但即使对于非 200 响应,我认为您应该假设您需要在http
模块之前阅读整个响应将连接返回到池中。
@robertklep 是的,你说得对,我也添加了一些东西来应对不良反应,然后挂断停止了!
@matt 看到了光,最近的 Node 版本设置了 Infinity
的限制。【参考方案2】:
如果您等待的时间足够长,5 个请求将超时,接下来的 5 个请求将被处理,因此应用程序不会真正挂起,因为它最终会处理所有请求。
要加快处理速度,您需要对响应数据进行处理,例如 r.on('data', function() );
【讨论】:
以上是关于node.js http.get 在向远程站点发出 5 次请求后挂起的主要内容,如果未能解决你的问题,请参考以下文章
如何在向某些站点发出 HttpWebRequest 时修复“底层连接已关闭:连接已意外关闭”
Elasticsearch:使用 Filebeat 从 Node.js Web 应用程序提取日志
Elasticsearch:使用 Filebeat 从 Node.js Web 应用程序提取日志