Node.js中的进程与线程
时间:2025-11-04 17:46:22 出处:域名阅读(143)
 
1. 回顾进程和线程的进程定义
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是线程系统进行资源分配和调度的基本单位。
线程(Thread)是进程操作系统能够进行运算调度的最小单位。它被包含在进程之中,线程是进程进程中的实际运作单位。
2. Node.js的线程单线程
Node特点主线程是单线程的 一个进程只开一个主线程,基于事件驱动的、异步非阻塞I/O,进程可以应用于高并发场景。线程
Nodejs中没有多线程,进程为了充分利用多核cpu,线程可以使用子进程实现内核的负载均衡,那我们就要解决以下问题:
Node.js 做耗时的进程计算时候阻塞问题。
Node.js如何开启多进程。线程
开发过程中如何实现进程守护。进程
3. 场景实例
const http = require(http); http.createServer((req,线程res)=>{ if(req.url === /sum){ // 求和 let sum = 0; for(let i = 0 ; i < 10000000000 ;i++){ sum+=i; } res.end(sum+) }else{ res.end(end); } }).listen(3000); // 这里我们先访问/sum,在新建一个浏览器页卡访问/ // 会发现要等待/sum路径处理后才能处理/路径4. 开启进程
Node.js 进程创建,进程是服务器租用通过child_process模块实现的:
child_process.spawn() 异步生成子进程。
child_process.fork() 产生一个新的Node.js进程,并使用建立的IPC通信通道调用指定的模块,该通道允许在父级和子级之间发送消息。
child_process.exec() 产生一个shell并在该shell中运行命令。
child_process.execFile() 无需产生shell。
4.1. spawn
spawn 产卵,可以通过此方法创建一个子进程:
let { spawn } = require("child_process"); let path = require("path"); // 通过node命令执行sub_process.js文件 let childProcess = spawn("node",[sub_process.js], { cwd: path.resolve(__dirname, "test"), // 找文件的目录是test目录下 stdio: [0, 1, 2] }); // 监控错误 childProcess.on("error", function(err) { console.log(err); }); // 监听关闭事件 childProcess.on("close", function() { console.log("close"); }); // 监听退出事件 childProcess.on("exit", function() { console.log("exit"); }); stido 这个属性非常有特色,这里我们给了0,1,2这三个值分别对应住进程的 process.stdin , process.stdout 和 process.stderr 这代表着主进程和子进程共享标准输入和输出: let childProcess = spawn("node",[sub_process.js], { cwd: path.resolve(__dirname, "test"), // 找文件的目录是test目录下 stdio: [0, 1, 2] });可以在当前进程下打印 sub_process.js 执行结果默认在不提供stdio参数时为 stdio:[pipe] ,也就是只能通过流的方式实现进程之间的通信:
let { spawn } = require("child_process"); let path = require("path"); // 通过node命令执行sub_process.js文件 let childProcess = spawn("node",[sub_process.js], { cwd: path.resolve(__dirname, "test"), stdio:[pipe] // 通过流的方式 }); // 子进程读取写入的数据 childProcess.stdout.on(data,function(data){ console.log(data); }); // 子进程像标准输出中写入 process.stdout.write(hello);使用 ipc 方式通信,设置值为 stdio:[pipe,pipe,pipe,ipc] 可以通过 on(message) 和 send 方式进行通信:
let { spawn } = require("child_process"); let path = require("path"); // 通过node命令执行sub_process.js文件 let childProcess = spawn("node",[sub_process.js], { cwd: path.resolve(__dirname, "test"), stdio:[pipe,pipe,pipe,ipc] // 通过流的方式 }); // 监听消息 childProcess.on(message,function(data){ console.log(data); }); // 发送消息 process.send(hello);还可以传入 ignore 进行忽略,传入 inherit 表示默认共享父进程的标准输入和输出。高防服务器
产生独立进程:
let { spawn } = require("child_process"); let path = require("path"); // 通过node命令执行sub_process.js文件 let child = spawn(node,[sub_process.js],{ cwd:path.resolve(__dirname,test), stdio: ignore, detached:true // 独立的线程 }); child.unref(); // 放弃控制4.2. fork
衍生新的进程,默认就可以通过 ipc 方式进行通信:
let { fork } = require("child_process"); let path = require("path"); // 通过node命令执行sub_process.js文件 let childProcess = fork(sub_process.js, { cwd: path.resolve(__dirname, "test"), }); childProcess.on(message,function(data){ console.log(data); });fork 是基于 spawn 的,可以多传入一个 silent 属性来设置是否共享输入和输出。
fork原理:
function fork(filename,options){ let stdio = [inherit,inherit,inherit] if(options.silent){ // 如果是安静的 就忽略子进程的输入和输出 stdio = [ignore,ignore,ignore] } stdio.push(ipc); // 默认支持ipc的方式 options.stdio = stdio return spawn(node,[filename],options) }到了这里我们就可以解决“3.场景实例”中的场景实例了:
const http = require(http); const {fork} = require(child_process); const path = require(path); http.createServer((req,res)=>{ if(req.url === /sum){ let childProcess = fork(calc.js,{ cwd:path.resolve(__dirname,test) }); childProcess.on(message,function(data){ res.end(data+); }) }else{ res.end(ok); } }).listen(3000);4.3. execFile
通过 node 指令,直接执行某个文件:
let childProcess = execFile("node",[./test/sub_process],function(err,stdout,stdin){ console.log(stdout); });内部调用的是 spawn 方法。
4.4. exec
let childProcess = exec("node ./test/sub_process",function(err,stdout,stdin){ console.log(stdout) });内部调用的是 execFile ,其实以上三个方法都是基于 spawn 的。
5. cluster
Node.js的单个实例在单个线程中运行。为了利用多核系统,用户有时会希望启动Node.js进程集群来处理负载。 自己通过进程来实现集群。
子进程与父进程共享HTTP服务器 fork实现:
let http = require(http); let { fork } = require(child_process); let fs = require(fs); let net = require(net); let path = require(path); let child = fork(path.join(__dirname, 8.child.js)); let server = net.createServer(); server.listen(8080, 127.0.0.1, function () { child.send(server, server); console.log(父进程中的服务器已经创建); let httpServer = http.createServer(); httpServer.on(request, function (req, res) { if (req.url != /favicon.ico) { let sum = 0; for (let i = 0; i < 100000; i++) { sum += 1; } res.write(客户端请求在父进程中被处理。); res.end(sum= + sum); } }); httpServer.listen(server); }); let http = require(http); process.on(message, function (msg, server) { if (msg == server) { console.log(子进程中的服务器已经被创建); let httpServer = http.createServer(); httpServer.on(request, function (req, res) { if (req.url != /favicon.ico) { sum = 0; for (let i = 0; i < 10000; i++) { sum += i; } res.write(客户端请求在子进程中被处理); res.end(sum= + sum); } }); httpServer.listen(server); } });进程与父进程共享socket对象:
let { fork } = require(child_process); let path = require(path); let child = fork(path.join(__dirname, 11.socket.js)); let server = require(net).createServer(); server.on(connection, function (socket) { if (Date.now() % 2 == 0) { child.send(socket, socket); } else { socket.end(客户端请求被父进程处理!); } }); server.listen(41234, ); process.on(message, function (m, socket) { if (m === socket) { socket.end(客户端请求被子进程处理.); } });使用cluster模块更加方便:
let cluster = require("cluster"); let http = require("http"); let cpus = require("os").cpus(). 免费信息发布网猜你喜欢
- 苹果6s手机质量评测(用心设计,品质保证,苹果6s手机的优势与不足)
 - Mira手环(探索Mira手环的功能与优势,让健康与时尚并驾齐驱)
 - 用iPadmini2唱歌,体验音乐的全新感觉(探索iPadmini2唱歌功能,打造属于你的音乐世界)
 - 小米6运动拍照效果全面解析(小米6运动拍照功能强大,记录每一刻动感细节)
 - 电脑玉雕创作教程(掌握玉雕电脑雕刻技术的关键步骤)
 - 探索BOSESolo(性的音频技术带来前所未有的音乐享受)
 - 探索Xplay6屏幕的卓越表现(揭秘Xplay6屏幕的突破性技术和出色画质)
 - 华为手表S1(开启时尚智能之旅,华为手表S1引领未来)
 - 电脑手绘装修柜子教程(学习如何使用电脑手绘技巧来装修你的柜子,让家居更加个性化)