node 多进程 vs java_如何理解node的多进程

事件驱动

nodejs基于chrome v8引擎构建,默认单线程单进程模式,nodejs的单线程指的是js引擎只有一个实例,且是在主线程执行的(减少线程间切换的开销,不用考虑锁和线程池问题),其他的异步IO和事件驱动相关的线程通过libuv实现内部的线程池和线程调度。libuv存在一个事件循环,事件循环中维持一个执行栈和任务队列,在执行栈中,如果有异步IO及定时器等函数的话,就把异步回调函数放入事件队列中,执行栈执行完成后,从事件队列中按照一定的顺序执行事件队列中的异步回调。

模块调用

nodejs中的模块调用,js代码调用c++核心模块,核心模块调用内建模块,通过libuv进行系统调用,送入线程池等待执行。线程池中的I/O操作调用完成之后会保存结果向IOCP(一种高性能的I/O模型,一种应用程序使用线程池处理异步I/O请求的机制)提交执行状态告知当前对象操作完成并将线程归还线程池

非阻塞I/O

程序执行过程中需要进行很多I/O操作,读写文件、输入输出、请求响应等,I/O操作较为费时,基于node的事件循环机制,在I/O操作的同时,可以继续执行其他的代码。如文件IO,nodejs调用libuv后,libuv在其他线程执行I/O任务,线程完成任务后会通知主线程,主线程回调nodejs。

多进程

nodejs以单线程模式运行,使用事件驱动处理并发,可以在多核CPU系统上创建多个子线程。进程分为master进程和worker进程,master进程负责调度和管理worker进程,worker进程负责具体的业务处理,在服务器层面,worker是一个服务进程,负责处理来自客户端的请求,多个worker相当于多个服务器,因此构成一个服务器群,master进程负责创建worker,接收客户端的请求,分配到各服务器上去处理,监控worker的运行状态及管理操作。

node提供child_process模块创建子进程。nodejs实现多进程

spawn 使用指定的命令行参数创建新进程

fork 用于在子进程中运行的模块,基于spawn的封装,fork('./main.js)相当于spawn('node', ['./main.js']),fork会在父进程与子进程之间,建立一个用于通信的管道,用于进程间的通信

exec 使用子进程执行命令,缓存子进程的输出,将子进程的输出以回调函数参数的形式返回。execFile基于spawn封装,可以直接创建子进程进行文件操作,exec基于execFile封装,可以直接开启子进程执行命令,常见的应用场景如http-server以及webpack-dev-server命令行在启动本地服务是自动打开浏览器。

集群与进程通信

node主进程在创建子进程的时候吧把主进程正在监听的server当作参数传给子进程,子进程自己也创建一个server来监听主进程传来的server。通过process.on中的message接受信息,使用process.send发送信息。

ipc标准进程通信使用send方法发送消息时,第二个参数支持传入一个服务,必须是http服务或tcp服务,子进程通过message事件进行接收,回调的参数对应发送的参数,第一个参数为消息,第二个参数为服务,可以在子进程创建服务并对主进程的服务进行监听和操作

const os = require("os"); // os 模块用于获取系统信息

const http = require("http");

const path = require("path");

const { fork } = rquire("child_process");

// 创建服务

const server = createServer((res, req) => {

res.end("hello");

}).listen(3000);

// 根据 CPU 个数创建子进程

os.cpus().forEach(() => {

fork("child_server.js", {

cwd: path.join(__dirname);

}).send("server", server);

});

/**-------------------子进程业务的代码----------------------*/

const http = require("http");

// 接收来自主进程发来的服务

process.on("message", (data, server) => {

http.createServer((req, res) => {

res.end(`child${process.pid}`);

}).listen(server); // 子进程共用主进程的服务

});

单个nodejs实例运行在单个线程中,为了充分利用多核系统,有时需要启用一组nodejs进程去处理负载任务,cluster模块可以创建共享服务器端口的子进程。cluster模块,通过isMaster属性,判断是否是Master进程,是则fork子进程,否则启动一个server,每个HTTP Server都能监听到同一个端口。cluster

cluster 模块可以创建共享服务器端口的子进程。

const cluster = require("cluster");

const http = require("http");

const os = require("os");

// 判断当前执行的进程是否为主进程,为主进程则创建子进程,否则用子进程监听服务

if (cluster.isMaster) {

// 创建子进程

os.cpus().forEach(() => cluster.fork());

} else {

// 创建并监听服务

http.createServer((req, res) => {

res.end(`child${process.pid}`);

}).listen(3000);

}

模块分类

核心模块:包含在nodejs源码中,被编译进nodejs可执行二进制文件的js模块,是lib和deps目录下的js文件,如http/fs等

内建模块: 一般不直接调用,在native模块中调用,再require

第三方模块:非nodejs源码自带的模块为第三方模块,如webpack/express,如lib目录下的fs.js是native模块,而fs.js调用的src目录下的node_fs.cc是内建模块

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值