EDIT
经过一番思考,我终于找到了一些看起来可能是可靠的线索:
当 Express 库当前正在使用 Node+OAuth 模块执行多个出站请求(例如,到 Facebook、Twitter 等)时,它无法接受传入请求。我能够通过在代码中放置大量日志来确定这一点,我发现在出站请求中间时不会触发“开始请求”日志(如下所述)。
我已经能够清楚地表明,当 Node+OAuth 模块发出一些出站请求时,对我的 API 的入站请求(通过浏览器窗口)将挂起并且不会被接收,直到其中一个出站 OAuth 请求完成为止。
当然,我已经做了:
require('http').globalAgent.maxSockets = 999;
根据 IRC 中的建议,我添加了
console.log(require('http').globalAgent.requests);
但这似乎总是 === {},这意味着据我所知没有待处理的入站请求。
因此,我得出的结论是,出于某种原因,node.js 或express 选择阻止由于出站请求而导致的传入请求,即使应该有大量可用的套接字......
有人对如何解决这个问题有任何提示吗?
我有一个使用 Express、Mongoose 等在 Node.js 中创建的 API,部署在 Amazon 云上,该 API 在 99% 的情况下都运行良好且快速。
但偶尔,某个请求似乎会以某种方式被丢弃或以其他方式被忽略。我说的是通常在几毫秒内完成的请求,随机无响应且没有清晰的图片why.
症状是连接到 API 端点时出现简单的“网关超时”。同一客户端使用相同参数发出的相同请求,无论是在之前还是之后,都可以正常工作。
当然,我的第一个想法是“呃,服务器超载!”所以我花了很多时间优化我的请求、mongoDB 等。最后我发现 CPU/磁盘/RAM 的整体使用情况(在 Node.js 服务器和 Mongo 服务器中)是very低的。我使用 Scout 和 RightScale 实时跟踪我的服务器,并记录任何耗时超过 100 毫秒的请求或查询。我的节点服务器目前有 5GB 的可用 RAM、70% 的可用 CPU(在第一个核心上)等。所以我 99.99% 确定这不是性能问题。
最后,我孤注一掷:我在客户提出的所有请求中附加了一个随机数。然后,在 node.js 应用程序中,我在首次收到请求和完成请求时执行 console.log() 。例如,这是我在express中使用的中间件:
var configureAPI = function() {
return function(req, res, next) {
if(req.body.ruid)
console.log(req.body.ruid);
// more middleware stuff...
};
}
server.configure(function(){
server.use(express.bodyParser());
server.use(configureAPI());
server.use(onError);
// ... more config stuff
}
我的发现令我震惊:显然,Node.js 应用程序甚至没有收到有问题的请求。我有一个 Javascript Web 应用程序,我将随请求发送到控制台的“ruid”打印出来。每当请求成功时,node.js 控制台中就会打印相应的“ruid”。每当超时,就没有。
编辑:更多调试和信息。
我的应用程序服务器实际上启动(并继续)也提供 PHP 服务(因此,它们安装了 Apache 等)。我需要http://streamified.me http://streamified.me为我的网站(PHP)提供服务并且http://api.streamified.me http://api.streamified.me为我的 API (node.js) 提供服务...所以我的 httpd.conf 文件中有一行可以导致对 api.streamified.me (而不是 Streamified.me)的请求通过端口 8888 转到 node.js:
RewriteCond %{HTTP_HOST} ^api.streamified.me
RewriteRule ^(.*) http://localhost:8888$1 [P]
因此,在同一个 httpd.conf 文件中,我打开了 RewriteLogLevel 5,然后在本地主机上创建了一个简单的 PHP+CURL 脚本,以使用随机 URL 访问我的 api.streamified.me(这应该会导致 node.js 触发一个简单的“未找到”响应),直到导致网关超时。在这里,您可以看到它已经发生了——并且重写日志显示该请求肯定已被应用程序服务器接收并转发到端口 8888...但它从未被 node.js 接收过(或者,至少,中间件第一行中的第一行代码永远不会得到它......)
我已经一遍又一遍地检查我的 Node.js 代码,并且非常确定我没有阻塞代码,即使我有,我也无法想象它会阻塞线程足够长的时间以错过请求而不在某处引发红旗。
我缺少什么?是否有某种原因导致传入套接字被阻止?我确实通过我的 node.js 应用程序向外部 API 发出了相当多的 HTTP 请求,但据我所知,这不应该阻止传入的套接字。
当然,我有错误日志记录。我已在进程级别启用它......
process.addListener("uncaughtException", function (err) {
// some logging code
}
以及 Express 级别(上面的 onError 处理程序)。我知道我的错误记录功能可以工作,因为我以前见过它们都触发过。但他们都没有在删除请求时报告任何内容,我也没有在控制台中看到任何内容......
- 快速版本:3.0.0rc5
- Node.js 版本:0.8.12
- 在标准 Amazon Cloud 设置(m1.large 实例)上运行的 Node.js 应用程序的 2 个实例,位于 2 个负载均衡器后面,连接到 3 个 MongoDB 副本集(也是 m1.large)