child_process.fork() 方法是专门用于衍生新的 Node.js 进程。返回 ChildProcess 类 ,ChildProcess 类的实例都是 EventEmitter,表示衍生的子进程。

const fork = require('child_process').fork;
const childProcess  = fork('./worker.js')

当子进程使用 process.send() 发送消息时会触发 'message' 事件。

process.on('message', (message, sendHandle) => {  // TODO
})

当子进程结束后时会触发 'exit' 事件。如果进程退出,则 code 是进程的最终退出码,否则为 null。如果进程是因为收到的信号而终止,则 signal 是信号的字符串名称,否则为 null。这两个值至少有一个是非空的。

childProcess.on('exit', (code, signal) => { // TODO
})

自动重启

有了父子进程之间的相关事件之后,就可以在这些关系之间创建出需要的机制了。至少我们能够通过监听子进程的 exit 事件来获知其退出的信息,接着前文的多进程架构,我们在主进程上要加入一些子进程管理的机制,比如重新启动一个工作进程来继续服务。

// worker.js 子进程文件
const http = require('http')
const process = require('process')   const server = http.createServer(  (req, res) => { res.writeHead(200, {    'Content-Type': 'text/plain',   })  res.end('handle by child')    }
)   process.on('message', (m, tcp) => {   if (m === 'server') {  tcp.on('connection', socket => {  server.emit('connection', socket) })  }
})
// master.js 主进程文件
const fork = require('child_process').fork;
const cpus = require('os').cpus();
const net = require('net')
const server = net.createServer()  server.listen(8080) const workers = {}
const createWorker = function () { const worker  = fork('./worker.js')  worker.on('exit', () => { console.log(`进程退出:${worker.pid}`)  delete workers[worker.pid]  createWorker()  })  worker.send('server', server) workers[worker.pid] = worker   console.log(`进程创建:${worker.pid}`)
}   for (let i = 0; i < cpus.length; i++) {   createWorker()
}

测试一下上面的代码,在 window 电脑中尝试使用 taskkill /pid 524 /f 杀死进程号为 524 的进程,发现会自动重启一个 6976 的进程。总体进程数量并没有发生改变。

在这个场景中我们主动杀死了一个进程,在实际业务中,可能有隐藏的bug导致工作进程退出,那么我们需要仔细地处理这种异常。

NodeJS 对于未捕获异常的默认处理是:触发 uncaughtException 事件,如果 uncaughtException 没有被监听,那么打印异常的堆栈信息,触发进程的 exit 事件。

const http = require('http')
const process = require('process')   const server = http.createServer(  (req, res) => { res.writeHead(200, {    'Content-Type': 'text/plain',   })  res.end('handle by child')    }
)   let worker;
process.on('message', (m, tcp) => {   if (m === 'server') {  worker = tcp;  tcp.on('connection', socket => {  server.emit('connection', socket) })  }
})  // 监听未捕获的异常
process.on('uncaughtException', () => {   // 停止接收新的连接 worker.close(() => {    // 已有连接断开后退出进程  process.exit(1) })
})

上述代码的处理流程是,一旦有未捕获的异常出现,工作进程就会立即停止接收新的连接;当所有连接断开后,退出进程。主进程在侦听到工作进程的 exit 后,将会立即启动新的进程服务,以此保证整个集群中总是有进程在为用户服务的。

自杀信号

当然上述代码存在的问题是要等到已有的所有连接断开后进程才退出,在极端的情况下,所有工作进程都停止接收新的连接,全处在等待退出的状态。但在等到进程完全退出才重启的过程中,所有新来的请求可能存在没有工作进程为新用户服务的情景,这会丢掉大部分请求。

为此需要改进这个过程,不能等到工作进程退出后才重启新的工作进程。当然也不能暴力退出进程,因为这样会导致已连接的用户直接断开。于是我们在退出的流程中增加一个自杀(suicide)信号。工作进程在得知要退出时,向主进程发送一个自杀信号,然后才停止接收新的连接,当所有连接断开后才退出。主进程在接收到自杀信号后,立即创建新的工作进程服务。代码改动如下所示:

const fork = require('child_process').fork;
const cpus = require('os').cpus();
const net = require('net')
const server = net.createServer()  server.listen(8080) const workers = {}
const createWorker = function () { const worker  = fork('./worker.js')  worker.on('exit', () => { console.log(`进程退出:${worker.pid}`)  delete workers[worker.pid]  createWorker()  })  // 创建一个新的进程 worker.on('message', message => { if (message.act === 'suicide') {   createWorker()  }   })  worker.send('server', server) workers[worker.pid] = worker   console.log(`进程创建:${worker.pid}`)
}   for (let i = 0; i < cpus.length; i++) {   createWorker()
}
const http = require('http')
const process = require('process')   const server = http.createServer(  (req, res) => { res.writeHead(200, {    'Content-Type': 'text/plain',   })  res.end('handle by child')    }
)   let worker;
process.on('message', (m, tcp) => {   if (m === 'server') {  worker = tcp;  tcp.on('connection', socket => {  server.emit('connection', socket) })  }
})  // 监听未捕获的异常
process.on('uncaughtException', () => {   // 通知主进程去创建一个新的进程   process.send({act: 'suicide'})    // 停止接收新的连接 worker.close(() => {    // 所有已有连接断开后退出进程    process.exit(1) })
})

至此我们完成了进程的平滑重启,一旦有异常出现,主进程会创建新的工作进程来为用户服务,旧的进程一旦处理完已有连接就自动断开。整个过程使得我们的应用的稳定性和健壮性大大提高。

Node如何自动重启进程相关推荐

  1. 利用进程管理利器supervise监控并自动重启进程

    一.什么是supervise supervise是Daemontools里的一个核心工具,Daemontools是一个包含了很多管理Unix服务的工具的软件包.而其中最核心的工具就是supervise ...

  2. Linux 自动重启进程

    Js代码   #!/bin/sh echo "Current DIR is " $PWD # ignore signal hup int quit tstp trap " ...

  3. PM2自动重启node服务

    PM2是node进程管理工具,可以利用它来简化很多node应用管理的繁琐任务,如性能监控.自动重启.负载均衡等,而且使用非常简单. 全局安装,简直不能更简单. npm install -g pm2 用 ...

  4. Memcached进程挂掉自动重启脚本

    由于一台WEB服务器的Memcached死掉而导致在访问网站的某些页面时候打不开,下面脚本会自动检测Memcached的进程,如果挂掉则自动重启Memcached服务. cat /root/sh/me ...

  5. 在linux下python爬虫进程发生异常时自动重启直至正常结束的方法

    在linux下python爬虫进程发生异常时自动重启直至正常结束的方法 参考文章: (1)在linux下python爬虫进程发生异常时自动重启直至正常结束的方法 (2)https://www.cnbl ...

  6. windows进程管理器_软件进程自动重启一遍又一遍……你需要这款自动杀进程的小公举ProcessKO...

    [PConline 应用]用Windows系统最烦的一件事,就是各种乱七八糟的进程.我们知道软件要运行,就会在后台唤起进程,但这些进程有时候并不那么听话,某些软件会不断唤起进程,对此Windows自带 ...

  7. linux里进程监控和自动重启,Linux - linux进程监控和自动重启的简单实现

    linux进程监控和自动重启的简单实现 目的:linux 下服务器程序会由于各类缘由dump掉,就会影响用户使用,这里提供一个简单的进程监控和重启功能.linux 实现原理:由定时任务crontab调 ...

  8. Node.js笔记 - 修改文件后自动重启node服务

    每次修改代码后都要手动重启node服务,虽然不是复杂的事,但是每次都要这么搞一次颇为麻烦. 所以nodemon登场了! nodemon会监测你已运行程序中的文件和目录,一旦被修改,它会自动重启node ...

  9. NSURLSessionDataTask与NSOperationQueue实现多文件断点下载(任意时刻终止进程,重启应用,自动重启下载)...

    效果展示 gif有点大,直接连接:7qnbrb.com1.z0.glb.clouddn.com/download.gi- 知识要点 NSOperationQueue线程队列的管理 NSURLSessi ...

最新文章

  1. 小程序云开发,判断数据库表的两个字段匹配 云开发数据库匹配之 and 和 or 的配合使用
  2. python抓取数据库数据封装成json_用Python将mysql数据导出成json的方法
  3. Linux 文件权限rwx
  4. 国庆假 的CSS +JS 学习笔记
  5. python(9)-变量、input函数
  6. 韩企全球首造72层3D NAND芯片 下半年或量产
  7. 资源地址整合与备份,即时更新
  8. php的limit分页,用php数组的array_slice分页和用limit查询分页哪个效率更高?
  9. 利用openssl创建私有CA的步骤和过程
  10. digester java_Java-Digester:提取节点名称
  11. 苹果亮度自动调节怎么关闭_找不到“自动亮度调节”?这两个技巧帮你快速更改设置...
  12. 智慧工厂之化工厂人员定位中的智能访客管理系统-新导智能
  13. 因设计或者设施缺陷导致道路交通事故赔偿问题的法律依据
  14. 如何处理接口幂等性问题(重复提交)
  15. 如何防止form表单重复提交
  16. 咸鱼的 GitHub 情报 | 20191229 期
  17. Python深度学习(循环神经网络)--学习笔记(十三)
  18. PLC张力控制(开环闭环算法分析)
  19. 异或(XOR)运算加密/解密算法
  20. C#ListView控件的相关用法

热门文章

  1. COSCon'20 Apache Roadshow- China 精彩收官 | 数据篇
  2. 17个品牌,113款5G手机,你选哪款?
  3. 开源要安全!Linux 基金会、GitHub、GitLab、Google 联合起来了!
  4. 为什么黑客无法攻击公开的区块链?
  5. 为什么说这 5 大趋势,开发者不容错过?
  6. 为什么说比特币隐私是一门艺术?
  7. TPC-C 中跑赢 Oracle 的 OceanBase,双 11 处理峰值达 6100 万次/秒!
  8. 国内 UOS 统一操作系统曝光;联想宣布要 All in 5G​;Android Studio 新版发布 | 极客头条...
  9. 刷爆了!程序员都在点赞的Python学习图谱安利给你!
  10. 冠军奖 3 万元!CSDN×易观算法大赛火热进行中