Node.js provides a specialized form of process spawning called a fork, which is designed to execute Node.js module code inside another V8 instance running on a separate processor. You can use a fork to run multiple services in parallel. However, it takes time to spin up a new instance of V8, and each instance takes about 10MB of memory. Therefore, you should design forked processes to be longer lived, and you shouldn’t require a large number of them. Remember that you really don’t get a performance benefit from creating more processes than you have CPUs in the system.
Unlike spawn
, you cannot configure stdio
for the child process. Instead, you use the send()
mechanism in the ChildProcess
object to communicate between the parent and child processes.
The syntax for the fork()
function, which returns a ChildProcess
object, is shown below:
child_process.fork(modulePath, [args], [options])
The modulePath
parameter is a string that specifies the path to the JavaScript file that is launched by the new Node.js instance. The args
parameter is an array that specifies command-line arguments to be passed to the node
command. The options
parameter is an object that specifies settings to use when executing the command, such as the current working directory. Table 9.9 lists the options you can specify with the fork()
command.
The callback
parameter is a function that accepts three parameters: error
, stdout
, and stderr
. The error
parameter is passed an error object if an error is encountered during execution of the command. stdout
and stderr
are Readable
stream objects.
Listing 9.5 and Listing 9.6 show examples of forking to another Node.js instance running in a separate process. The code in Listing 9.5 uses fork()
to create three child processes that are running the code from Listing 9.6. The parent process then uses the ChildProcess
objects to send commands to the child processes. The code in Listing 9.6 implements the process.on('message')
callback to receive messages from the parent and the process.send()
method to send the response back to the parent process, thus implementing the IPC mechanism between the two. Figure 9.5 shows the output of these listings.
01 var child_process = require('child_process'),
02 var options = {
03 env:{user:'Brad'},
04 encoding:'utf8'
05 };
06 function makeChild(){
07 var child = child_process.fork('chef.js', [], options);
08 child.on('message', function(message) {
09 console.log('Served: ' + message);
10 });
11 return child;
12 }
13 function sendCommand(child, command){
14 console.log("Requesting: " + command);
15 child.send({cmd:command});
16 }
17 var child1 = makeChild();
18 var child2 = makeChild();
19 var child3 = makeChild();
20 sendCommand(child1, "makeBreakfast");
21 sendCommand(child2, "makeLunch");
22 sendCommand(child3, "makeDinner");
01 process.on('message', function(message, parent) {
02 var meal = {};
03 switch (message.cmd){
04 case 'makeBreakfast':
05 meal = ["ham", "eggs", "toast"];
06 break;
07 case 'makeLunch':
08 meal = ["burger", "fries", "shake"];
09 break;
10 case 'makeDinner':
11 meal = ["soup", "salad", "steak"];
12 break;
13 }
14 process.send(meal);
15 });