Node.js , being single threaded itself , works superbly fine with single processes in a CPU but a single process in a single CPU is not enough to handle the increasing load. Limitation of a single threaded process is that no matter how advanced or powerful our server may be , it does have a limit to support load. Moreover, Node.js is single threaded but it does not mean that we can't take the advantage of multiple process.
Node.js's child process
module is the solution with the help of which we can create many sub-processes or child processes of a single process which
can be used to handle the load. These child processes can communicate with each other using inter process communication. child_process
module is also used to access operating system functionalities by running OS commands inside child processes. We can control the input stream as well as the
output stream of the child processes. We can also control the arguments to be passed to underlying OS commands. Also , pipes for stdin
,
stdout
and stderr
are established between the parent and the child node.js process by default. We can stream data through these
pipes in non-blocking way.
There are four different ways for creating child processes :
There are four different ways for creating child processes asynchronously :
child_process.spawn()
: This method spawns the child process asynchronously without blocking the node.js event loop child_process.fork()
: This method is used to spawn a new node.js process and also invokes a specific method which provides
inter-process communciation channel established that allow us to send messages between parent process and child process. child_process.exec()
: This method is used to spawn a shell and then runs the command within that shell. This method also allows
for an optional callback function which will be invoked when the execution of the process is completed. child_process.execFile()
: This method is similar to child_process.exec()
except that it spawns the command directly
instead of spawning a shell. This method also allows for an optional callback which will be invoked when the execution of the process is completed.
Let's understand each method in detail with code example.
child_process.spawn(command[, args][, options])
string
. It specifies the command to run. array
. It specifies ist of string arguments object
.It may contains one or more of the following :
childProcess
master-spawn.js
from which we will access slave.js
file as shown below :
//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 ');
});
}
>node master-spawn.js
Value of Stdout : Child Process number 3 is executed.
Value of Stdout : Child Process number 2 is executed.
child process exited with code
child process exited with code
Value of Stdout : Child Process number 1 is executed.
child process exited with code
Value of Stdout : Child Process number 4 is executed.
child process exited with code
Value of Stdout : Child Process number 5 is executed.
child process exited with code
child_process.fork(modulePath[, args][, options])
string
. It specifies the command to run. array
. It specifies ist of string arguments object
.It may contains one or more of the following :
childProcess
master-fork.js
from which we will access slave.js
file as shown below :
//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);
});
}
>node master-fork.js
Child Process number 3 is executed.
child process exited with code 0
Child Process number 2 is executed.
child process exited with code 0
Child Process number 4 is executed.
child process exited with code 0
Child Process number 5 is executed.
Child Process number 1 is executed.
child process exited with code 0
child process exited with code 0
child_process.exec(command[, options][, callback])
string
. It specifies the command to run. object
.It may contains one or more of the following :
childProcess
master-exec.js
from which we will access slave.js
file as shown below :
//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 ');
});
}
>node master-exec.js
Child process exited
Value of stdout: Child Process number 1 is executed.
Child process exited
Value of stdout: Child Process number 2 is executed.
Child process exited
Value of stdout: Child Process number 5 is executed.
Child process exited
Value of stdout: Child Process number 3 is executed.
Child process exited
Value of stdout: Child Process number 4 is executed.
child_process.execFile(file[, args][, options][, callback])
string
. It specifies the command to run. object
.It may contains one or more of the following :
childProcess
execFile
method is
given below :
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);
});
There are three different ways for creating child processes Synchronously :
child_process.spawnSync()
: This method spawns the child process synchronously and it will block the node.js event loop. child_process.execSync()
: This method is same as child_process.exec()
except that it will run synchronously and it
will block the node.js event loop, pausing the execution of any other code. child_process.execFileSync()
: This method is same as child_process.execFile()
except that it will run synchronously and it
will block the node.js event loop, pausing the execution of any other code.Events emitted while working with child processes are as follows :
Message
: This event is triggered when a child process uses process.send()
method to send messages for
IPC communication. exit
: This event is emitted when the child processes is ended. error
: The error event is emitted when :
disconnect
: This event is emitted when either the parent process calls the process.disconnect()
method or
subprocess.disconnect()
method is called in parent process. Either way, inter-process communication is not possible after once the disconnect
event is emitted. close
: This event is emitted when stdio
streams of the child process is closed.