Node.js:什么是自动重新启动没有响应的节点服务器的好方法?

我已经inheritance了一个有点乱的node.js / Express应用程序。 这是定期和相当随机卡住,没有响应任何请求,直到它重新启动。

我怀疑,应用程序内的东西是阻塞,要么陷入一个循环或向外部API请求,而不使用适当的asynchronous技术,永远不会得到一个响应,永远不会超时女巫点服务器停止响应,但不'没有崩溃。

我显然希望find罪魁祸首代码,并解决问题,但同时我想find一种方法来自动重新启动服务器,当它停止响应。

为了在本地testing解决scheme(因为我目前不知道真正的罪魁祸首),我创build了以下快速路由,它模拟了我所得到的确切行为。

app.get('/block-block-block', function (req, res){ for(;;) {} }; 

我有的问题是给上述路线被打(这会立即停止服务器响应任何东西),有没有办法检测内部节点堵塞,并重新启动或closures? 如果没有什么是一个很好的解决scheme来检查服务器没有响应,并重新启动它?

我做的大多数search引导我到像永远和PM2的工具。 如果你的应用程序崩溃,这些工作很好,但我真的没有看到任何function重新启动时,应用程序是radomley阻止。

首先,您应该通过查看代码来找出代码中的问题。

内存泄漏

对于正在运行的应用程序,您应该使用pm2 。 它有一个设置,以重新启动应用程序的内存消耗过多。 直接从文档 :

 pm2 start big-array.js --max-memory-restart 20M 

或者使用一个ecosystem.json

 { "max_memory_restart" : "20M" } 

还有几篇关于debuggingnode.js中的内存泄漏以在线查找的优秀 文章 。 甚至有一个模块报告我们在早期使用的泄漏 。 这是一个太大的话题来填补它在这里。

阻塞事件循环/无限循环

您可以testing您的应用程序来报告事件循环的响应。 因此,如果某些代码阻塞循环的时间过长,则可以通过编程方式终止该进程。 你将不得不看看process.nextTick

您可以引入一个度量值,例如每X秒调用一次process.nextTick ,如果超过一定的时间,则发送process.exit(1)来终止进程并让pm2重新启动它。

这个好处是你的应用程序大部分时间运行。 缺点是所有打开连接的用户在调用process.exit都不会得到任何答案。

debugging

要find运行代码中的内存泄漏和其他问题,您应该进入https://www.joyent.com/developers/node/debug 。 关于MDB有一整段可以帮你find问题,但需要一些时间和习惯。 所有这些都是太多的信息,不能链接到这里。

祝您好运!

我遇到过这个问题一两次了,答案一直是手动一个独立的监视服务,它定期向端点发送请求。 经过如此多的失败或超时请求后,服务将重新启动服务器。

但是,它没有缺点。 最明显的是你的应用程序在重启之前必须失败或者达到某个门槛。 这意味着,根据您的阈值,重启前可能会停产数分钟甚至数小时。 然而,另一种select是等待应用程序的用户开始抱怨,因为他们最有可能是你的客户,这可能更糟。

我想出了如何使用本地节点function来解决这个问题。 Migg的回答很好,让我朝着正确的方向发展,但是当事件循环完全被阻止时,它仍然没有显示如何自动重启。

诀窍是使用Node的本地child_process模块和fork方法从另一个节点实例启动服务器,并让该实例ping服务器以获取响应,并在其卡住时重新启动服务器。 这与Forever和PM2的工作方式类似。 很难相信没有一个简单的方法来实现这两个库中的任何一个,但这是你如何能够天真地做到这一点。

我已经大量地评论这个代码来指出一切都在做什么。 另外请注意,我正在使用ES2015的箭头function。 去了解他们,如果你不熟悉。

 var fork = require('child_process').fork; var server, heartbeat; function startServer () { console.log('Starting server'); server = fork('server'); //when the server goes down restart it server.on('close', (code) => { startServer(); }); //when server sends a heartbeat message save it server.on('message', (message) => { heartbeat = message ? message.heartbeat : null; }); //ask the server for a heartbeat server.send({request: 'heartbeat'}); //wait 5 seconds and check if the server responded setTimeout(checkHeartbeat, 5000); } function checkHeartbeat() { if(heartbeat) { console.log('Server is alive'); //clear the heart beat and send request for a new one heartbeat = null; server.send({request: 'heartbeat'}); //set another hearbeat check setTimeout(checkHeartbeat, 5000); } else { console.log('Server looks stuck...killing'); server.kill(); } } startServer(); 

请确保使用任何您想运行的Node应用程序更改server.js。

现在在您的服务器上添加以下内容来响应心跳请求。

 //listen and respond to heartbeat request from parent process.on('message', (message) => { if(message && message.request === 'heartbeat') { process.send({heartbeat: 'thump'}); } }); 

最后添加一个超时来testing它是否工作(不适用于生产)

 //block the even loop after 30 seconds setTimeout(() => { for(;;){} }, 30000);