正常closures在Forever下运行的NodeJS上的UNIX套接字服务器
我有一个NodeJS应用程序,它设置了一个UNIX套接字来公开一些进程间通信通道(某种监视的东西)。 UNIX套接字文件放在os.tmpdir()
文件夹(即/tmp/app-monitor.sock
)中。
var net = require('net'); var server = net.createServer(...); server.listen('/tmp/app-monitor.sock', ...);
我使用信号处理(SIGINT,SITERM等…)正常closures我的服务器并删除套接字文件。
function shutdown() { server.close(); // socket file is automatically removed here process.exit(); } process.on('SIGINT', shutdown); // and so on
我的应用程序正在forever start ...
运行forever start ...
监视它的生命周期。
我有一个与forever restartall
命令的问题。 当永远restartall
它使用SIGKILL
来终止所有subprocess。 SIGKILL
不能被进程处理,所以我的应用程序没有任何关机程序而死亡。
问题是使用SIGKILL
时不会删除的套接字文件。 在subprocess重新启动后,新的服务器不能启动,因为“一个listen
调用将导致EADDRINUSE
错误。
我不能在应用程序启动过程中删除现有的套接字文件,因为我不知道它是否是一个真正的工作套接字或以前的不干净closures的痕迹。
所以,问题是…有什么更好的方式来处理这种情况(SIGKILL和UNIX-socket服务器)?
正如其他人所提到的那样,对于SIGKILL来说,不能做任何事情,一般来说为什么forever
(和其他人)不应该在极端情况下使用SIGKILL。 所以你可以做的最好的是在另一个过程中清理。
我build议你开始清理。 当你得到EADDRINUSE
,尝试连接到套接字。 如果套接字连接成功,另一个服务器正在运行,所以这个实例应该退出。 如果连接失败,则可以安全地断开套接字文件并创build一个新文件。
var fs = require('fs'); var net = require('net'); var server = net.createServer(function(c) { //'connection' listener console.log('server connected'); c.on('end', function() { console.log('server disconnected'); }); c.write('hello\r\n'); c.pipe(c); }); server.on('error', function (e) { if (e.code == 'EADDRINUSE') { var clientSocket = new net.Socket(); clientSocket.on('error', function(e) { // handle error trying to talk to server if (e.code == 'ECONNREFUSED') { // No other server listening fs.unlinkSync('/tmp/app-monitor.sock'); server.listen('/tmp/app-monitor.sock', function() { //'listening' listener console.log('server recovered'); }); } }); clientSocket.connect({path: '/tmp/app-monitor.sock'}, function() { console.log('Server running, giving up...'); process.exit(); }); } }); server.listen('/tmp/app-monitor.sock', function() { //'listening' listener console.log('server bound'); });
你应该可以使用SIGTERM来做你想做的事: process.on('SIGTERM', shutdown)
server.on('error', function (e) { if (e.code == 'EADDRINUSE') { console.log('Address in use, retrying...'); setTimeout(function () { server.close(); server.listen(PORT, HOST); }, 1000); } });
http://nodejs.org/api/net.html#net_server_listen_port_host_backlog_callback
UPD
你不能处理SIGKILL,那么你必须清理套接字手册
这个例子永远正常工作
var fs = require('fs'); var net = require('net'); var server = net.createServer(function(c) {}); server.listen('./app-monitor.sock', function() { console.log('server bound'); }); server.on('error', function (e) { if (e.code == 'EADDRINUSE') { console.log('Address in use, retrying...'); setTimeout(function () { fs.unlink('./app-monitor.sock'); }, 1000); } });
既然你不能处理SIGKILL
,你想永远使用(使用SIGKILL
),你将不得不使用一个解决方法。
例如,首先发送一个信号来closures你的服务器,然后进行永久重启:
kill -s SIGUSR1 $pid # $pid contains the pid of your node process, or use # killall -SIGUSR1 node sleep 2 forever restart test.js
在你的js句柄中SIGUSR1:
process.on('SIGUSR1', gracefullyShutdownMyServer);
你必须select
- 将SIGKILL更改为永久监视器中的另一个信号以在应用程序中处理
- 在这种情况下照顾你的应用程序,使用fs.unlink
- 停止使用永远