【问题标题】:Auto restart or Proper Handling socket.io server on exception in linux在 Linux 中出现异常时自动重启或正确处理 socket.io 服务器
【发布时间】:2025-11-21 16:30:04
【问题描述】:

我的 socket.io 服务器在后台运行。但是,有几种情况它会死亡。我该怎么做才能让我的 socket.io 服务器在它死亡或终止时自动重启。

这就是我启动节点服务器的方式

> node server &

但是服务器抛出异常并死掉了。

events.js:141
      throw er; // Unhandled 'error' event
      ^

Error: Redis connection to pub-redis-us-east1-garantiabata.com:12087 failed - connect ETIMEDOUT 54.179.28.165:12087
    at RedisClient.on_error (/home/org-chatserver/node_modules/redis/index.js:185:24)
    at Socket.<anonymous> (/home/org-chatserver/node_modules/redis/index.js:95:14)
    at emitOne (events.js:77:13)
    at Socket.emit (events.js:169:7)
    at emitErrorNT (net.js:1253:8)
    at doNTCallback2 (node.js:450:9)
    at process._tickCallback (node.js:364:17)
^C

这是我的环境

Linux version 2.6.32-042stab090.5 (root@kbuild-rh6-x64) (gcc version 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC) ) #1 SMP Sat Jun 21 00:15:09 MSK 2014

我相信我的团队正在使用这个:

https://github.com/jbavari/ionic-socket.io-redis-chat

【问题讨论】:

标签: linux node.js socket.io restart


【解决方案1】:

您可以使用主管 - http://supervisord.org

Supervisor 是一个客户端/服务器系统,允许其用户监视和控制类 UNIX 操作系统上的许多进程。

安装后,为您的应用创建一个主管配置文件。

比如/etc/supervisor/conf.d/myserver.conf下-

[program:my-server]
    command=node /path/to/server.js
    numprocs=1
    autostart=true  
    autorestart=true
    startretries=99999
    environment=NODE_ENV=production  
    stderr_logfile=/var/log/my-server.err.log  
    stdout_logfile=/var/log/my-server.log  
    user=myuser  

编辑主管主配置文件 - /etc/supervisor/supervisord.conf

[unix_http_server]
file=/var/run/supervisor.sock    ; (the path to the socket file)
chmod=0700                       ; socket file mode (default 0700)

[supervisord]
logfile=/var/log/supervisor/supervisord.log ; (main log file;default    ] $CWD/supervisord.log)
pidfile=/var/run/supervisord.pid            ; (supervisord pidfile;default supervisord.pid)
childlogdir=/var/log/supervisor             ; ('AUTO' child log dir, default $TEMP)

; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
 [rpcinterface:supervisor]
supervisor.rpcinterface_factory =  supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///var/run//supervisor.sock ; use a unix:// URL  for a unix socket

; The [include] section can just contain the "files" setting.  This
; setting can list multiple files (separated by whitespace or
; newlines).  It can also contain wildcards.  The filenames are
; interpreted as relative to this file.  Included files *cannot*
; include files themselves.

[include]
files = /etc/supervisor/conf.d/*.conf

用法: /etc/init.d/supervisord {start|stop|restart|force-reload|status|force-stop}

更多信息/文档 - 请阅读http://supervisord.org/

【讨论】:

【解决方案2】:

您可以使用pm2 来监控日志、自动重启...等。例如:

sudo npm install -g pm2
pm2 start app.js --watch

更多关于watch & restart

【讨论】:

  • 我可以在后台运行它吗,因为我不想为此使用专门的控制台。我想要一些东西来确保这个节点服务器持续运行,即使它可能会关闭
  • 是的,pm2 start在后台启动进程,你可以使用pm2 listpm2 monitpm2 logs查看进程。如果你想远程监控它,你可能需要使用他们的dashboard service
  • 到目前为止我喜欢这个。我认为它有效,到目前为止测试了 12 个小时还活着。我觉得这就是。但有一件事是我做了你所有的命令,比如 pm2 list、pm2 monit……我似乎无法在表列表中找到我的进程?
  • 那么,你看到了什么?
  • 好的,现在我明白了,可能是控制台问题。 imgur.com/Kpo9LyL。但是没有重启。如果它死了,它会自动重新启动并显示在表格计数器中吗?
【解决方案3】:

要让服务器重新连接,您可能需要使用一些程序(如永远)来检查服务器的状态并在服务器死机时重新启动它。然而,这并不能解决客户的问题。当服务器死机时,客户端还需要重新初始化与服务器的连接。让我向您展示如何让您的客户端连接回服务器的最小示例。

主要思想是您将从客户端套接字侦听“关闭”事件,并在需要时重新启动连接。让我们使用 OOP 来更好地说明这一点。

function Connector(host, port)
{
  // Connection parameters
  this.host = host;
  this.port = port;

  this.socket = null;

  // Attempt to establish a connection with the server.
  this._connect();
}

Connector.prototype._connect = function()
{
  this.socket = net.connect(this.port, this.host);

  this.socket.on('connect', this._onConnect);
  this.socket.on('error', this._onError);
  this.socket.on('close', this._onClose);
  this.socket.on('data', this._onData);
}


Connector.prototype._onConnect = function()
{
  console.log('Incoming connection');
}

Connector.prototype._onError = function(err)
{
  console.error('Connection error: ' + err);
}

Connector.prototype._onClose = function(had_error)
{
  console.log('Reconnecting to server.');
  self._scheduleReconnection();
}


Connector.prototype._scheduleReconnection = function()
{
  self.socket.removeAllListeners();
  self.socket = null;

  // Try to connect to the server again after 2 seconds.
  setTimeout(self._connect.bind(self), 2000);
}

Connector.prototype._onData = function(data)
{
  console.log('Incoming data.')
}

使用 Connector 对象,您现在可以开始连接:

connection = new Connector(127.0.0.1, 8080)

而且您知道此连接会不断尝试与服务器保持连接。

【讨论】: