纵横研究院NodeJS技术专题社区

【原创】学习NodeJs多进程(二)

2019-04-07  本文已影响33人  拂云枝

前文介绍了NodeJs子进程创建和进程间通信,但让开发者处理多进程的管理是比较麻烦的事情,通常开发者只希望关注业务代码的实现。本文介绍了多进程管理相关的cluster模块、工具、负载均衡等。

相关文章

目录

cluster模块

cluster模块是对多进程创建、消息传递、共享端口的封装。以下为官方的使用示例,根据cpu数量创建工作进程,并监听同一个端口8000

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

if (cluster.isMaster) {
  console.log(`Master ${process.pid} is running`)

  // Fork workers.
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork()
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`worker ${worker.process.pid} died`)
  })
} else {
  // Workers can share any TCP connection
  // In this case it is an HTTP server
  http.createServer((req, res) => {
    res.writeHead(200)
    res.end('hello world\n')
  }).listen(8000)

  console.log(`Worker ${process.pid} started`)
}

在前文介绍的多进程监听同一端口中,主进程创建服务器,并将服务器句柄传递给子进程,子进程再根据句柄还原服务器实例,请求到来时由操作系统调度机制决定交给哪个进程处理。以上由于保留了多个服务器实例直接监听同一端口,会造成资源浪费,并且请求转发不可控。

cluster模块中默认以轮询的方式处理请求,父进程创建内部服务器并监听端口,所有请求先经过该服务器,再转发给子进程处理。由于父进程负责转发,因此父进程可以指定负载均衡策略,另外父进程不直接处理业务逻辑,可以保证父进程的稳定性。

cluster模块提供丰富的api用来管理子进程,以下示例为子进程挂掉后自动创建新的进程:

const cluster = require('cluster')
const http = require('http')

cluster.schedulingPolicy = cluster.SCHED_RR

function listen (worker) {
  worker.on('message', (msg) => {
    console.log(`worker ${worker.process.pid}:`, msg)
  })
}

if (cluster.isMaster) {
  console.log(`master process ${process.pid} is running`)
  for (let i = 0; i < 4; i++) {
    cluster.fork()
  }

  for (const id in cluster.workers) {
    listen(cluster.workers[id])
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`worker process ${worker.process.pid} is exited`)
    listen(cluster.fork())
  })
} else {
  http.createServer((req, res) => {
    res.writeHead(200)
    res.end('hello world')

    process.send('handled request')
  }).listen(8000)

  console.log(`worker process ${process.pid} is running`)
}

访问localhost:8000,再手动kill掉某一进程,执行结果如下:

master process 8616 is running
worker process 16332 is running
worker process 4624 is running
worker process 8084 is running
worker process 16352 is running
worker 16332: handled request
worker 15172: handled request
worker process 15172 is exited
worker process 2260 is running
worker 16332: handled request
worker 8084: handled request
worker 2260: handled request

可以看到,只要有子进程退出,会自动创建子进程。只要有工作进程存在,就能继续处理请求。

负载均衡

cluster模块提供两种负载均衡策略

使用cluster.schedulingPolicy可指定以上两种策略,也可以使用NODE_CLUSTER_SCHED_POLICY环境变量,对应以上的两种策略的取值为rrnone

cluster不支持自定义负载均衡策略,可参考cluster的源码,实现自己的负载均衡策略。根据cluster模块源码学习来理解多进程的负载均衡算法,文章地址:http://www.cnblogs.com/accordion/p/7207740.html

进程管理工具

在生产环境中,除了使用多进程充分利用cpu性能外,还需考虑进程异常退出的自动重启,多个工作进程共享资源,以及多进程之间的调度。cluster模块只是对多进程创建、消息传递、共享端口的简单封装,下面介绍一些目前成熟的进程管理工具。

cluster不适用的场景

这里的cluster不止指node的cluster模块,也包括通过第三方库实现的多进程管理工具。cluster虽然能充分利用服务器cpu资源,提高服务的健壮性,但并不是所有场景都适合用多进程来处理,比如:

总结

本文介绍了cluster模块和常用的多进程管理工具,希望对想要使用多进程来提升服务的性能和健壮性的小伙伴有一些帮助。

本文参考资源如下

上一篇 下一篇

猜你喜欢

热点阅读