停止节点实例的最安全方法

Posted

技术标签:

【中文标题】停止节点实例的最安全方法【英文标题】:Safest way to stop a node instance 【发布时间】:2017-09-03 19:41:44 【问题描述】:

我有一个非常繁忙的网络应用程序:

nginx 作为“前端”,充当反向代理 在非特权端口上运行的节点服务器,由 Nginx 查询

应用程序使用 websockets(为每个客户端打开一个套接字)。 Nginx 的配置方式非常典型:

server 
        listen X.Y.255.3:443 ssl http2;
        server_name example.com;

        client_max_body_size 0;


        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
        ssl_dhparam /etc/nginx/ssl/dhparam.pem;
        ssl_stapling on;
        ssl_stapling_verify on;

        location / 

          proxy_pass http://localhost:8082;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection 'upgrade';
          proxy_set_header Host $host;
          proxy_cache_bypass $http_upgrade;
        
    

我的想法是,当我想停止服务器时,我会执行以下操作: 我发送一个 SIGTERM,以便: * 我让服务器停止接受连接 * 我切断了现有的套接字(包括 websockets) * 我清除了间隔和超时

此时,服务器应该自行退出,因为事件循环应该是空的(一旦完成最后的数据库写入等)。

我是这样编码的:

        ...
        var server = http.createServer(app);

        process.on('SIGTERM', function()
          server.close();
          console.log("TERMINATING THIS INSTANCE!");

          // This will make sure hotplate modules will get dir
          // of intervals and lose ends
          process.emit( 'hotplateShutdown');
          var handles = Array.prototype.slice.call(process._getActiveHandles())
          console.log( "Event loop has: ", handles.length );

          handles.forEach( (o ) =>   console.log( "Dealing with:", o.readyState ); o.unref && o.unref();  );

        );

        server.listen(app.get('port'), app.get('ipAddress'), function () 
            console.log("Express server listening on port " + app.get('port'));
          );

如果 10 秒后该过程仍在进行,我会发送 SIGKILL(此时出现问题)。但是,请注意,我几乎可以立即重新运行服务器,因为在 SIGTERM 之后服务器停止侦听绑定端口。这意味着重新启动时的停机时间最短。

websockets 应该被杀死。

问题:

1) 这是一种理智的方法吗?

2) 如果DB调用中途,会完成吗?

3) 由于我使用的是 express,所以我真的不能轻易use this technique -- 可以吗?

我注意到事件循环包含 5 个套接字。这些套接字存在即使 Nginx 没有运行。我不确定为什么是 5,我不确定这是一个理智的方法......

意见/想法?

【问题讨论】:

【参考方案1】:

SIGTERM 和 SIGKILL 是为这些东西而设计的守护线程,即终止或终止进程。

这是一种理智的方法吗?

如果没有任何问题,那么是的,这是正常的。

如果DB调用是半途而废,会完成吗?

是的,我可以向您保证,如果某个 db 调用正在进行,那么它将在终止进程之前完成。

由于我使用的是 express,所以我不能很容易地使用这种技术——可以吗?

我不认为你可以,我仍然认为终止进程是一个更好的解决方案。

不久前,我在 AWS Elastic Beanstalk 上做了类似的事情,我必须杀死工人并重新启动它。好吧,我有 AWS SDK 的方法,比如

重启AppServer 杀死环境

但我对此进行了研究,发现this。也许这会对你有所帮助。

【讨论】:

以上是关于停止节点实例的最安全方法的主要内容,如果未能解决你的问题,请参考以下文章

优雅地关闭节点实例,不中途停止任何事情

数据结构与算法之深入解析“访问所有节点的最短路径”的求解思路与算法示例

Neo4j具有给定属性的任何节点的ShortestPath

索引(用于搜索索引)70,000 个节点的最简单方法是啥?

LeetCode847 访问所有结点的最短路径

Leetcode 802 找到最终的安全状态(拓扑)