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

Posted

技术标签:

【中文标题】优雅地关闭节点实例,不中途停止任何事情【英文标题】:Close node instance gracefully, without stopping anything half-way 【发布时间】:2016-06-14 15:03:00 【问题描述】:

请注意,这个问题不是关于在进程崩溃时保持进程运行,或者在完成新部署时重新启动它。这个问题是关于如何在不终止挂起操作的情况下重新启动。

我有一个 非常 繁忙的节点应用程序,每秒接收 很多 次点击。我的应用程序运行的函数需要很长时间才能返回(请参阅:通过 API 上传的 youtube)。

我遇到的问题是,当我部署新版本的应用程序时,进程会重新启动——结果,任何“待处理”的东西基本上也会被杀死。这意味着 10 个 youtube 上传可能会被终止,需要重新启动。 现在:

清空事件队列基本上是不可能的,因为我可能会等待很长时间 按原样杀死进程被证明是有问题的

理想的解决方案是确保满足任何现有正在进行的请求,但使用新部署的代码处理任何新请求。

一个可能的想法:

有一个主进程接受连接。这个过程永远不会改变 当有更新时,向该进程发送信号,该进程将重新加载“跑步者” 此时,任何新请求都将通过更新后的运行器

您必须真正重新启动进程本身的唯一时间是 你想更新主连接。

这种方法是“完成”的吗?有没有一个模块可以做到这一点?还是完全矫枉过正?

更新

有趣的答案:https://***.com/a/10711410/829771 但是,等待事件循环为空 重新启动进程是不现实的。

但是这里还有另一个级别的复杂性:如果服务器有计时器,例如它每 5 分钟运行一次任务,按照我在上面写的内容,您最终会运行 两个。因此,必须用信号通知“已过时”的进程并且必须监听它并在收到信号时停止任何“后台”操作。请记住,这不是理论——我确实在我的应用程序中有setInterval()s

【问题讨论】:

可能的解决方案:您可以尝试发送/捕获信号(如 SIGTERM)。收到信号后,服务器停止接受客户端连接,但继续上传并在所有上传完成后终止。在这种情况下,使用新代码启动一个新的 nodejs 进程,并让该进程接受连接。这假设两个进程可以同时使用您的数据存储,大多数数据库都支持。 这实际上是一个非常有趣的解决方案。但是......我怎么能成为唯一一个甚至这个问题的人?我真的不明白 【参考方案1】:

就您而言,正常关闭所需的只是等待下载。操作系统将自动处理其他任何事情,“手动”清理所有内部节点内容毫无意义。因为它可能比应用程序本身复杂得多;)

只需在 2 个不同的端口上启动至少 2 个“工作”进程,在主应用程序中实现一些简单的面板,您可以在其中启动/暂停它们并将所有“任务”发送到其中一个。当您部署时,只需暂停一个,等到上传完成,然后您就可以部署,然后移动到第二个。额外的好处是你有一些冗余。如果您实现一些简单的“ping”命令,您可以在其中一个进程终止时自动路由连接。

您可以实现一些功能,该功能将使用正在运行的计时器返回挂起的上传列表,然后“主”应用程序可以自动杀死跑步者。实际上,如果计时器触发的操作不是原子的,您应该在开始时将其添加到列表并在最后删除,即使计时器仍在滴答作响,这也不是问题。在它触发前 20 秒将它放在列表中,您不会遇到在获取“进程”列表、终止进程和事件触发之间发生的竞争条件的问题。

【讨论】:

以上是关于优雅地关闭节点实例,不中途停止任何事情的主要内容,如果未能解决你的问题,请参考以下文章

写出更优雅和稳健的 TS 代码的几个 tips

如何优雅地关闭猫鼬的连接池?

使用 docker-compose up 运行时如何优雅地停止 Dockerized Python ROS2 节点?

如果优雅地关闭ExecutorService提供的java线程池

WebSocketSession.send 不做任何事情

有没有办法通过Visual Studio菜单/工具栏优雅地关闭正在运行的应用程序?