Cluster

前言

最近 deno 的诞生,看着大牛们的分析文章,有很多看不懂的内容,作为一个立志成为大牛的大白,应该多向大牛们学习才是。
本人学艺不经,此文只作概念性介绍。

node

node 保持了 JavaScript 在浏览器中单线程的特点。单线程最大的好处就是不用像多线程那样需要注意状态的同步,死锁问题等。但是单线程也有它不好的地方,比如说,健壮性,无法利用多核CPU等。
于是出现了 child_process,顾名思义就是子线程,和 Web Workers 原理差不多,通过 Master-Worker 的管理方式,将处理分发给各个子进程,再通过进程之间的事件消息来传递结果,充分的利用了CPU资源,也提升了一定的健壮性。

child_process

node 中 child_process 模块提供了创建子进程的能力,有四个方法用于创建子进程:

1.spawn()
2.exec()
3.execFile()
4.fork()

具体方法使用这里不进行赘述,可以查看文档

进程间通信

Web Workers 中主线程和工作线程之间通过 onmessage() 和 postMessage() 进行通信。而在 node 中,通过 fork 等API创建子进程之后,父进程与子进程之间将会创建IPC(Inter-Process Communication)通道,通过IPC通道才能进行消息传递。
IPC是让不同的进程之间能够互相访问资源,IPC的方式通常有管道(命名管道、匿名管道)、消息队列、信号量、共享内存、Socket等实现方式。在 node 中 IPC 的具体实现由 libuv 提供,用管道技术进行实现(没有深究,书上看来的,只是概念性介绍^-^),暴露给上层是简单的 message 和 send 等接口,非常的简洁(我只是代码的搬运工,别人都封装好了~)。

句柄

上面说到,父进程和子进程之间创建IPC通道进行通信,那么子进程如何知道这个IPC是连接它的父进程的呢?
通过文件描述符,父进程在创建子进程的时候,会将IPC通道的文件描述符告诉子进程,子进程通过这个文件描述符去连接IPC通道,在linux上是文件描述符,在windows上是句柄,都是起到标识作用。

在 node 中可以看到如下 API

subprocess.send(message[, sendHandle[, options]][, callback])

第二个可选参数就是句柄,注意这里的句柄不是传递IPC通道的文件描述符(此时IPC已经建立连接了),这里的句柄用于传入一个 TCP 服务器或 socket 对象给子进程。
为什么直接传一个服务器对象给子进程呢?考虑一下,如果有请求通过80端口访问,父进程监听到请求,想让子进程处理,这个时候怎么做,如果使用代理转发给子进程,那么会多建立一个请求,也就多浪费一倍资源,这样,句柄的作用就体现出来了。

集群

虽然我们可以创建很多个子进程(集群),但是每个子进程都是在单线程上执行的,直接运行它的稳定性还是不能够保障,所以需要做一些子进程的管理操作来保障,比如监听子进程的退出(可能是异常退出,也可能是手动自己退出)实现自动重启(需要限量重启,不可能无限制重启)等功能。

cluster

在 node 中有一个 cluster 模块,可以直接创建共享服务器端口的集群

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

if (cluster.isMaster) {
  console.log(`主进程 ${process.pid} 正在运行`);

  // 衍生工作进程。
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`工作进程 ${worker.process.pid} 已退出`);
  });
} else {
  // 工作进程可以共享任何 TCP 连接。
  // 在本例子中,共享的是一个 HTTP 服务器。
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('hello world \n');
  }).listen(8000);

  console.log(`工作进程 ${process.pid} 已启动`);
}

cluster 模块是 child_process 和 net 模块的组合,简单来说,cluster 模块提供了一些便利,但是也失去了 child_process 的灵活度。

总结

参考:
* node 文档
* 深入浅出 nodeJS
* pm2

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值