返回顶部
首页 > 资讯 > 前端开发 > node.js >导致Node.js进程退出的情况是什么
  • 797
分享到

导致Node.js进程退出的情况是什么

2024-04-02 19:04:59 797人浏览 薄情痞子
摘要

这篇文章主要介绍“导致node.js进程退出的情况是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“导致node.js进程退出的情况是什么”文章能帮助大家解决问题

这篇文章主要介绍“导致node.js进程退出的情况是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“导致node.js进程退出的情况是什么”文章能帮助大家解决问题。

导致Node.js进程退出的情况是什么

在我们的服务发布后,难免会被运行环境(如容器、pm2 等)调度、升级服务导致重启、各种异常导致进程崩溃;一般情况下,运行环境都有对服务进程的健康监测,在进程异常时,会重新拉起进程,在升级时,也有滚动升级的策略。但运行环境的调度策略是把我们服务的进程当成黑盒来处理的,不会管服务进程内部的运行情况,因此需要我们的服务进程主动感知运行环境的调度动作,然后做一些退出的清理动作。

因此我们今天就是梳理各种可能导致 Node.js 进程退出的情况,以及我们可以通过监听这些进程退出事件做哪些事情。

原理

一个进程要退出,无非就是两种情况,一是进程自己主动退出,另外就是收到系统信号,要求进程退出。

系统信号通知退出

在 Node.js 官方文档 中列出了常见的系统信号,我们主要关注几个:

  • SIGHUP:不通过 ctrl+c 停止进程,而是直接关闭命令行终端,会触发该信号

  • SIGINT:按下 ctrl+c 停止进程时触发;pm2 重启或者停止子进程时,也会向子进程发送该信号

  • SIGTERM:一般用于通知进程优雅退出,如 k8s 删除 pod 时,就会向 pod 发送 SIGTERM 信号,pod 可以在超时时间内(默认 30s)做一些退出清理动作

  • SIGBREAK:在 window 系统上,按下 ctrl+break 会触发该信号

  • SIGKILL:强制退出进程,进程无法做任何清理动作,执行命令 kill -9 pid,进程会收到该信号。k8s 删除 pod 时,如果超过 30s,pod 还没退出,k8s 会向 pod 发送 SIGKILL 信号,立即退出 pod 进程;pm2 在重启或者停止进程时,如果超过 1.6s,进程还没退出,也会发送 SIGKILL 信号

在收到非强制退出信号时,Node.js 进程可以监听退出信号,做一些自定义的退出逻辑。比如我们写了一个 cli 工具,需要比较长的时间执行任务,如果用户在任务执行完成前想要通过 ctrl+c 退出进程时,可以提示用户再等等:

const readline = require('readline');

process.on('SIGINT', () => {
  // 我们通过 readline 来简单地实现命令行里面的交互
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  });
  rl.question('任务还没执行完,确定要退出吗?', answer => {
    if (answer === 'yes') {
      console.log('任务执行中断,退出进程');
      process.exit(0);
    } else {
      console.log('任务继续执行...');
    }
    rl.close();
  });
});



// 模拟一个需要执行 1 分钟的任务
const longTimeTask = () => {
  console.log('task start...');
  setTimeout(() => {
    console.log('task end');
  }, 1000 * 60);
};

longTimeTask();

实现效果如下,每次按下 ctrl + c 都会提示用户:

导致Node.js进程退出的情况是什么

进程主动退出

Node.js 进程主动退出,主要包含下面几种情况:

  • 代码执行过程中触发了未捕获的错误,可以通过 process.on('uncaughtException') 监听这种情况

  • 代码执行过程中触发了未处理的 promise rejection(Node.js v16 开始会导致进程退出),可以通过 process.on('unhandledRejection') 监听这种情况

  • EventEmitter 触发了未监听的 error 事件

  • 代码中主动调用 process.exit 函数退出进程,可以通过 process.on('exit') 监听

  • Node.js 的事件队列为空,可简单认为没有需要执行的代码了,可以通过 process.on('exit') 监听

我们知道 pm2 有守护进程的效果,在你的进程发生错误退出时,pm2 会重启你的进程,我们也在 Node.js 的 cluster 模式下,实现一个守护子进程的效果(实际上 pm2 也是类似的逻辑):

const cluster = require('cluster');
const Http = require('http');
const numCPUs = require('os').cpus().length;
const process = require('process');

// 主进程代码
if (cluster.isMaster) {
  console.log(`启动主进程: ${process.pid}`);
  // 根据 cpu 核数,创建工作进程
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
  // 监听工作进程退出事件
  cluster.on('exit', (worker, code, signal) => {
    console.log(`工作进程 ${worker.process.pid} 退出,错误码: ${code || signal}, 重启中...`);
    // 重启子进程
    cluster.fork();
  });
}

// 工作进程代码
if (cluster.isWorker) {
  // 监听未捕获错误事件
  process.on('uncaughtException', error => {
    console.log(`工作进程 ${process.pid} 发生错误`, error);
    process.emit('disconnect');
    process.exit(1);
  });
  // 创建 WEB server
  // 各个工作进程都会监听端口 8000(Node.js 内部会做处理,不会导致端口冲突)
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('hello world\n');
  }).listen(8000);
  console.log(`启动工作进程: ${process.pid}`);
}

应用实践

上面分析了 Node.js 进程退出的各种情况,现在我们来做一个监听进程退出的工具,在 Node.js 进程退出时,允许使用方执行自己的退出逻辑:

// exit-hook.js
// 保存需要执行的退出任务
const tasks = [];
// 添加退出任务
const addExitTask = fn => tasks.push(fn);
const handleExit = (code, error) => {  
  // ...handleExit 的实现见下面
};
// 监听各种退出事件
process.on('exit', code => handleExit(code));
// 按照 POSIX 的规范,我们用 128 + 信号编号 得到最终的退出码
// 信号编号参考下面的图片,大家可以在 linux 系统下执行 kill -l 查看所有的信号编号
process.on('SIGHUP', () => handleExit(128 + 1));
process.on('SIGINT', () => handleExit(128 + 2));
process.on('SIGTERM', () => handleExit(128 + 15));
// windows 下按下 ctrl+break 的退出信号
process.on('SIGBREAK', () => handleExit(128 + 21));
// 退出码 1 代表未捕获的错误导致进程退出
process.on('uncaughtException', error => handleExit(1, error));
process.on('unhandledRejection', error => handleExit(1, error));

信号编号:

导致Node.js进程退出的情况是什么

接下来我们要实现真正的进程退出函数 handleExit,因为用户传入的任务函数可能是同步的,也可能是异步的;我们可以借助 process.nextTick 来保证用户的同步代码都已经执行完成,可以简单理解 process.nextTick 会在每个事件循环阶段的同步代码执行完成后执行(理解 process.nextTick);针对异步任务,我们需要用户调用 callback 来告诉我们异步任务已经执行完成了:

// 标记是否正在退出,避免多次执行
let isExiting = false;
const handleExit = (code, error) => {
  if (isExiting) return;
  isExiting = true;

  // 标记已经执行了退出动作,避免多次调用
  let hasDoExit = fasle;
  const doExit = () => {
      if (hasDoExit) return;
      hasDoExit = true
      process.nextTick(() => process.exit(code))
  }

  // 记录有多少个异步任务
  let asyncTaskCount = 0;
  // 异步任务结束后,用户需要调用的回调
  let ayncTaskCallback = () => {
      process.nextTick(() => {
        asyncTaskCount--
        if (asyncTaskCount === 0) doExit() 
      })
  }
  // 执行所有的退出任务

  tasks.forEach(taskFn => {
      // 如果 taskFn 函数的参数个数大于 1,认为传递了 callback 参数,是一个异步任务
      if (taskFn.length > 1) {
         asyncTaskCount++
         taskFn(error, ayncTaskCallback)
      } else {
          taskFn(error)
      }
  });

  // 如果存在异步任务
  if (asyncTaskCount > 0) {
      // 超过 10s 后,强制退出
      setTimeout(() => {
          doExit();
      }, 10 * 1000)
  } else {
      doExit()
  }
};


进程优雅退出

通常我们的 web server 在重启、被运行容器调度(pm2 或者 Docker 等)、出现异常导致进程退出时,我们希望执行退出动作,如完成已经连接到服务的请求响应、清理数据库连接、打印错误日志、触发告警等,做完退出动作后,再退出进程,我们可以使用刚才的进程退出监听工具实现:

const http = require('http');

// 创建 web server
const server = http.createServer((req, res) => {
  res.writeHead(200);
  res.end('hello world\n');
}).listen(8000);

// 使用我们在上面开发的工具添加进程退出任务
addExitTask((error, callback) => {
   // 打印错误日志、触发告警、释放数据库连接等
   console.log('进程异常退出', error)
   // 停止接受新的请求
   server.close((error) => {
       if (error) {
         console.log('停止接受新请求错误', error)
       } else {
         console.log('已停止接受新的请求')
       }
   })
   // 比较简单的做法是,等待一定的时间(这里我们等待 5s),让存量请求执行完毕
   // 如果要完全保证所有请求都处理完毕,需要记录每一个连接,在所有连接都释放后,才执行退出动作
   // 可以参考开源库 https://GitHub.com/sebhildebrandt/http-graceful-shutdown
   setTimout(callback, 5 * 1000)
})

关于“导致Node.js进程退出的情况是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网node.js频道,小编每天都会为大家更新不同的知识点。

--结束END--

本文标题: 导致Node.js进程退出的情况是什么

本文链接: https://lsjlt.com/news/97244.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 导致Node.js进程退出的情况是什么
    这篇文章主要介绍“导致Node.js进程退出的情况是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“导致Node.js进程退出的情况是什么”文章能帮助大家解决问题...
    99+
    2024-04-02
  • Node.js进程退出的原理是什么
    今天小编给大家分享一下Node.js进程退出的原理是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。原理一个进程要退出,无...
    99+
    2023-06-29
  • Java中什么情况会导致内存泄漏
    这篇文章主要讲解了“Java中什么情况会导致内存泄漏”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中什么情况会导致内存泄漏”吧!概念内存泄露:指程序中动态分配内存给一些临时对象,但对...
    99+
    2023-06-16
  • mysql中什么情况会导致索引失效
    这篇文章主要为大家展示了“mysql中什么情况会导致索引失效”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“mysql中什么情况会导致索引失效”这篇文章吧。为了讲解以下索引内容,我们先建立一个临时...
    99+
    2023-06-25
  • 什么情况会导致香港服务器丢包
    导致香港服务器丢包的情况有:1、提供香港服务器的机房出现网络故障问题导致;2、香港服务器本地网络出现故障,导致服务器出现丢包情况;3、中转网络出现故障,从而使香港服务器丢包率增加。具体内容如下:机房网络故障用户在选择机房时,通常会比较注重机...
    99+
    2024-04-02
  • 什么情况会导致美国服务器IP被封
    会导致美国服务器IP被封的情况有:1、使用美国服务器时违背法美国律政策法规导致;2、美国服务器被同行或者黑客攻击导致;3、美国服务器遭受大规模流量攻击导致。具体内容如下:违背法美国律政策法规这一类美国服务器IP被封,服务商也很无可奈何,服务...
    99+
    2024-04-02
  • 什么情况下容易导致服务器IP被封
    容易导致服务器IP被封的情况有:1、当前服务器IP存在不良记录或者违反了法律规定导致;2、服务器遭受网络攻击,攻击规模超过了机房预设的阈值,从而导致机房管理员将该IP暂时封停。具体内容如下:服务器IP段有不良记录大多数国际数据中心外国服务器...
    99+
    2024-04-02
  • Node.js进程退出的深入理解
    目录背景介绍原理系统信号通知退出进程主动退出应用实践进程优雅退出总结背景介绍 在我们的服务发布后,难免会被运行环境(如容器、pm2 等)调度、升级服务导致重启、各种异常导致进程崩溃;...
    99+
    2024-04-02
  • NodeJS进程是怎么退出的
    本篇内容介绍了“NodeJS进程是怎么退出的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!目录前言主动退出Exceptions, Rejec...
    99+
    2023-06-20
  • java内存溢出的四种情况是什么
    这篇文章主要介绍了java内存溢出的四种情况是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇java内存溢出的四种情况是什么文章都会有所收获,下面我们一起来看看吧。1、堆溢出,堆是存放实例对象的,但是这样堆...
    99+
    2023-06-30
  • MySQL中进行sql优化的情况是什么
    这篇“MySQL中进行sql优化的情况是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“...
    99+
    2023-05-25
    mysql sql
  • 为什么在这种情况下主协程会被阻塞从而导致死锁?
    在PHP中,主协程被阻塞导致死锁的情况是比较常见的。主协程在执行过程中,如果遇到阻塞的操作,比如网络请求、IO操作或者等待其他协程结果等,如果没有合适的处理方式,就有可能导致死锁的发生...
    99+
    2024-02-09
  • 在duplicate中出现监听BLOCKED的情况导致监听自动关闭该怎么办
    这篇文章给大家介绍在duplicate中出现监听BLOCKED的情况导致监听自动关闭该怎么办,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。 注意设置gri...
    99+
    2024-04-02
  • 防止Node.js中错误导致进程阻塞的办法
    前言 在Node.js中,当某个回调函数发生了错误,整个进程都会崩溃,影响后面的代码执行。 Node.js这样处理,是因为在发生未被捕获的错误时,进程的状态就不确定。之后也就无法正常工作了。如果错误始终不处...
    99+
    2022-06-04
    进程 错误 办法
  • Node.js中防止错误导致的进程阻塞的方法
    在Node.js中,当某个回调函数发生了错误,整个进程都会崩溃,影响后面的代码执行。 Node.js这样处理,是因为在发生未被捕获的错误时,进程的状态就不确定。之后也就无法正常工作了。如果错误始终不处理的话...
    99+
    2022-06-04
    进程 错误 方法
  • 如何正确处理PHP中16进制转换导致的中文乱码情况
    标题:解决PHP中16进制转换导致的中文乱码问题 在使用PHP进行16进制转换的过程中,有时候会遇到中文乱码的情况。这种问题通常是因为在进行16进制转换时,未正确处理中文编码导致的。本...
    99+
    2024-03-04
    php处理 进制 中文乱码
  • react的setstate同步情况是什么
    本文小编为大家详细介绍“react的setstate同步情况是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“react的setstate同步情况是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。react...
    99+
    2023-07-04
  • Node.js中的进程和线程是什么
    这篇文章主要介绍“Node.js中的进程和线程是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Node.js中的进程和线程是什么”文章能帮助大家解决问题。一、进...
    99+
    2024-04-02
  • Redo丢失的4种情况是什么
    这篇文章将为大家详细讲解有关Redo丢失的4种情况是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一.说明:1.以下所说的当前日志指日志状态为CURRENT,ACTI...
    99+
    2024-04-02
  • ubuntu退出程序的方法是什么
    这篇文章主要讲解了“ubuntu退出程序的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“ubuntu退出程序的方法是什么”吧!打开命令行窗口,通过以下命令杀掉对应的进程来退出。方法...
    99+
    2023-07-04
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作