
เราทุกคนรู้ดีว่า Node.js ใช้โมเดล I/O แบบอะซิงโครนัสแบบเธรดเดียวที่ขับเคลื่อนด้วยเหตุการณ์ คุณลักษณะของมันคือตัวกำหนดว่าไม่สามารถใช้ประโยชน์จาก CPU แบบมัลติคอร์ได้ และไม่ดีในการดำเนินการบางอย่างที่ไม่ใช่ I/O ( เช่น การรันสคริปต์) , การคำนวณ AI, การประมวลผลภาพ ฯลฯ ) เพื่อแก้ไขปัญหาดังกล่าว Node.js ได้จัดเตรียมโซลูชันแบบหลายกระบวนการ (เธรด) แบบธรรมดา (สำหรับการอภิปรายเกี่ยวกับกระบวนการและเธรด โปรดดูที่ผู้เขียน บทความอื่นๆ Node.js และ Concurrency Model ) บทความนี้จะแนะนำให้คุณรู้จักกับกลไกแบบมัลติเธรดของ Node.js
เราสามารถใช้โมดูล child_process เพื่อสร้างกระบวนการย่อยของ Node.js เพื่อทำงานพิเศษบางอย่างให้เสร็จสมบูรณ์ (เช่น การรันสคริปต์) โมดูลนี้ส่วนใหญ่จะมี exec , execFile , fork , spwan และวิธีอื่น ๆ ด้านล่างนี้เราจะแนะนำวิธีการเหล่านี้โดยย่อ . ใช้.
const { exec } = ต้องการ ('child_process');
exec('ls -al', (ข้อผิดพลาด, stdout, stderr) => {
console.log(stdout);
}); เมธอดนี้ประมวลผลสตริงคำสั่งตามไฟล์ปฏิบัติการที่ระบุโดย options.shell แคชเอาต์พุตระหว่างการดำเนินการคำสั่ง จากนั้นส่งคืนผลลัพธ์การดำเนินการในรูปแบบของพารามิเตอร์ฟังก์ชันเรียกกลับจนกว่าการดำเนินการคำสั่งจะเสร็จสมบูรณ์
พารามิเตอร์ของวิธีนี้มีการอธิบายดังนี้
options
cwd
command สั่งที่จะดำเนินการ (เช่น ls -al );
ค่าเริ่ม process.env env
encoding utf8
process.cwd()
shell
บน
Unix /bin/sh Windows ของ process.env.ComSpec (หากว่างเปล่า จะเป็น cmd.exe );
} = ต้องการ ('child_process');
exec("print('Hello World!')", { shell: 'python' }, (ข้อผิดพลาด, stdout, stderr) => {
console.log(stdout);
}); การรันตัวอย่างข้างต้นจะแสดงผล Hello World! ซึ่งเทียบเท่ากับกระบวนการย่อยที่รันคำสั่ง python -c "print('Hello World!')" ดังนั้น เมื่อใช้แอ็ตทริบิวต์นี้ คุณต้องใส่ใจกับ ไฟล์ปฏิบัติการที่ระบุต้องได้รับการสนับสนุน การดำเนินการของคำสั่งที่เกี่ยวข้องผ่านตัวเลือก -c
หมายเหตุ: มันเกิดขึ้นที่ Node.js รองรับตัวเลือก -c เช่นกัน แต่เทียบเท่ากับตัวเลือก --check ใช้เพื่อตรวจสอบว่ามีข้อผิดพลาดทางไวยากรณ์ในสคริปต์ที่ระบุหรือไม่ และจะไม่เรียกใช้สคริปต์ที่เกี่ยวข้อง
signal : ใช้ AbortSignal ที่ระบุเพื่อยุติกระบวนการ
ลูก
const ac = AbortController ใหม่ ();
exec('ls -al', { signal: ac.signal }, (error, stdout, stderr) => {}); ในตัวอย่างข้างต้น เราสามารถยุติกระบวนการย่อยได้ก่อนเวลาโดยการเรียก ac.abort()
timeout : เวลาหมดเวลาของกระบวนการลูก (หากค่าของคุณลักษณะนี้มากกว่า 0 ดังนั้นเมื่อเวลาการทำงานของกระบวนการลูกเกินค่าที่ระบุ สัญญาณการสิ้นสุดที่ระบุโดยแอตทริบิวต์ killSignal จะถูกส่งไปยังกระบวนการลูก ) ในหน่วยมิลลิเมตร ค่าเริ่มต้นคือ 0 ;
maxBuffer : แคชสูงสุด (ไบนารี) ที่อนุญาตโดย stdout หรือ stderr หากเกินนั้น กระบวนการลูกจะถูกฆ่าและเอาต์พุตใด ๆ จะถูกตัดทอน ค่าเริ่มต้นคือ 1024 * 1024
killSignal : สัญญาณการยุติกระบวนการลูก ค่าเริ่มต้นคือ SIGTERM ;
uid สำหรับการดำเนินการกระบวนการลูก uid
gid gid สำหรับการดำเนินการกระบวนการลูก
windowsHide : ไม่ว่าจะซ่อนหน้าต่างคอนโซลของกระบวนการลูกที่ใช้กันทั่วไปในระบบ Windows ค่าเริ่มต้นคือ false ;
callback : ฟังก์ชัน callback รวมถึง error , stdout , stderr พารามิเตอร์:
error : หากดำเนินการบรรทัดคำสั่งสำเร็จ ค่าจะเป็น null มิฉะนั้นค่าจะเป็นอินสแตนซ์ของ Error โดยที่ error.code คือทางออก รหัสข้อผิดพลาดของกระบวนการเด็ก error.signal เป็นstdout encoding buffer stderr stdout encoding stderr หรือค่าของ stdout หรือ stderr เป็นสตริงที่ไม่รู้จัก ก็จะถูกเข้ารหัสตาม bufferconst { execFile } = ต้องการ ('child_process');
execFile('ls', ['-al'], (ข้อผิดพลาด, stdout, stderr) => {
console.log(stdout);
}); ฟังก์ชั่นของเมธอดนี้คล้ายกับ exec ข้อแตกต่างเพียงอย่างเดียวคือ execFile ประมวลผลคำสั่งโดยตรงด้วยไฟล์ปฏิบัติการที่ระบุ (นั่นคือค่าของ file พารามิเตอร์ ) ตามค่าเริ่มต้น ซึ่งทำให้ประสิทธิภาพสูงกว่า exec เล็กน้อย (ถ้าคุณดูที่เชลล์ เมื่อพูดถึงตรรกะในการประมวลผล ฉันรู้สึกว่าประสิทธิภาพนั้นน้อยมาก)
พารามิเตอร์ของวิธีการนี้อธิบายไว้ดังนี้:
file : ชื่อหรือเส้นทางของไฟล์ปฏิบัติการ
args : รายการพารามิเตอร์ของไฟล์ปฏิบัติการ
options : การตั้งค่าพารามิเตอร์ (ไม่สามารถระบุได้) คุณสมบัติที่เกี่ยวข้องมีดังนี้:
shell : เมื่อค่าเป็น false หมายถึงการใช้ไฟล์ปฏิบัติการที่ระบุโดยตรง (นั่นคือ ค่าของ file พารามิเตอร์ ) ประมวลผลคำสั่ง เมื่อค่าเป็น true หรือสตริงอื่น ฟังก์ชันจะเทียบเท่ากับ shell ใน exec ค่าเริ่มต้นคือ false ;windowsVerbatimArguments : ไม่ว่าจะอ้างอิงหรือหลีกพารามิเตอร์ใน Windows คุณลักษณะนี้จะถูก Unix falsekillSignal uid maxBuffer cwd timeout encoding gid env , windowsHide และ signal ได้รับการแนะนำข้างต้นแล้ว และจะไม่ถูกทำซ้ำที่นี่callback : ฟังก์ชัน callback ซึ่งเทียบเท่ากับ callback ใน exec และจะไม่อธิบายไว้ที่นี่
const { fork } = ต้องการ ('child_process');
const echo = fork('./echo.js', {
เงียบ: จริง
-
echo.stdout.on('ข้อมูล', (ข้อมูล) => {
console.log(`stdout: ${data}`);
-
echo.stderr.on('ข้อมูล', (ข้อมูล) => {
console.error(`stderr: ${data}`);
-
echo.on('ปิด', (รหัส) => {
console.log(`กระบวนการลูกออกด้วยรหัส ${code}`);
}); วิธีการนี้ใช้เพื่อสร้างอินสแตนซ์ Node.js ใหม่เพื่อรันสคริปต์ Node.js ที่ระบุและสื่อสารกับกระบวนการหลักผ่าน IPC
พารามิเตอร์ของเมธอดนี้อธิบายไว้ดังนี้:
modulePath : เส้นทางของสคริปต์ Node.js ที่จะเรียกใช้;
args : รายการพารามิเตอร์ที่ส่งผ่านไปยังสคริปต์ Node.js;
options : การตั้งค่าพารามิเตอร์ (ไม่สามารถระบุได้), คุณลักษณะที่เกี่ยวข้อง เช่น:
execArgv process.execArgv
detached spwan ล่างของ options.detached
serialization
execPath
: ประเภทหมายเลขซีเรียลของข้อความระหว่างกระบวนการ ค่าที่ใช้ได้คือ json และ advanced ค่าเริ่มต้นคือ json ;
slient : หาก true stdin , stdout และ stderr ของกระบวนการลูกจะถูกส่งไปยังกระบวนการหลัก ผ่านไปป์ มิฉะนั้น stdin , stdout และ stderr ของกระบวนการหลักจะได้รับการสืบทอด ค่าเริ่มต้นคือ false ;
stdio : ดูคำอธิบายของ options.stdio ใน spwan ด้านล่าง สิ่งที่ต้องสังเกตที่นี่คือ
slient จะถูกละเว้นipc (เช่น [0, 1, 2, 'ipc'] ) มิฉะนั้น ข้อยกเว้นจะถูกส่งออกไปคุณสมบัติ cwd , env , uid , gid , windowsVerbatimArguments , signal , timeout และ killSignal ได้รับการแนะนำข้างต้นและจะไม่ทำซ้ำที่นี่
const { วางไข่ } = ต้องการ ('child_process');
const ls = วางไข่ ('ls', ['-al']);
ls.stdout.on('ข้อมูล', (ข้อมูล) => {
console.log(`stdout: ${data}`);
-
ls.stderr.on('ข้อมูล', (ข้อมูล) => {
console.error(`stderr: ${data}`);
-
ls.on('ปิด', (รหัส) => {
console.log(`กระบวนการลูกออกด้วยรหัส ${code}`);
}); fork spawn execFile exec พื้นฐานของโมดูล child_process
พารามิเตอร์ของวิธีนี้มีการอธิบายดังต่อไปนี้:
command : ชื่อหรือเส้นทางของไฟล์ที่เรียกใช้งาน
options
args
argv0 : ส่งไปยังค่า argv [0] ค่าเริ่มต้นค่าเริ่มต้นคือค่าของ command พารามิเตอร์
detached กระบวนการสามารถทำงานต่อไปได้) ค่าเริ่มต้นคือ false และเมื่อค่าเป็น true แต่ละแพลตฟอร์ม ผลกระทบจะเป็นดังนี้:
Windows หลังจากที่กระบวนการหลักออกแล้ว กระบวนการลูกสามารถทำงานต่อไปได้ และกระบวนการลูก มีหน้าต่างคอนโซลของตัวเอง (เมื่อคุณสมบัตินี้เริ่มต้นขึ้น จะไม่สามารถเปลี่ยนแปลงได้ในระหว่างกระบวนการทำงาน)Windows กระบวนการย่อยจะทำหน้าที่เป็นผู้นำของกลุ่มเซสชันกระบวนการใหม่ ในเวลานี้ โดยไม่คำนึงถึง ไม่ว่ากระบวนการย่อยจะถูกแยกออกจากกระบวนการหลักหรือไม่ กระบวนการย่อยสามารถทำงานต่อไปได้หลังจากที่กระบวนการหลักออกจากระบบแล้วควรสังเกตว่าหากกระบวนการลูกจำเป็นต้องทำงานในระยะยาว และต้องการให้กระบวนการหลักออกก่อนกำหนด จะต้องปฏิบัติตามประเด็นต่อไปนี้พร้อมกัน:
unref ของกระบวนการลูกเพื่อลบเด็กออก กระบวนการจากลูปเหตุการณ์ของกระบวนการหลักdetached ตั้งค่าเป็น trueignore stdioตัวอย่างเช่น ตัวอย่างต่อไปนี้:
// hello.js
const fs = ต้องการ('fs');
ให้ดัชนี = 0;
ฟังก์ชั่นรัน () {
setTimeout(() => {
fs.writeFileSync('./hello', `index: ${index}`);
ถ้า (ดัชนี < 10) {
ดัชนี += 1;
วิ่ง();
-
}, 1,000);
-
วิ่ง();
//main.js
const { วางไข่ } = ต้องการ ('child_process');
const child = วางไข่ ('โหนด', ['./hello.js'], {
เดี่ยว: จริง
stdio: 'ไม่สนใจ'
-
child.unref();stdio : การกำหนดค่าอินพุตและเอาท์พุตมาตรฐานของกระบวนการลูก ค่าเริ่มต้นคือ pipe ค่าคือสตริงหรืออาร์เรย์:
pipe ถูกแปลงเป็น ['pipe', 'pipe', 'pipe'] ) ค่าที่มีอยู่คือ pipe , overlapped , ignore , inherit ;stdin , stdout และ stderr ตามลำดับแต่ละค่าที่มีอยู่ของรายการคือ pipe , overlapped , ignore , inherit , ipc , วัตถุสตรีม, จำนวนเต็มบวก (ตัวอธิบายไฟล์ที่เปิดในกระบวนการหลัก), null (ถ้าเป็น ตั้งอยู่ในสามรายการแรกของอาร์เรย์จะเทียบเท่ากับ pipe มิฉะนั้นจะเทียบเท่ากับ ignore ) undefined (หากอยู่ในสามรายการแรกของอาร์เรย์ จะเทียบเท่ากับ pipe มิฉะนั้นจะเทียบเท่ากับ ignore ).คุณลักษณะ cwd , env , uid , gid , serialization , shell (ค่าเป็น boolean หรือ string ), windowsVerbatimArguments , windowsHide , signal , timeout , killSignal ได้รับการแนะนำข้างต้น และจะไม่ถูกทำซ้ำที่นี่
ข้างต้นให้ข้อมูลเบื้องต้นสั้นๆ เกี่ยวกับการใช้วิธีการหลักในโมดูล child_process เนื่องจากวิธี execSync , execFileSync , forkSync และ spwanSync เป็นเวอร์ชันซิงโครนัสของ exec , execFile และ spwan จึงไม่มีความแตกต่างในพารามิเตอร์ ดังนั้น พวกเขาจะไม่ถูกทำซ้ำ
ผ่านโมดูล cluster เราสามารถสร้างคลัสเตอร์กระบวนการ Node.js ได้ด้วยการเพิ่มกระบวนการ Node.js ลงในคลัสเตอร์ เราสามารถใช้ประโยชน์จากมัลติคอร์ได้อย่างเต็มที่ยิ่งขึ้น และกระจายงานโปรแกรมไปยังกระบวนการต่างๆ เพื่อปรับปรุงการดำเนินการ ประสิทธิภาพของโปรแกรม ด้านล่าง เราจะใช้ตัวอย่างนี้แนะนำการใช้โมดูล cluster :
const http = need('http');
const คลัสเตอร์ = ต้องการ ('คลัสเตอร์');
const numCPUs = ต้องการ ('os'). cpus (). ความยาว;
if (Cluster.isprimary) {
สำหรับ (ให้ i = 0; i < numCPUs; i++) {
cluster.fork ();
-
} อื่น {
http.createServer((req, res) => {
Res.writehead (200);
res.end(`${process.pid}n`);
}).ฟัง(8000);
} ตัวอย่างข้างต้นแบ่งออกเป็นสองส่วนตามการตัดสินของ cluster.isPrimary แอตทริบิวต์ (นั่นคือการตัดสินว่ากระบวนการปัจจุบันเป็นกระบวนการหลัก):
8000cluster.forkเรียกใช้ตัวอย่างด้านบนและเข้าถึง http://localhost:8000/ pid เบราว์เซอร์ กลยุทธ์การทำโหลดบาลานซ์เริ่มต้นที่ Node.js นำมาใช้คือการตั้งเวลาแบบ Round-robin ซึ่งสามารถแก้ไขได้ผ่านตัวแปรสภาพแวดล้อม NODE_CLUSTER_SCHED_POLICY หรือคุณสมบัติ cluster.schedulingPolicy :
NODE_CLUSTER_SCHED_POLICY = rr // หรือไม่มีเลย คลัสเตอร์.schedulingPolicy =คลัสเตอร์.SCHED_RR; // หรือคลัสเตอร์.SCHED_NONE
อีกสิ่งหนึ่งที่ควรทราบก็คือแม้ว่าแต่ละกระบวนการย่อยจะสร้างเซิร์ฟเวอร์ HTTP และฟังพอร์ตเดียวกัน แต่ก็ไม่ได้หมายความว่ากระบวนการย่อยเหล่านี้มีอิสระที่จะแข่งขัน คำขอของผู้ใช้ เนื่องจากไม่สามารถรับประกันได้ว่าโหลดของกระบวนการลูกทั้งหมดจะสมดุล ดังนั้นกระบวนการที่ถูกต้องควรเป็นกระบวนการหลักในการฟังพอร์ตจากนั้นส่งต่อคำขอของผู้ใช้ไปยังกระบวนการย่อยเฉพาะสำหรับการประมวลผลตามนโยบายการแจกจ่าย
เนื่องจากกระบวนการถูกแยกออกจากกัน โดยทั่วไปกระบวนการจะสื่อสารผ่านกลไกต่างๆ เช่น หน่วยความจำที่ใช้ร่วมกัน การส่งข้อความ และไปป์ node.js เสร็จสิ้นการสื่อสารระหว่างกระบวนการผู้ปกครองและเด็กผ่าน消息传递เช่นตัวอย่างต่อไปนี้:
const http = require ('http');
const คลัสเตอร์ = ต้องการ ('คลัสเตอร์');
const numCPUs = ต้องการ ('os'). cpus (). ความยาว;
ถ้า (cluster.isPrimary) {
สำหรับ (ให้ i = 0; i < numCPUs; i++) {
ผู้ปฏิบัติงาน const = คลัสเตอร์.ส้อม ();
Worker.on ('ข้อความ', (ข้อความ) => {
console.log(`ฉันเป็นคนหลัก(${process.pid}) ฉันได้รับข้อความจากคนงาน: "${message}"`);
worker.send(`Send message to worker`)
-
-
} อื่น {
process.on ('ข้อความ', (ข้อความ) => {
console.log(`ฉันเป็นคนทำงาน(${process.pid}) ฉันได้รับข้อความจากผู้หลัก: "${message}"`)
-
http.createServer((req, res) => {
res.writeHead(200);
res.end(`${process.pid}n`);
process.send('ส่งข้อความถึงประถม');
}). ฟัง (8000);
} เรียกใช้ตัวอย่างข้างต้นและไปที่ http://localhost:8000/ จากนั้นตรวจสอบเทอร์มินัล เราจะเห็นผลลัพธ์ที่คล้ายกับข้อความต่อไปนี้:
I am primary (44460) ฉันได้รับข้อความจากผู้ปฏิบัติงาน: "Send message to primary" ฉันเป็นคนทำงาน (44461) ฉันได้รับข้อความจากเจ้าหน้าที่หลัก: "ส่งข้อความถึงพนักงาน" ฉันเป็นหลัก (44460) ฉันได้รับข้อความจากคนงาน: "ส่งข้อความถึงหลัก" ฉันเป็นคนงาน (44462) ฉันได้รับข้อความจากหน่วยงานหลัก: "ส่งข้อความถึงพนักงาน"
การใช้กลไกนี้ทำให้เราสามารถตรวจสอบสถานะของกระบวนการย่อยแต่ละกระบวนการได้ เพื่อว่าเมื่อเกิดอุบัติเหตุในกระบวนการย่อย เราก็สามารถเข้าไปแทรกแซงได้ทันเวลา เพื่อให้แน่ใจว่ามีการให้บริการ
อินเทอร์เฟซของโมดูล cluster นั้นเรียบง่ายมาก เพื่อประหยัดพื้นที่ เราจะสร้างคำสั่งพิเศษบางอย่างเกี่ยวกับวิธีคลัสเตอร์ cluster.setupPrimary เท่านั้น สำหรับวิธีอื่น โปรดตรวจสอบเอกสารประกอบอย่างเป็นทางการ:
cluster.setupPrimary การตั้งค่าที่เกี่ยวข้อง จะถูกซิงโครไนซ์กับ cluster.settings และทุกๆ การเรียกแต่ละครั้งจะขึ้นอยู่กับค่าของแอ็ cluster.settings คลัสเตอร์ปัจจุบันcluster.setupPrimary แล้ว จะไม่มีผลกระทบต่อกระบวนการลูกที่กำลังรันอยู่ แต่จะมีเพียงการเรียก cluster.fork ที่ตามมาเท่านั้น ได้รับผลกระทบcluster.setupPrimary จะไม่ส่งผลต่อการส่งผ่านไปยัง cluster.fork fork ในภายหลัง พารามิเตอร์ env ของการเรียกคลัสเตอร์.cluster.setupPrimary สามารถใช้ได้เฉพาะในกระบวนการหลักเท่านั้นเราแนะนำโมดูล cluster ก่อนหน้า cluster ซึ่งเราสามารถสร้างคลัสเตอร์กระบวนการ Node.js เพื่อปรับปรุงประสิทธิภาพการทำงานของโปรแกรม ของทรัพยากรระหว่างกระบวนการ เพื่อแก้ไขปัญหาดังกล่าว Node.js ได้จัดเตรียม worker_threads ด้านล่างนี้เราจะแนะนำการใช้โมดูลนี้โดยย่อผ่านตัวอย่างเฉพาะ:
// server.js
const http = ต้องการ ('http');
const {คนงาน} = ต้องการ ('worker_threads');
http.createserver ((req, res) => {
const httpWorker = ผู้ปฏิบัติงานใหม่ ('./http_worker.js');
httpworker.on ('ข้อความ', (ผลลัพธ์) => {
res.writeHead(200);
res.end(`${ผล}n`);
-
httpworker.postMessage ('TOM');
}).ฟัง(8000);
// http_worker.js
const { parentPort } = ต้องการ ('worker_threads');
parentport.on ('ข้อความ', (ชื่อ) => {
parentport.postMessage (`welcone $ {ชื่อ}!`);
}); ตัวอย่างข้างต้นแสดงการใช้งานแบบง่ายของ worker_threads เมื่อใช้ worker_threads คุณต้องใส่ใจกับประเด็นต่อไปนี้:
สร้างอินสแตนซ์ Worker ผ่าน worker_threads.Worker โดยที่สคริปต์ Worker อาจเป็นไฟล์ JavaScript อิสระหรือ字符串ก็ได้ ตัวอย่างเช่น ตัวอย่างข้างต้นสามารถแก้ไขได้เป็น:
const code = "const { parentPort } = need('worker_threads'); parentPort.on('message', (name) => {parentPort.postMessage(`Welcone ${ ชื่อ}!` );})";
const httpWorker = new Worker(code, { eval: true });เมื่อสร้างอินสแตนซ์ Worker ผ่าน worker_threads.Worker คุณสามารถตั้งค่าเมตาดาต้าเริ่มต้นของเธรดย่อย Worker ได้โดยระบุค่าของ workerData เช่น:
// server .js
const { ผู้ปฏิบัติงาน } = ต้องการ ('worker_threads');
const httpWorker = ผู้ปฏิบัติงานใหม่ ('./http_worker.js', { workerData: { ชื่อ: 'Tom'} });
// http_worker.js
const {workerData} = ต้องการ ('worker_threads');
console.log (WorkerData
worker_threads.Worker SHARE_ENV
ต้องการ('worker_threads ');
ผู้ปฏิบัติงาน const = ผู้ปฏิบัติงานใหม่ ('process.env.SET_IN_WORKER = "foo"', { eval: true, env: SHARE_ENV });
worker.on('ออก', () => {
console.log(process.env.SET_IN_WORKER);
}worker_threads cluster
message parentPort.postMessage เหตุการณ์ message parentPortpostMessage httpWorker httpWorker โดยการฟังเหตุการณ์ message ของ httpWorkerใน Node.js ไม่ว่าจะเป็นกระบวนการลูกที่สร้างโดย cluster หรือเธรดลูกของผู้ปฏิบัติงานที่สร้างโดย worker_threads พวกเขาทั้งหมดมีอินสแตนซ์ V8 และลูปเหตุการณ์ของตัวเอง ความแตกต่างคือ
แม้ว่าดูเหมือนว่าผู้ทำงานย่อยของคนงานจะมีประสิทธิภาพมากกว่ากระบวนการเด็ก แต่คนงานย่อยของคนงานก็มีข้อบกพร่องนั่นคือ cluster ให้การปรับสมดุลโหลดในขณะที่ worker_threads ต้องการให้เราทำการออกแบบและการดำเนินการโหลดบาลานซ์ด้วยตัวเอง
บทความนี้แนะนำการใช้สามโมดูล child_process cluster และ worker_threads ใน Node.js เราสามารถใช้ประโยชน์จากข้อดีของ CPU แบบมัลติคอร์ได้อย่างเต็มที่ และแก้ไขปัญหาพิเศษบางอย่างในแบบมัลติเธรดได้อย่างมีประสิทธิภาพ ( โหมดเธรด) ประสิทธิภาพการทำงานของงาน (เช่น AI, การประมวลผลภาพ ฯลฯ ) แต่ละโมดูลมีสถานการณ์ที่เกี่ยวข้อง บทความนี้จะอธิบายเฉพาะการใช้งานขั้นพื้นฐานเท่านั้น ในที่สุดหากมีข้อผิดพลาดใด ๆ ในบทความนี้ฉันหวังว่าคุณจะแก้ไขได้