应用实践
上面分析了 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));信号编号:

文章插图
接下来我们要实现真正的进程退出函数 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() }};
至此 , 我们的进程退出监听工具就完成了 , 完整的实现可以查看这个开源库 async-exit-hook进程优雅退出
https://github.com/darukjs/daruk-exit-hook
通常我们的 web server 在重启、被运行容器调度(pm2 或者 docker 等)、出现异常导致进程退出时 , 我们希望执行退出动作 , 如完成已经连接到服务的请求响应、清理数据库连接、打印错误日志、触发告警等 , 做完退出动作后 , 再退出进程 , 我们可以使用刚才的进程退出监听工具实现:
const http = require('http');// 创建 web serverconst 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 进程退出的各种情况心里有数了 。 在服务上线后 , 虽然 k8s、pm2 等工具能够在进程异常退出时 , 不停地拉起进程 , 保证服务的可用性 , 但我们也应该在代码中主动感知进程的异常或者被调度的情况 , 从而能够更早发现问题 。
更多node相关知识 , 请访问:nodejs 教程!
以上就是聊聊各种可能导致 Node.js 进程退出的情况的详细内容 , 更多请关注电脑自学网其它相关文章!
【聊聊各种可能导致 Node.js 进程退出的情况】
推荐阅读
- 兼容方案探究 聊聊使用CSS怎么实现毛玻璃特效
- 宠物会将病毒传染给人吗 宠物可能会传染给人的疾病有哪些
- 出现这3个现象代表宝宝可能要长高了
- 孩子夜惊做噩梦?可能是这几种情况引起的,家长一定要注意
- 新生儿低血糖可能造成脑损伤?医生:早发现,及时止损很重要
- 要不要给孩子割包皮?这3种情况真得赶紧去,这2种情况可能白挨一刀
- 支付宝养猫彩蛋抽各种红包
- 各种微信撩妹调情截图
- 营养早餐-双瓜土豆糕的做法
- 京东会员免费领各种健身会员