656 lines
27 KiB
HTML
656 lines
27 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>Cluster Node.js v0.8.14 Manual & Documentation</title>
|
||
<link rel="stylesheet" href="assets/style.css">
|
||
<link rel="stylesheet" href="assets/sh.css">
|
||
<link rel="canonical" href="http://nodejs.org/api/cluster.html">
|
||
</head>
|
||
<body class="alt apidoc" id="api-section-cluster">
|
||
<div id="intro" class="interior">
|
||
<a href="/" title="Go back to the home page">
|
||
<img id="logo" src="http://nodejs.org/images/logo-light.png" alt="node.js">
|
||
</a>
|
||
</div>
|
||
<div id="content" class="clearfix">
|
||
<div id="column2" class="interior">
|
||
<ul>
|
||
<li><a href="/" class="home">Home</a></li>
|
||
<li><a href="/download/" class="download">Download</a></li>
|
||
<li><a href="/about/" class="about">About</a></li>
|
||
<li><a href="http://search.npmjs.org/" class="npm">npm Registry</a></li>
|
||
<li><a href="http://nodejs.org/api/" class="docs current">Docs</a></li>
|
||
<li><a href="http://blog.nodejs.org" class="blog">Blog</a></li>
|
||
<li><a href="/community/" class="community">Community</a></li>
|
||
<li><a href="/logos/" class="logos">Logos</a></li>
|
||
<li><a href="http://jobs.nodejs.org/" class="jobs">Jobs</a></li>
|
||
</ul>
|
||
<p class="twitter"><a href="http://twitter.com/nodejs">@nodejs</a></p>
|
||
</div>
|
||
|
||
<div id="column1" class="interior">
|
||
<header>
|
||
<h1>Node.js v0.8.14 Manual & Documentation</h1>
|
||
<div id="gtoc">
|
||
<p>
|
||
<a href="index.html" name="toc">Index</a> |
|
||
<a href="all.html">View on single page</a> |
|
||
<a href="cluster.json">View as JSON</a>
|
||
</p>
|
||
</div>
|
||
<hr>
|
||
</header>
|
||
|
||
<div id="toc">
|
||
<h2>Table of Contents</h2>
|
||
<ul>
|
||
<li><a href="#cluster_cluster">Cluster</a><ul>
|
||
<li><a href="#cluster_how_it_works">How It Works</a></li>
|
||
<li><a href="#cluster_cluster_settings">cluster.settings</a></li>
|
||
<li><a href="#cluster_cluster_ismaster">cluster.isMaster</a></li>
|
||
<li><a href="#cluster_cluster_isworker">cluster.isWorker</a></li>
|
||
<li><a href="#cluster_event_fork">Event: 'fork'</a></li>
|
||
<li><a href="#cluster_event_online">Event: 'online'</a></li>
|
||
<li><a href="#cluster_event_listening">Event: 'listening'</a></li>
|
||
<li><a href="#cluster_event_disconnect">Event: 'disconnect'</a></li>
|
||
<li><a href="#cluster_event_exit">Event: 'exit'</a></li>
|
||
<li><a href="#cluster_event_setup">Event: 'setup'</a></li>
|
||
<li><a href="#cluster_cluster_setupmaster_settings">cluster.setupMaster([settings])</a></li>
|
||
<li><a href="#cluster_cluster_fork_env">cluster.fork([env])</a></li>
|
||
<li><a href="#cluster_cluster_disconnect_callback">cluster.disconnect([callback])</a></li>
|
||
<li><a href="#cluster_cluster_worker">cluster.worker</a></li>
|
||
<li><a href="#cluster_cluster_workers">cluster.workers</a></li>
|
||
<li><a href="#cluster_class_worker">Class: Worker</a><ul>
|
||
<li><a href="#cluster_worker_id">worker.id</a></li>
|
||
<li><a href="#cluster_worker_process">worker.process</a></li>
|
||
<li><a href="#cluster_worker_suicide">worker.suicide</a></li>
|
||
<li><a href="#cluster_worker_send_message_sendhandle">worker.send(message, [sendHandle])</a></li>
|
||
<li><a href="#cluster_worker_destroy">worker.destroy()</a></li>
|
||
<li><a href="#cluster_worker_disconnect">worker.disconnect()</a></li>
|
||
<li><a href="#cluster_event_message">Event: 'message'</a></li>
|
||
<li><a href="#cluster_event_online_1">Event: 'online'</a></li>
|
||
<li><a href="#cluster_event_listening_1">Event: 'listening'</a></li>
|
||
<li><a href="#cluster_event_disconnect_1">Event: 'disconnect'</a></li>
|
||
<li><a href="#cluster_event_exit_1">Event: 'exit'</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
</div>
|
||
|
||
<div id="apicontent">
|
||
<h1>Cluster<span><a class="mark" href="#cluster_cluster" id="cluster_cluster">#</a></span></h1>
|
||
<pre><code>Stability: 1 - Experimental</code></pre>
|
||
<p>A single instance of Node runs in a single thread. To take advantage of
|
||
multi-core systems the user will sometimes want to launch a cluster of Node
|
||
processes to handle the load.
|
||
|
||
</p>
|
||
<p>The cluster module allows you to easily create a network of processes that
|
||
all share server ports.
|
||
|
||
</p>
|
||
<pre><code>var cluster = require('cluster');
|
||
var http = require('http');
|
||
var numCPUs = require('os').cpus().length;
|
||
|
||
if (cluster.isMaster) {
|
||
// Fork workers.
|
||
for (var i = 0; i < numCPUs; i++) {
|
||
cluster.fork();
|
||
}
|
||
|
||
cluster.on('exit', function(worker, code, signal) {
|
||
console.log('worker ' + worker.process.pid + ' died');
|
||
});
|
||
} else {
|
||
// Workers can share any TCP connection
|
||
// In this case its a HTTP server
|
||
http.createServer(function(req, res) {
|
||
res.writeHead(200);
|
||
res.end("hello world\n");
|
||
}).listen(8000);
|
||
}</code></pre>
|
||
<p>Running node will now share port 8000 between the workers:
|
||
|
||
</p>
|
||
<pre><code>% node server.js
|
||
Worker 2438 online
|
||
Worker 2437 online</code></pre>
|
||
<p>This feature was introduced recently, and may change in future versions.
|
||
Please try it out and provide feedback.
|
||
|
||
</p>
|
||
<p>Also note that, on Windows, it is not yet possible to set up a named pipe
|
||
server in a worker.
|
||
|
||
</p>
|
||
<h2>How It Works<span><a class="mark" href="#cluster_how_it_works" id="cluster_how_it_works">#</a></span></h2>
|
||
<!--type=misc-->
|
||
|
||
<p>The worker processes are spawned using the <code>child_process.fork</code> method,
|
||
so that they can communicate with the parent via IPC and pass server
|
||
handles back and forth.
|
||
|
||
</p>
|
||
<p>When you call <code>server.listen(...)</code> in a worker, it serializes the
|
||
arguments and passes the request to the master process. If the master
|
||
process already has a listening server matching the worker's
|
||
requirements, then it passes the handle to the worker. If it does not
|
||
already have a listening server matching that requirement, then it will
|
||
create one, and pass the handle to the child.
|
||
|
||
</p>
|
||
<p>This causes potentially surprising behavior in three edge cases:
|
||
|
||
</p>
|
||
<ol>
|
||
<li><code>server.listen({fd: 7})</code> Because the message is passed to the master,
|
||
file descriptor 7 <strong>in the parent</strong> will be listened on, and the
|
||
handle passed to the worker, rather than listening to the worker's
|
||
idea of what the number 7 file descriptor references.</li>
|
||
<li><code>server.listen(handle)</code> Listening on handles explicitly will cause
|
||
the worker to use the supplied handle, rather than talk to the master
|
||
process. If the worker already has the handle, then it's presumed
|
||
that you know what you are doing.</li>
|
||
<li><code>server.listen(0)</code> Normally, this will cause servers to listen on a
|
||
random port. However, in a cluster, each worker will receive the
|
||
same "random" port each time they do <code>listen(0)</code>. In essence, the
|
||
port is random the first time, but predictable thereafter. If you
|
||
want to listen on a unique port, generate a port number based on the
|
||
cluster worker ID.</li>
|
||
</ol>
|
||
<p>When multiple processes are all <code>accept()</code>ing on the same underlying
|
||
resource, the operating system load-balances across them very
|
||
efficiently. There is no routing logic in Node.js, or in your program,
|
||
and no shared state between the workers. Therefore, it is important to
|
||
design your program such that it does not rely too heavily on in-memory
|
||
data objects for things like sessions and login.
|
||
|
||
</p>
|
||
<p>Because workers are all separate processes, they can be killed or
|
||
re-spawned depending on your program's needs, without affecting other
|
||
workers. As long as there are some workers still alive, the server will
|
||
continue to accept connections. Node does not automatically manage the
|
||
number of workers for you, however. It is your responsibility to manage
|
||
the worker pool for your application's needs.
|
||
|
||
</p>
|
||
<h2>cluster.settings<span><a class="mark" href="#cluster_cluster_settings" id="cluster_cluster_settings">#</a></span></h2>
|
||
<div class="signature"><ul>
|
||
<li><span class="type">Object</span><ul>
|
||
<li><code>exec</code> <span class="type">String</span> file path to worker file. (Default=<code>__filename</code>)</li>
|
||
<li><code>args</code> <span class="type">Array</span> string arguments passed to worker.
|
||
(Default=<code>process.argv.slice(2)</code>)</li>
|
||
<li><code>silent</code> <span class="type">Boolean</span> whether or not to send output to parent's stdio.
|
||
(Default=<code>false</code>)</li>
|
||
</ul>
|
||
</li>
|
||
</div></ul>
|
||
<p>All settings set by the <code>.setupMaster</code> is stored in this settings object.
|
||
This object is not supposed to be change or set manually, by you.
|
||
|
||
</p>
|
||
<h2>cluster.isMaster<span><a class="mark" href="#cluster_cluster_ismaster" id="cluster_cluster_ismaster">#</a></span></h2>
|
||
<div class="signature"><ul>
|
||
<li><span class="type">Boolean</span></li>
|
||
</div></ul>
|
||
<p>True if the process is a master. This is determined
|
||
by the <code>process.env.NODE_UNIQUE_ID</code>. If <code>process.env.NODE_UNIQUE_ID</code> is
|
||
undefined, then <code>isMaster</code> is <code>true</code>.
|
||
|
||
</p>
|
||
<h2>cluster.isWorker<span><a class="mark" href="#cluster_cluster_isworker" id="cluster_cluster_isworker">#</a></span></h2>
|
||
<div class="signature"><ul>
|
||
<li><span class="type">Boolean</span></li>
|
||
</div></ul>
|
||
<p>This boolean flag is true if the process is a worker forked from a master.
|
||
If the <code>process.env.NODE_UNIQUE_ID</code> is set to a value, then
|
||
<code>isWorker</code> is <code>true</code>.
|
||
|
||
</p>
|
||
<h2>Event: 'fork'<span><a class="mark" href="#cluster_event_fork" id="cluster_event_fork">#</a></span></h2>
|
||
<div class="signature"><ul>
|
||
<li><code>worker</code> <span class="type">Worker object</span></li>
|
||
</div></ul>
|
||
<p>When a new worker is forked the cluster module will emit a 'fork' event.
|
||
This can be used to log worker activity, and create you own timeout.
|
||
|
||
</p>
|
||
<pre><code>var timeouts = [];
|
||
function errorMsg() {
|
||
console.error("Something must be wrong with the connection ...");
|
||
}
|
||
|
||
cluster.on('fork', function(worker) {
|
||
timeouts[worker.id] = setTimeout(errorMsg, 2000);
|
||
});
|
||
cluster.on('listening', function(worker, address) {
|
||
clearTimeout(timeouts[worker.id]);
|
||
});
|
||
cluster.on('exit', function(worker, code, signal) {
|
||
clearTimeout(timeouts[worker.id]);
|
||
errorMsg();
|
||
});</code></pre>
|
||
<h2>Event: 'online'<span><a class="mark" href="#cluster_event_online" id="cluster_event_online">#</a></span></h2>
|
||
<div class="signature"><ul>
|
||
<li><code>worker</code> <span class="type">Worker object</span></li>
|
||
</div></ul>
|
||
<p>After forking a new worker, the worker should respond with a online message.
|
||
When the master receives a online message it will emit such event.
|
||
The difference between 'fork' and 'online' is that fork is emitted when the
|
||
master tries to fork a worker, and 'online' is emitted when the worker is
|
||
being executed.
|
||
|
||
</p>
|
||
<pre><code>cluster.on('online', function(worker) {
|
||
console.log("Yay, the worker responded after it was forked");
|
||
});</code></pre>
|
||
<h2>Event: 'listening'<span><a class="mark" href="#cluster_event_listening" id="cluster_event_listening">#</a></span></h2>
|
||
<div class="signature"><ul>
|
||
<li><code>worker</code> <span class="type">Worker object</span></li>
|
||
<li><code>address</code> <span class="type">Object</span></li>
|
||
</div></ul>
|
||
<p>When calling <code>listen()</code> from a worker, a 'listening' event is automatically assigned
|
||
to the server instance. When the server is listening a message is send to the master
|
||
where the 'listening' event is emitted.
|
||
|
||
</p>
|
||
<p>The event handler is executed with two arguments, the <code>worker</code> contains the worker
|
||
object and the <code>address</code> object contains the following connection properties:
|
||
<code>address</code>, <code>port</code> and <code>addressType</code>. This is very useful if the worker is listening
|
||
on more than one address.
|
||
|
||
</p>
|
||
<pre><code>cluster.on('listening', function(worker, address) {
|
||
console.log("A worker is now connected to " + address.address + ":" + address.port);
|
||
});</code></pre>
|
||
<h2>Event: 'disconnect'<span><a class="mark" href="#cluster_event_disconnect" id="cluster_event_disconnect">#</a></span></h2>
|
||
<div class="signature"><ul>
|
||
<li><code>worker</code> <span class="type">Worker object</span></li>
|
||
</div></ul>
|
||
<p>When a workers IPC channel has disconnected this event is emitted. This will happen
|
||
when the worker dies, usually after calling <code>.destroy()</code>.
|
||
|
||
</p>
|
||
<p>When calling <code>.disconnect()</code>, there may be a delay between the
|
||
<code>disconnect</code> and <code>exit</code> events. This event can be used to detect if
|
||
the process is stuck in a cleanup or if there are long-living
|
||
connections.
|
||
|
||
</p>
|
||
<pre><code>cluster.on('disconnect', function(worker) {
|
||
console.log('The worker #' + worker.id + ' has disconnected');
|
||
});</code></pre>
|
||
<h2>Event: 'exit'<span><a class="mark" href="#cluster_event_exit" id="cluster_event_exit">#</a></span></h2>
|
||
<div class="signature"><ul>
|
||
<li><code>worker</code> <span class="type">Worker object</span></li>
|
||
<li><code>code</code> <span class="type">Number</span> the exit code, if it exited normally.</li>
|
||
<li><code>signal</code> <span class="type">String</span> the name of the signal (eg. <code>'SIGHUP'</code>) that caused
|
||
the process to be killed.</li>
|
||
</div></ul>
|
||
<p>When any of the workers die the cluster module will emit the 'exit' event.
|
||
This can be used to restart the worker by calling <code>fork()</code> again.
|
||
|
||
</p>
|
||
<pre><code>cluster.on('exit', function(worker, code, signal) {
|
||
var exitCode = worker.process.exitCode;
|
||
console.log('worker ' + worker.process.pid + ' died ('+exitCode+'). restarting...');
|
||
cluster.fork();
|
||
});</code></pre>
|
||
<h2>Event: 'setup'<span><a class="mark" href="#cluster_event_setup" id="cluster_event_setup">#</a></span></h2>
|
||
<div class="signature"><ul>
|
||
<li><code>worker</code> <span class="type">Worker object</span></li>
|
||
</div></ul>
|
||
<p>When the <code>.setupMaster()</code> function has been executed this event emits.
|
||
If <code>.setupMaster()</code> was not executed before <code>fork()</code> this function will
|
||
call <code>.setupMaster()</code> with no arguments.
|
||
|
||
</p>
|
||
<h2>cluster.setupMaster([settings])<span><a class="mark" href="#cluster_cluster_setupmaster_settings" id="cluster_cluster_setupmaster_settings">#</a></span></h2>
|
||
<div class="signature"><ul>
|
||
<li><code>settings</code> <span class="type">Object</span><ul>
|
||
<li><code>exec</code> <span class="type">String</span> file path to worker file. (Default=<code>__filename</code>)</li>
|
||
<li><code>args</code> <span class="type">Array</span> string arguments passed to worker.
|
||
(Default=<code>process.argv.slice(2)</code>)</li>
|
||
<li><code>silent</code> <span class="type">Boolean</span> whether or not to send output to parent's stdio.
|
||
(Default=<code>false</code>)</li>
|
||
</ul>
|
||
</li>
|
||
</div></ul>
|
||
<p><code>setupMaster</code> is used to change the default 'fork' behavior. The new settings
|
||
are effective immediately and permanently, they cannot be changed later on.
|
||
|
||
</p>
|
||
<p>Example:
|
||
|
||
</p>
|
||
<pre><code>var cluster = require("cluster");
|
||
cluster.setupMaster({
|
||
exec : "worker.js",
|
||
args : ["--use", "https"],
|
||
silent : true
|
||
});
|
||
cluster.fork();</code></pre>
|
||
<h2>cluster.fork([env])<span><a class="mark" href="#cluster_cluster_fork_env" id="cluster_cluster_fork_env">#</a></span></h2>
|
||
<div class="signature"><ul>
|
||
<li><code>env</code> <span class="type">Object</span> Key/value pairs to add to child process environment.</li>
|
||
<li>return <span class="type">Worker object</span></li>
|
||
</div></ul>
|
||
<p>Spawn a new worker process. This can only be called from the master process.
|
||
|
||
</p>
|
||
<h2>cluster.disconnect([callback])<span><a class="mark" href="#cluster_cluster_disconnect_callback" id="cluster_cluster_disconnect_callback">#</a></span></h2>
|
||
<div class="signature"><ul>
|
||
<li><code>callback</code> <span class="type">Function</span> called when all workers are disconnected and handlers are closed</li>
|
||
</div></ul>
|
||
<p>When calling this method, all workers will commit a graceful suicide. When they are
|
||
disconnected all internal handlers will be closed, allowing the master process to
|
||
die graceful if no other event is waiting.
|
||
|
||
</p>
|
||
<p>The method takes an optional callback argument which will be called when finished.
|
||
|
||
</p>
|
||
<h2>cluster.worker<span><a class="mark" href="#cluster_cluster_worker" id="cluster_cluster_worker">#</a></span></h2>
|
||
<div class="signature"><ul>
|
||
<li><span class="type">Object</span></li>
|
||
</div></ul>
|
||
<p>A reference to the current worker object. Not available in the master process.
|
||
|
||
</p>
|
||
<pre><code>var cluster = require('cluster');
|
||
|
||
if (cluster.isMaster) {
|
||
console.log('I am master');
|
||
cluster.fork();
|
||
cluster.fork();
|
||
} else if (cluster.isWorker) {
|
||
console.log('I am worker #' + cluster.worker.id);
|
||
}</code></pre>
|
||
<h2>cluster.workers<span><a class="mark" href="#cluster_cluster_workers" id="cluster_cluster_workers">#</a></span></h2>
|
||
<div class="signature"><ul>
|
||
<li><span class="type">Object</span></li>
|
||
</div></ul>
|
||
<p>A hash that stores the active worker objects, keyed by <code>id</code> field. Makes it
|
||
easy to loop through all the workers. It is only available in the master
|
||
process.
|
||
|
||
</p>
|
||
<pre><code>// Go through all workers
|
||
function eachWorker(callback) {
|
||
for (var id in cluster.workers) {
|
||
callback(cluster.workers[id]);
|
||
}
|
||
}
|
||
eachWorker(function(worker) {
|
||
worker.send('big announcement to all workers');
|
||
});</code></pre>
|
||
<p>Should you wish to reference a worker over a communication channel, using
|
||
the worker's unique id is the easiest way to find the worker.
|
||
|
||
</p>
|
||
<pre><code>socket.on('data', function(id) {
|
||
var worker = cluster.workers[id];
|
||
});</code></pre>
|
||
<h2>Class: Worker<span><a class="mark" href="#cluster_class_worker" id="cluster_class_worker">#</a></span></h2>
|
||
<p>A Worker object contains all public information and method about a worker.
|
||
In the master it can be obtained using <code>cluster.workers</code>. In a worker
|
||
it can be obtained using <code>cluster.worker</code>.
|
||
|
||
</p>
|
||
<h3>worker.id<span><a class="mark" href="#cluster_worker_id" id="cluster_worker_id">#</a></span></h3>
|
||
<div class="signature"><ul>
|
||
<li><span class="type">String</span></li>
|
||
</div></ul>
|
||
<p>Each new worker is given its own unique id, this id is stored in the
|
||
<code>id</code>.
|
||
|
||
</p>
|
||
<p>While a worker is alive, this is the key that indexes it in
|
||
cluster.workers
|
||
|
||
</p>
|
||
<h3>worker.process<span><a class="mark" href="#cluster_worker_process" id="cluster_worker_process">#</a></span></h3>
|
||
<div class="signature"><ul>
|
||
<li><span class="type">ChildProcess object</span></li>
|
||
</div></ul>
|
||
<p>All workers are created using <code>child_process.fork()</code>, the returned object
|
||
from this function is stored in process.
|
||
|
||
</p>
|
||
<p>See: <a href="child_process.html">Child Process module</a>
|
||
|
||
</p>
|
||
<h3>worker.suicide<span><a class="mark" href="#cluster_worker_suicide" id="cluster_worker_suicide">#</a></span></h3>
|
||
<div class="signature"><ul>
|
||
<li><span class="type">Boolean</span></li>
|
||
</div></ul>
|
||
<p>This property is a boolean. It is set when a worker dies after calling <code>.destroy()</code>
|
||
or immediately after calling the <code>.disconnect()</code> method. Until then it is <code>undefined</code>.
|
||
|
||
</p>
|
||
<h3>worker.send(message, [sendHandle])<span><a class="mark" href="#cluster_worker_send_message_sendhandle" id="cluster_worker_send_message_sendhandle">#</a></span></h3>
|
||
<div class="signature"><ul>
|
||
<li><code>message</code> <span class="type">Object</span></li>
|
||
<li><code>sendHandle</code> <span class="type">Handle object</span></li>
|
||
</div></ul>
|
||
<p>This function is equal to the send methods provided by
|
||
<code>child_process.fork()</code>. In the master you should use this function to
|
||
send a message to a specific worker. However in a worker you can also use
|
||
<code>process.send(message)</code>, since this is the same function.
|
||
|
||
</p>
|
||
<p>This example will echo back all messages from the master:
|
||
|
||
</p>
|
||
<pre><code>if (cluster.isMaster) {
|
||
var worker = cluster.fork();
|
||
worker.send('hi there');
|
||
|
||
} else if (cluster.isWorker) {
|
||
process.on('message', function(msg) {
|
||
process.send(msg);
|
||
});
|
||
}</code></pre>
|
||
<h3>worker.destroy()<span><a class="mark" href="#cluster_worker_destroy" id="cluster_worker_destroy">#</a></span></h3>
|
||
<p>This function will kill the worker, and inform the master to not spawn a
|
||
new worker. The boolean <code>suicide</code> lets you distinguish between voluntary
|
||
and accidental exit.
|
||
|
||
</p>
|
||
<pre><code>cluster.on('exit', function(worker, code, signal) {
|
||
if (worker.suicide === true) {
|
||
console.log('Oh, it was just suicide\' – no need to worry').
|
||
}
|
||
});
|
||
|
||
// destroy worker
|
||
worker.destroy();</code></pre>
|
||
<h3>worker.disconnect()<span><a class="mark" href="#cluster_worker_disconnect" id="cluster_worker_disconnect">#</a></span></h3>
|
||
<p>When calling this function the worker will no longer accept new connections, but
|
||
they will be handled by any other listening worker. Existing connection will be
|
||
allowed to exit as usual. When no more connections exist, the IPC channel to the worker
|
||
will close allowing it to die graceful. When the IPC channel is closed the <code>disconnect</code>
|
||
event will emit, this is then followed by the <code>exit</code> event, there is emitted when
|
||
the worker finally die.
|
||
|
||
</p>
|
||
<p>Because there might be long living connections, it is useful to implement a timeout.
|
||
This example ask the worker to disconnect and after 2 seconds it will destroy the
|
||
server. An alternative would be to execute <code>worker.destroy()</code> after 2 seconds, but
|
||
that would normally not allow the worker to do any cleanup if needed.
|
||
|
||
</p>
|
||
<pre><code>if (cluster.isMaster) {
|
||
var worker = cluster.fork();
|
||
var timeout;
|
||
|
||
worker.on('listening', function(address) {
|
||
worker.disconnect();
|
||
timeout = setTimeout(function() {
|
||
worker.send('force kill');
|
||
}, 2000);
|
||
});
|
||
|
||
worker.on('disconnect', function() {
|
||
clearTimeout(timeout);
|
||
});
|
||
|
||
} else if (cluster.isWorker) {
|
||
var net = require('net');
|
||
var server = net.createServer(function(socket) {
|
||
// connection never end
|
||
});
|
||
|
||
server.listen(8000);
|
||
|
||
server.on('close', function() {
|
||
// cleanup
|
||
});
|
||
|
||
process.on('message', function(msg) {
|
||
if (msg === 'force kill') {
|
||
server.destroy();
|
||
}
|
||
});
|
||
}</code></pre>
|
||
<h3>Event: 'message'<span><a class="mark" href="#cluster_event_message" id="cluster_event_message">#</a></span></h3>
|
||
<div class="signature"><ul>
|
||
<li><code>message</code> <span class="type">Object</span></li>
|
||
</div></ul>
|
||
<p>This event is the same as the one provided by <code>child_process.fork()</code>.
|
||
In the master you should use this event, however in a worker you can also use
|
||
<code>process.on('message')</code>
|
||
|
||
</p>
|
||
<p>As an example, here is a cluster that keeps count of the number of requests
|
||
in the master process using the message system:
|
||
|
||
</p>
|
||
<pre><code>var cluster = require('cluster');
|
||
var http = require('http');
|
||
|
||
if (cluster.isMaster) {
|
||
|
||
// Keep track of http requests
|
||
var numReqs = 0;
|
||
setInterval(function() {
|
||
console.log("numReqs =", numReqs);
|
||
}, 1000);
|
||
|
||
// Count requestes
|
||
function messageHandler(msg) {
|
||
if (msg.cmd && msg.cmd == 'notifyRequest') {
|
||
numReqs += 1;
|
||
}
|
||
}
|
||
|
||
// Start workers and listen for messages containing notifyRequest
|
||
var numCPUs = require('os').cpus().length;
|
||
for (var i = 0; i < numCPUs; i++) {
|
||
cluster.fork();
|
||
}
|
||
|
||
Object.keys(cluster.workers).forEach(function(id) {
|
||
cluster.workers[id].on('message', messageHandler);
|
||
});
|
||
|
||
} else {
|
||
|
||
// Worker processes have a http server.
|
||
http.Server(function(req, res) {
|
||
res.writeHead(200);
|
||
res.end("hello world\n");
|
||
|
||
// notify master about the request
|
||
process.send({ cmd: 'notifyRequest' });
|
||
}).listen(8000);
|
||
}</code></pre>
|
||
<h3>Event: 'online'<span><a class="mark" href="#cluster_event_online_1" id="cluster_event_online_1">#</a></span></h3>
|
||
<p>Same as the <code>cluster.on('online')</code> event, but emits only when the state change
|
||
on the specified worker.
|
||
|
||
</p>
|
||
<pre><code>cluster.fork().on('online', function() {
|
||
// Worker is online
|
||
};</code></pre>
|
||
<h3>Event: 'listening'<span><a class="mark" href="#cluster_event_listening_1" id="cluster_event_listening_1">#</a></span></h3>
|
||
<div class="signature"><ul>
|
||
<li><code>address</code> <span class="type">Object</span></li>
|
||
</div></ul>
|
||
<p>Same as the <code>cluster.on('listening')</code> event, but emits only when the state change
|
||
on the specified worker.
|
||
|
||
</p>
|
||
<pre><code>cluster.fork().on('listening', function(address) {
|
||
// Worker is listening
|
||
};</code></pre>
|
||
<h3>Event: 'disconnect'<span><a class="mark" href="#cluster_event_disconnect_1" id="cluster_event_disconnect_1">#</a></span></h3>
|
||
<p>Same as the <code>cluster.on('disconnect')</code> event, but emits only when the state change
|
||
on the specified worker.
|
||
|
||
</p>
|
||
<pre><code>cluster.fork().on('disconnect', function() {
|
||
// Worker has disconnected
|
||
};</code></pre>
|
||
<h3>Event: 'exit'<span><a class="mark" href="#cluster_event_exit_1" id="cluster_event_exit_1">#</a></span></h3>
|
||
<div class="signature"><ul>
|
||
<li><code>code</code> <span class="type">Number</span> the exit code, if it exited normally.</li>
|
||
<li><code>signal</code> <span class="type">String</span> the name of the signal (eg. <code>'SIGHUP'</code>) that caused
|
||
the process to be killed.</li>
|
||
</div></ul>
|
||
<p>Emitted by the individual worker instance, when the underlying child process
|
||
is terminated. See <a href="child_process.html#child_process_event_exit">child_process event: 'exit'</a>.
|
||
|
||
</p>
|
||
<pre><code>var worker = cluster.fork();
|
||
worker.on('exit', function(code, signal) {
|
||
if( signal ) {
|
||
console.log("worker was killed by signal: "+signal);
|
||
} else if( code !== 0 ) {
|
||
console.log("worker exited with error code: "+code);
|
||
} else {
|
||
console.log("worker success!");
|
||
}
|
||
};</code></pre>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="footer">
|
||
<ul class="clearfix">
|
||
<li><a href="/">Node.js</a></li>
|
||
<li><a href="/download/">Download</a></li>
|
||
<li><a href="/about/">About</a></li>
|
||
<li><a href="http://search.npmjs.org/">npm Registry</a></li>
|
||
<li><a href="http://nodejs.org/api/">Docs</a></li>
|
||
<li><a href="http://blog.nodejs.org">Blog</a></li>
|
||
<li><a href="/community/">Community</a></li>
|
||
<li><a href="/logos/">Logos</a></li>
|
||
<li><a href="http://jobs.nodejs.org/">Jobs</a></li>
|
||
<li><a href="http://twitter.com/nodejs" class="twitter">@nodejs</a></li>
|
||
</ul>
|
||
|
||
<p>Copyright <a href="http://joyent.com/">Joyent, Inc</a>, Node.js is a <a href="/trademark-policy.pdf">trademark</a> of Joyent, Inc. View <a href="https://raw.github.com/joyent/node/v0.8.14/LICENSE">license</a>.</p>
|
||
</div>
|
||
|
||
<script src="../sh_main.js"></script>
|
||
<script src="../sh_javascript.min.js"></script>
|
||
<script>highlight(undefined, undefined, 'pre');</script>
|
||
<script>
|
||
window._gaq = [['_setAccount', 'UA-10874194-2'], ['_trackPageview']];
|
||
(function(d, t) {
|
||
var g = d.createElement(t),
|
||
s = d.getElementsByTagName(t)[0];
|
||
g.src = '//www.google-analytics.com/ga.js';
|
||
s.parentNode.insertBefore(g, s);
|
||
}(document, 'script'));
|
||
</script>
|
||
</body>
|
||
</html>
|
||
|