详解如何利用Nodejs构建多进程应用

 更新时间:2022年10月18日 14:46:55   作者:SaraiNoQ  
这篇文章主要为大家介绍了如何利用Nodejs构建多进程应用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

前言

JavaScript 主线程运行在单个进程的单个线程上。这样做的好处是:

  • 程序状态是单一的,在没有多线程的情况下没有锁、线程同步问题,
  • 操作系统在调度时因为较少上下文的切换,可以很好地提高CPU的使用率。

但是单进程单线程并非完美的结构,一旦线程中某段代码发生异常阻塞,会阻塞代码执行而浪费资源。同时,如今CPU基本均是多核的,服务器往往还有多个CPU。

因此 Nodejs 不可避免的面临两个问题:如何充分利用多核CPU ****和 ****如何保证进程的健壮性和稳定性 。 另外,由于 Nodejs 中所有处理都在单线程上进行,影响事件驱动服务模型性能的点在于CPU的计算能力,而不受多进程或多线程模式中资源上限的影响,可伸缩性远比前两者高。如果解决掉多核CPU的利用问题,带来的性能上提升是可观的。

进程的创建和使用

多核利用率

面对单进程单线程对多核使用不足的问题,最简单的方法是启动多进程即可。理想状态下每个进程各自利用一个CPU,以此实现多核CPU的利用。Nodejs 提供了 child_process模块,并且也提供了child_process.fork() 方法帮助我们实现进程的复制。

你可以通过这个方法在本地启动多个 HTTP 服务,首先编写一段创建 http服务端 的代码:

const http = require("http");
const server = http.createServer((req, res) => {
  res.writeHead(200, {
    "Content-Type": "text/plain"
  });
  res.end("hello,world!");
});
// 随机监听1000-1999的任意一个端口
server.listen(Math.floor((1 + Math.random()) * 1000));

然后创建一个主进程 master.js 来启动和管理他们:

const fork = require("child_process").fork;
const cpus = require("os").cpus();
console.log(cpus.length);
for (let i = 0; i < cpus.length; i++) {
  fork('./server.js');
}

💡 在 Linux 系统中,你可以通过 ps aux | grep worker.js 来直接查看,在 Windows 中,你能通过 netstat -a 然后查看 1000-1999 端口的进程。

这样的模式称为 Master-Worker模式,又称 主从模式。如图,进程分为两种:主进程和工作进程。这是典型的分布式架构中用于并行处理业务的模式,具备较好的可伸缩性和稳定性:

  • 主进程不负责具体的业务处理,而是负责调度或管理工作进程,它是趋向于稳定的。
  • 工作进程负责具体的业务处理,趋于不稳定。

💡 fork() 能让我们复制进程使每个CPU内核都使用上,但是依然要切记 fork() 进程是昂贵的。因为Node通过事件驱动和异步IO的方式很大的缓解了并发问题,所以这里启动多个进程只是为了充分将CPU资源利用起来,而不是为了解决并发问题。

创建子进程

child_process模块 给予 Node 可以随意创建子进程(child_process)的能力。它提供了4个方法用于创建子进程:

  • spawn():启动一个子进程来执行命令。
  • exec():启动一个子进程来执行命令。与spawn()不同的是其接口不同,它有一个回调函数获知子进程的状况。
  • execFile():启动一个子进程来执行可执行文件。
  • fork():与 spawn() 类似,不同点在于它创建 Node 的子进程只需指定要执行的 JavaScript 文件模块即可。
const cp = require("child_process");
cp.spawn("node", ["./server.js"]);
cp.exec("node server.js", (err, stdout, stderr) => {
  // TODO
});
cp.execFile("server.js", (err, stdout, stderr) => {
  // TODO
});
cp.fork('./server.js');

💡 execFile() 只能用于可以直接执行的文件。在 Linux 中,你可以在文件开头加入 #! /usr/bin/env node

进程间通信 IPC

Master-Worker模式 中,要实现主进程管理和调度工作进程的功能,需要主进程和工作进程之间的通信。子进程对象则由 send() 方法实现主进程向子进程发送数据,message事件 实现收听子进程发来的数据:

// parent.js
const cp = require("child_process");
const n = cp.fork("./child.js");
n.on('message', (msg) => {
  console.log('parent got msg: ', msg);
});
n.send({
  s: 'hello, world',
});
// child.js
process.on('message', (msg) => {
  console.log('child got msg', msg);
});
process.send({
  b: 'bar',
});

💡 HTML5提出了 WebWorker API 来创建工作线程,而主进程和工作进程之间通过 onmessage()postMessage() 进行通信。具体参考MDN文档

通过 fork() 或者其他API,创建子进程之后,为了实现父子进程之间的通信,父进程与子进程之间将会创建IPC通道(Inter-Process Communication,即进程间通信) 。通过IPC通道,父子进程之间才能通过message和send()传递消息。

父进程在实际创建子进程之前,会创建IPC通道并监听它,然后才真正创建出子进程,并通过环境变量(NODE_CHANNEL_FD)告诉子进程这个IPC通道的文件描述符。子进程在启动的过程中,根据文件描述符去连接这个已存在的IPC通道,从而完成父子进程之间的连接。

💡 只有启动的子进程是Node进程时,子进程才会根据环境变量去连接IPC通道。对于其他类型的子进程则无法实现进程间通信,除非其他进程也按约定去连接这个已经创建好的IPC通道

总结

今天我们讨论了 Nodejs 在多核利用方法的问题,然后介绍了创建子进程、进程间通信与IPC通道的内容。通过这些基础技术,用 child_process模块 在单机上搭建 Nodejs集群 是件相对容易的事情,让 Nodejs 能够在多核CPU的环境下充分利用计算资源。

以上就是详解如何利用Nodejs构建多进程应用的详细内容,更多关于Nodejs构建多进程应用的资料请关注脚本之家其它相关文章!

相关文章

  • 剖析Node.js异步编程中的回调与代码设计模式

    剖析Node.js异步编程中的回调与代码设计模式

    这篇文章主要介绍了Node.js异步编程中的回调与代码设计模式,虽然大多数场合回调编写时的长串括号不怎么好看,但Node的异步性能确实很好,需要的朋友可以参考下
    2016-02-02
  • node.js爬取中关村的在线电瓶车信息

    node.js爬取中关村的在线电瓶车信息

    这篇文章主要给大家介绍了关于利用node.js如何爬取中关村的在线电瓶车信息的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用node.js具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • Node.js 实现抢票小工具 & 短信通知提醒功能

    Node.js 实现抢票小工具 & 短信通知提醒功能

    这篇文章主要介绍了Node.js 实现抢票小工具 & 短信通知提醒功能,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-10-10
  • nodejs 快速入门之事件循环

    nodejs 快速入门之事件循环

    这篇文章主要介绍了nodejs 快速入门之事件循环的相关资料,需要的朋友可以参考下
    2023-05-05
  • 手把手教你把nodejs部署到linux上跑出hello world

    手把手教你把nodejs部署到linux上跑出hello world

    本篇文章主要介绍了手把手教你把nodejs部署到linux上跑出hello world,非常具有实用价值,需要的朋友可以参考下
    2017-06-06
  • node解析修改nginx配置文件操作实例分析

    node解析修改nginx配置文件操作实例分析

    这篇文章主要介绍了node解析修改nginx配置文件操作,结合实例形式分析了node.js使用nginx-conf解析修改nginx配置文件的相关操作技巧,需要的朋友可以参考下
    2019-11-11
  • Node.js开发静态资源服务器

    Node.js开发静态资源服务器

    这篇文章主要为大家介绍了Node.js开发静态资源服务器示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • node连接MongoDB数据库错误:MongoServerSelectionError: connect ECONNREFUSED ::1:27017(解决方案)

    node连接MongoDB数据库错误:MongoServerSelectionError: connect ECON

    使用node连接MongoDB数据库时发生报错,MongoServerSelectionError: connect ECONNREFUSED ::1:27017,本文给大家分享原因分析及解决方案,感兴趣的朋友跟随小编一起看看吧
    2023-04-04
  • 在Node.js中将SVG图像转换为PNG,JPEG,TIFF,WEBP和HEIF格式的方法

    在Node.js中将SVG图像转换为PNG,JPEG,TIFF,WEBP和HEIF格式的方法

    这篇文章主要介绍了在Node.js中将SVG图像转换为PNG,JPEG,TIFF,WEBP和HEIF格式的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • 基于docker搭建node环境开发服务器全过程

    基于docker搭建node环境开发服务器全过程

    这篇文章主要给大家介绍了关于如何基于docker搭建node环境开发服务器的相关资料,本文将采用docker技术部署一个简单的nodejs应用,文中通过图文以及代码介绍的非常详细,需要的朋友可以参考下
    2023-11-11

最新评论