2012-10-12 41 views
6

编辑的Node.js +快递随机中断请求,导致网关超时

多putzing身边后,我终于找到的东西,好像它可能是一个固体铅:

快递库在当前使用Node + OAuth模块执行多个出站请求(例如,Facebook,Twitter等)时未能接受传入请求。我可以通过在我的代码中放置大量日志来确定这一点,我发现在出站请求中间没有触发“开始 - 请求”日志(如下所述)。

我已经能够证明,当Node + OAuth模块发出几个出站请求时,通过浏览器窗口对我的API的入站请求将挂起并且不会被接收,直到其中一个出站OAuth请求已完成。

当然,我已经做了:

require('http').globalAgent.maxSockets = 999; 

每一个建议在IRC,我已经添加

console.log(require('http').globalAgent.requests); 

但这似乎总是=== {},这意味着没有待处理的入站请求AFAIK。

因此我留下得出结论,无论是Node.js的或表达的是选择到,出于某种原因,由于出站请求块传入的请求,即使应该有大量可用的套接字...

任何人有任何提示如何解决这个问题?


我在使用快递,猫鼬等,部署在Amazon云这奇妙的作品和快速的99%的时间node.js中创建的API。

除了,过一段时间,请求似乎不知何故掉落或忽略。我正在讨论通常以毫秒为单位完成的请求,并且没有任何清晰的图像,因此随机无响应为什么

症状是一个简单的“网关超时”连接到API端点时。在同一个客户端使用相同的参数创建一个相同的请求,就在之前或之后的某个时刻,可以很好地工作。

当然,我首先想到的是“咄,服务器超载!”所以我花了很多时间来优化我的请求,monogoDB等等。最后,我发现整个电路板(包括Node.js服务器和Mongo服务器)的CPU /磁盘/ RAM使用率为非常低。我使用Scout和RightScale实时跟踪我的服务器,并且记录超过100ms的任何请求或查询。我的节点服务器目前有5GB的可用内存,70%的可用CPU(第一核心)等等,所以我99.99%肯定这不是性能问题。

最后,我就拼命回落:我重视我的客户(S)由随机数所有请求。然后,在node.js应用程序中,当请求第一次被接收并且完成时,我做了一个console.log()。例如,这里是我的快递使用的中间件:

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 
} 

我找到了什么让我震惊:显然,节点。js应用程序甚至没有收到有问题的请求。我有一个JavaScript web应用程序,并打印与请求一起发送到控制台的“ruid”。只要请求成功,node.js控制台中就会显示相应的“ruid”。每当它超时,就没有。


编辑:更多调试&信息。

我的应用程序服务器实际上启动(并继续)也提供PHP(因此,他们已安装Apache等)。我需要http://streamified.me来为我的网站(PHP)和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 +卷曲脚本在我的本地打我的API。用随机的URL(这会导致node.js触发一个简单的“not found”响应)streamified.me,直到它导致网关超时。在这里,你可以看到它发生了 - 重写日志显示请求已被应用程序服务器明确接收并转发到端口8888 ...但它从来没有被node.js收到(或者至少在中间件从来没有得到它的第一行的第一行代码...)

enter image description here


我已经一遍又一遍我的Node.js代码,并敢肯定我没有阻挡代码,即使我这样做了,我也无法想象它会阻塞线程足够长的时间以致错过某个请求,而不会在某处引发红旗。

我错过了什么?传入的套接字是否会被阻塞?我通过我的node.js应用程序向外部API发送了相当多的HTTP请求,但AFAIK不应该阻止传入的套接字。


当然,我有错误记录到位。我已经在过程级别上启用它...

process.addListener("uncaughtException", function (err) { 
    // some logging code 
} 

和Express级别(上面的onError处理程序)。我知道我的错误日志记录功能是有效的,因为我看过他们都在之前发作。但无论他们的报告围绕着下降请求的时候什么,我也不在控制台中看到什么...


  • 快递版本:3.0.0rc5
  • Node.js的版本:0.8。在一个标准的亚马逊云设置(m1.large实例)运行的node.js应用程序,后面2个负载平衡器12分
  • 2的情况下,连接到3×副本集MongoDBs(也m1.large)
+0

您已确认负载均衡器正在接收请求并将其成功发送到节点服务器?当一个人失败时你多久提出一次请求? – Bill

+0

相同的LB /应用程序服务器也提供PHP文件,永远不会造成超时。但我不太清楚如何确认LB正确转发到节点服务器,不过,除此之外。我没有出现任何交通高峰。 Rightscale上的apache日志报告一致~10 req/sec。 –

+0

我发现了一些列出的类似问题的错误,但它们都是由0.6.6修复的。您可能会尝试升级到最新版本,因为自0.6版以来已经进行了大量修复/改进。我还建议你在你的应用服务器上设置网络嗅探器,以确保服务器实际上正在接收数据包。 – Bill

回答

1

这听起来像你锁起来您的Node线程太长,导致传入连接在处理它们之前超时。节点是单线程的,所以它一次只能做一件事,它不能选择阻止一个传入的请求。它只能接受传入的请求,因为它忙于做其他事情。你需要弄清楚它在忙什么。

如果你不发出出站请求,一切工作正常?如果是这样,你需要看看这些请求的代码,以确保你没有等待回应。

+0

这是有道理的。我是积极的,我没有做任何“同步”任务,我使用Q来实现承诺。唯一值得关注的是JSON.parse()命令,它们正在评估大量(〜2MB)的数据字符串。这些操作可能会阻止该线程吗? –

+0

有些数据可能会返回大于2MB? 2MB不应该挂起线程足够长的时间来放弃请求(虽然它会阻塞一些东西),但如果偶尔尝试解析更大的字符串,它可能是罪魁祸首。您可以尝试用一个调用来替换解析,以返回静态数据以查看是否可以解决问题。 – Bill

+0

嗯,我无法真正使用静态数据,因为JSON解析会影响下游的事情,并且通过使用静态数据,我只能测试1场景......无论如何,我开始输出解析()次,有时大约在100ms左右(并且通常有几次背靠背,尽管按承诺分开)。另外,我刚刚发生了第一次出现OOM错误“致命错误:CALL_AND_RETRY_2分配失败 - 进程内存不足”......这让我想知道这是否是问题的一部分......虽然这是我第一次我见过这样的错误... –