Node.js، خود یک برنامه thread است، بنابراین به خوبی با single processes (یا فرآیندهای مجرد، فرایندهایی هستند که هنگام اجرا، فرایند جدیدی همانند خودش را ایجاد نمیکند) در CPU کار میکند اما یک فرآیند مجرد single process در یک CPU باعث می شوند که زمان بارگذاری سایت (load) افزایش و در نتیجه کارایی کاهش پیدا کند.
هر چقدر هم که سرور ما قوی و پیشرفته باشد باز هم یک فرایند تک نخی یا thread محدودیتهای خاص خودش را دارد و نمیتواند بارگذاری سایت را کنترل کند. علاوه بر این، درست است که node.js یک فرایند تک نخی است اما این به این معنی نیست که نمی تواند از مزیت های فرایندهای چندگانه (multiple process) بیبهره باشد.
ماژول child process در node.js به عنوان یک راه حل برای کمک به ما در زمینه ایجاد زیر فرایندها (sub-processes) یا فرآیندهای فرزند child processes از فرایند مجرد (single process) مورد استفاده قرار میگیرد، این کار باعث میشود که ما به راحتی بتوانیم مسئله بارگذاری سایت (load) را کنترل کنیم.
دقت نمایید که در اینجا فرایند مجرد (single process) که توانسته چند فرایند جدید همانند خودش ایجاد کند، با نام فرایند پدر شناخته می شود و فرایندهای ایجاد شده فرایند فرزند خوانده میشوند. این فرایندهای فرزند میتوانند با استفاده از ارتباط بین فرآیندی (inter process communication ) با همدیگر رابطه برقرار کنند.
دقت کنید که بر طبق گزارش ویکی پدیا، در علوم رایانه، ارتباطات بین پردازشی (به انگلیسی Inter-Process Communication یا IPC)، مجموعهای از روشها برای تبادل اطلاعات بین فرآیندهای فرزند child processes میباشند، و بنابراین هر یک از این روشها میتواند برای ارتباط بین یک یا چند فرآیند بکار میروند. ممکن است این فرآیندها در یک یا چندین رایانه متصل به هم توسط یک شبکه اجرا گردند.
ماژول child_process با اجرای دستور OS در فرآیندهای فرزند، میتواند به ویژگیها و قابلیتهای سیستم عامل دسترسی پیدا کند. دقت کنید که ما میتوانیم جریان ورودی (input stream) و جریان خروجی (output stream) فرایندهای فرزند را به خوبی اداره کنیم.
مفهومی به نام stream در واقع دنبالهای از دادهها با فرمتهای مختلف برای مثال 8 بیتی یا 1 بایتی است که از منبعی خوانده شده یا در آن درج میشود، حالا منظور از input stream دادههایی است که در منبع درج میشوند و منظور از output stream دادههایی است که از منبع خوانده میشوند.
ما همچنین میتوانیم از آرگومانها دستور OS برای کنترل بیشتر فرآیندها نیز، استفاده نماییم. همچنین مؤلفههای ارتباطی (pipes) برایstdin ، stdout و stderr بین گره فرزند و گره پدر ایجاد شده است.
چهار روش مختلف برای ایجاد فرایندهای فرزند Child processes وجود دارد:
فرایندهای فرزند میتوانند به صورت غیر همزمان (Asynchronously) و یا به صورت همزمان (Synchronously) بر اساس الزامات ایجاد شود.
اجازه دهید که برای درک بهتر شما عزیزان، جز به جز هر یک از متدهای ایجاد فرایند را با هم بررسی کنیم.
چهار راه مختلف برای ایجاد فرایندهای فرزند (Child processes) به صورت غیر همزمان وجود دارد:
()child_process.spawn
: این متد فرایند فرزند را به صورت غیرهمزمان و بدون ایجاد توقف در حلقه رویداد node.js ایجاد میکند.()child_process.fork
: این متد برای ایجاد یک فرایند node.js جدید استفاده میشود و همچنین یک متد خاص را فراخوانی میکند که کار این متد خاص فراهم کردن کانال ارتباطات بین پردازشی (که پیشتر آن را توضیح دادم) هست که به ما اجازه ارسال پیام بین فرایند پدر و فرایند فرزند را میدهد.()child_process.exec
: این متد برای تولید کردن یک sell و سپس اجرای دستور در آن sell مورد استفاده قرار میگیرد. این متد همچنین اجاره میدهد، زمانی که اجرای فرآیند تکمیل شد، یک تابع Callback اختیاری فراخوانی شود.()child_process.execFile
: این متد از لحاظ کارایی مشابه متد ()child_process.exec است با این تفاوت که به جای ایجاد یک sell ، این اجازه را میدهد که دستورات به صورت مستقیم و به عنوان یک آرگومان در آن وارد شوند.نکات زیر جهت یادآوری عرض می شود که:
اجازه دهید که با استفاده از مثال، جزییات هر کدام از متدهای غیر همزمان را بیشتر درک کنیم.
1- ()child_process.spawn
همان طور که گفته شد این متد برای ایجاد یک فرایند جدید مورد استفاده قرار میگیرد.
نحوی نوشتن این متد:
child_process.spawn(command[, args][, options])
پارامترها :
مقدار برگشت داده شده توسط این متد child_process.spawn : یک فرآیند فرزند childProcess است.
مثال کد نویسی: ما دو فایل master-spawn.js و slave.js را برای شما در زیر آماده کردهایم.
//Name of the file : slave.js console.log("Child Process number " + process.argv[2] + " is executed." );
//Name of the file : master-spawn.js var cp = require('child_process'); for(var i = 1; i<6; i++) { var worker = cp.spawn('node', ['slave.js', i]); worker.stdout.on('data', function (data) { console.log('Value of Stdout : ' + data); }); worker.stderr.on('data', function (data) { console.log('stderr: ' + data); }); worker.on('close', function (code) { //console.log("Exit code : " + code); console.log('child process exited with code '); }); }
حالا ما میتوانیم مانند تصویر زیر مثالهای بالا را اجرا نماییم.
2- ()child_process.fork
این متد نیز یک فرآیند جدید را ایجاد میکند به موارد زیر دقت نمایید.
نحوی نوشتن این متد:
child_process.fork(modulePath[, args][, options])
پارامترها:
مقدار برگشت داده شده توسط این متد: یک childProcess است.
مثال کد نویسی: ما دو فایل master-fork.js و slave.js را برای شما در زیر آماده کردهایم.
//Name of the file : slave.js console.log("Child Process number " + process.argv[2] + " is executed." );
//Name of the file : master-fork.js var cp = require('child_process'); for(var i=1; i<6; i++) { var worker = cp.fork("slave.js", [i]); worker.on('close', function (code) { console.log('child process exited with code ' + code); }); }
حالا ما میتوانیم مانند تصویر زیر مثالهای بالا را اجرا نماییم.
3- ()child_process.exec :
این متد نیز یک فرآیند جدید را ایجاد میکند به موارد زیر دقت نمایید.
نحوی نوشتن این متد:
child_process.exec(command[, options][, callback])
پارامترها:
callback :
مقدار برگشت داده شده توسط این متد: یک childProcess است.
مثال کد نویسی: ما دو فایل master-exec.js و slave.js را برای شما در زیر آماده کردهایم.
//Name of the file : slave.js console.log("Child Process number " + process.argv[2] + " is executed." );
// Name of the file : master-exec.js var cp = require('child_process'); for(var i=1; i<6; i++) { var workerProcess = cp.exec('node slave.js ' + i , function(error, stdout, stderr) { if (error) { console.log(error.stack); console.log('Error Code: '+error.code); console.log('Error Signal: '+error.signal); } if(stderr){ console.log('value of stderr: ' + stderr); } console.log('Value of stdout: ' + stdout); }); workerProcess.on('exit', function (code) { //console.log("exit code : "+ code); console.log('Child process exited '); }); }
حالا ما میتوانیم مانند تصویر زیر مثالهای بالا را اجرا نماییم.
4- ()child_process.execFile :
این متد نیز یک فرآیند جدید را ایجاد میکند به موارد زیر دقت نمایید.
نحوی نوشتن این متد:
child_process.execFile(file[, args][, options][, callback])
پارامترها:
callback :
مقدار برگشت داده شده توسط این متد: یک childProcess است.
مثال کد نویسی: در پایین، یک قطعه کد ساده را مشاهده کنید که با استفاده از متد execFile، برای شما نسخهی node.js نصب شده بر روی سیستم تان را به نمایش در میآورد.
var ef = require('child_process').execFile; var child = ef('node', ['--version'], (err, stdout, stderr) => { if (err) { console.log('stderr', stderr); throw err; } console.log('Node.js version : ', stdout); });
در اینجا ما برای شما سه راه مختلف ایجاد فرایندهای فرزند (child processes) به صورت همزمان (Synchronously) را آوردهایم:
()spawnSync
:این متد برای شما فرایند فرزند را به صورت همزمان ایجاد میکند اما باید دقت کنید که برای انجام این کار، event loop (حلقه رویداد) برنامه node.js را متوقف میکند.()execSync
: این متد همانند متد child_process.exec() هست با این تفاوت که به صورت همزمان اجرا می شود، بنابراین event loop (حلقه رویداد) برنامه node.js را متوقف میکند و باعث توقف در اجرای هر کد دیگری میشود.()execFileSync
: این متد همانند متد child_process.execFile() هست با این تفاوت که به صورت همزمان اجرا میشود، بنابراین event loop (حلقه رویداد) برنامه node.js را متوقف میکند و باعث توقف در اجرای هر کد دیگری میشود.رویدادهایی که هنگام کار با فرآیندهای فرزند روی می دهند، عبارتاند از:
Message
: این رویداد هنگامی رخ میدهد که یک فرایند فرزند (child process) از متد ()process.send برای ارسال پیامها از طریق ارتباط IPC ( ارتباط بین فرآیندی inter process communication ) استفاده میکند.exit
: این رویداد زمانی روی میدهد که فرآیندهای فرزند خاتمه پیدا کنند.error
: رویداد error در 3 حالت زیر ممکن است روی دهد:1- وقتی که فرآیند فرزند نمیتواند ایجاد شود.
2- وقتی که فرایند فرزند خاتمه نمییابد
3- زمانی که ارتباط با فرآیند فرزند امکانپذیر نباشد.
disconnect
: زمانی روی میدهد که فرایند پدر متد process.disconnect() یا متد subprocess.disconnect() را فراخوانی میکند. دقت نمایید اگر رویداد disconnect به وقوع بپیوندد دیگر نمیتوان از ارتباط IPC استفاده کرد.close
: زمانی روی میدهد که فرایند فرزند، stdio streams را مسدود میکند.در درس 24ام از سلسله دروس 30 روز با نود جی اس، اطلاعات زیادی در مورد فرآیندهای فرزند child processes را با همدیگر یاد گرفتیم. همچنین آموختیم که چگونه این فرآیندهای فرزند را میتوان به صورت همزمان و غیر همزمان ساخت.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.