nodejs如何开启进程,进程如何通讯?

116 阅读1分钟

进程process vs 线程 thread

  • 进程,OS进行资源分配和调度的最小单位,有独立的内存空间
  • 线程,OS进行运算调度的最小单位,共享进程的内存空间
  • JS是单线程的,但是可以开启多进程执行,如WebWorker 【单线程(在进程中只有一个线程进行计算)】

image.png

为何需要多进程

  • 多核CPU,更适合处理更多进程
  • 内存较大,多个进程才能更好的利用资源(单进程有内存上限)
  • 总之,“压榨”机器资源,更快,更节省

代码演示:nodejs多进程

第一种方式fork实现:

主进程代码:

const http = require('http')
const fork = require('child_process').fork

const server = http.createServer((req, res) => {
  if (req.url === '/get-sum') {
    console.info('主进程 id', process.pid)
    // 开启子进程
    const computeProcess = fork('./compute.js')
    computeProcess.send('开始计算')
    computeProcess.on('message', (data) => {
      console.info('主进程接收到的信息:', data)
      res.end('sum is ' + data)
    })
    // 子进程出错则杀掉
    computeProcess.on('close', () => {
      console.info('子进程因报错而退出')
      computeProcess.kill()
      res.end('error')
    })
  }
})
server.listen(3000, () => {
  console.info('localhost:3000')
})

子进程代码:

// 子进程 计算

function getSum() {
  let sum = 0
  for (let i = 0; i < 10000; i++) {
    sum += i
  }
  return sum
}

process.on('message', (data) => {
  console.log('子进程 id', process.pid)
  console.log('子进程接收到的信息:', data)

  const sum = getSum()

  // 发送消息给主进程
  process.send(sum)
})

结果:

image.png

第二种方式cluster实现

const http = require('http')
const cpuCoreLength = require('os').cpus().length; // 获取cpu的核数
const cluster = require('cluster')

if (cluster.isMaster) { // 如果是主进程
  for (let i = 0; i < cpuCoreLength; i++) {
    cluster.fork() // 开启cpu核数同样数量的子进程
  }

  cluster.on('exit', worker => {
    console.log('子进程退出');
    cluster.fork()// 进程守护 (一个进程死了 再开一个)
  })
} else {
  // 多个子进程会共享一个TCP连接 提供一个网络服务
  const server = http.createServer((req,res) => {
    res.writeHead(200)
    res.end('done')
  })
  server.listen(3000)
}

// 实际工作中会用 PM2 实现

答案

  • 开启子进程 child_process.fork 和 cluster.fork
  • 使用send和on传递消息

划重点

  • 进程vs线程
  • JS是单线程的
  • 为何需要多进程?