| <!doctype html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8"> |
| <title>Cluster Node.js v0.10.24 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://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.10.24 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_kill_signal_sigterm">worker.kill([signal='SIGTERM'])</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> |
| <li><a href="#cluster_event_error">Event: 'error'</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 class="api_stability_1">Stability: 1 - Experimental</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 child 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_DEBUG=cluster node server.js |
| 23521,Master Worker 23524 online |
| 23521,Master Worker 23526 online |
| 23521,Master Worker 23523 online |
| 23521,Master Worker 23528 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 worker. |
| |
| </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>execArgv</code> <span class="type">Array</span> list of string arguments passed to the node executable. |
| (Default=<code>process.execArgv</code>)</li> |
| <li><code>exec</code> <span class="type">String</span> file path to worker file. (Default=<code>process.argv[1]</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>After calling <code>.setupMaster()</code> (or <code>.fork()</code>) this settings object will contain |
| the settings, including the default values. |
| |
| </p> |
| <p>It is effectively frozen after being set, because <code>.setupMaster()</code> can |
| only be called once. |
| |
| </p> |
| <p>This object is not supposed to be changed 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>True if the process is not a master (it is the negation of <code>cluster.isMaster</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 an online message. |
| When the master receives an online message it will emit this event. |
| The difference between 'fork' and 'online' is that fork is emitted when the |
| master forks a worker, and 'online' is emitted when the worker is running. |
| |
| </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>After calling <code>listen()</code> from a worker, when the 'listening' event is emitted on |
| the server, a listening event will also be emitted on <code>cluster</code> in the master. |
| |
| </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> |
| <p>The <code>addressType</code> is one of: |
| |
| </p> |
| <ul> |
| <li><code>4</code> (TCPv4)</li> |
| <li><code>6</code> (TCPv6)</li> |
| <li><code>-1</code> (unix domain socket)</li> |
| <li><code>"udp4"</code> or <code>"udp6"</code> (UDP v4 or v6)</li> |
| </ul> |
| <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>Emitted after the worker IPC channel has disconnected. This can occur when a |
| worker exits gracefully, is killed, or is disconnected manually (such as with |
| worker.disconnect()). |
| |
| </p> |
| <p>There may be a delay between the <code>disconnect</code> and <code>exit</code> events. These events |
| 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. |
| |
| </p> |
| <p>This can be used to restart the worker by calling <code>.fork()</code> again. |
| |
| </p> |
| <pre><code>cluster.on('exit', function(worker, code, signal) { |
| console.log('worker %d died (%s). restarting...', |
| worker.process.pid, signal || code); |
| cluster.fork(); |
| });</code></pre> |
| <p>See <a href="child_process.html#child_process_event_exit">child_process event: 'exit'</a>. |
| |
| </p> |
| <h2>Event: 'setup'<span><a class="mark" href="#cluster_event_setup" id="cluster_event_setup">#</a></span></h2> |
| <p>Emitted the first time that <code>.setupMaster()</code> is called. |
| |
| </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>process.argv[1]</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. Once called, |
| the settings will be present in <code>cluster.settings</code>. |
| |
| </p> |
| <p>Note that: |
| |
| </p> |
| <ul> |
| <li>Only the first call to <code>.setupMaster()</code> has any effect, subsequent calls are |
| ignored</li> |
| <li>That because of the above, the <em>only</em> attribute of a worker that may be |
| customized per-worker is the <code>env</code> passed to <code>.fork()</code></li> |
| <li><code>.fork()</code> calls <code>.setupMaster()</code> internally to establish the defaults, so to |
| have any effect, <code>.setupMaster()</code> must be called <em>before</em> any calls to |
| <code>.fork()</code></li> |
| </ul> |
| <p>Example: |
| |
| </p> |
| <pre><code>var cluster = require("cluster"); |
| cluster.setupMaster({ |
| exec : "worker.js", |
| args : ["--use", "https"], |
| silent : true |
| }); |
| cluster.fork();</code></pre> |
| <p>This can only be called from the master process. |
| |
| </p> |
| <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 worker process environment.</li> |
| <li>return <span class="type">Worker object</span></li> |
| </div></ul> |
| <p>Spawn a new worker process. |
| |
| </p> |
| <p>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 handles are |
| closed</li> |
| </div></ul> |
| <p>Calls <code>.disconnect()</code> on each worker in <code>cluster.workers</code>. |
| |
| </p> |
| <p>When they are disconnected all internal handles will be closed, allowing the |
| master process to die gracefully if no other event is waiting. |
| |
| </p> |
| <p>The method takes an optional callback argument which will be called when finished. |
| |
| </p> |
| <p>This can only be called from the master process. |
| |
| </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> |
| <p>A worker is removed from cluster.workers just before the <code>'disconnect'</code> or |
| <code>'exit'</code> event is emitted. |
| |
| </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 as <code>.process</code>. In a worker, the global <code>process</code> |
| is stored. |
| |
| </p> |
| <p>See: <a href="child_process.html#child_process_child_process_fork_modulepath_args_options">Child Process module</a> |
| |
| </p> |
| <p>Note that workers will call <code>process.exit(0)</code> if the <code>'disconnect'</code> event occurs |
| on <code>process</code> and <code>.suicide</code> is not <code>true</code>. This protects against accidental |
| disconnection. |
| |
| </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>Set by calling <code>.kill()</code> or <code>.disconnect()</code>, until then it is <code>undefined</code>. |
| |
| </p> |
| <p>The boolean <code>worker.suicide</code> lets you distinguish between voluntary and accidental |
| exit, the master may choose not to respawn a worker based on this value. |
| |
| </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'). |
| } |
| }); |
| |
| // kill worker |
| worker.kill();</code></pre> |
| <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. |
| |
| </p> |
| <p>In a worker you can also use <code>process.send(message)</code>, it 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.kill([signal='SIGTERM'])<span><a class="mark" href="#cluster_worker_kill_signal_sigterm" id="cluster_worker_kill_signal_sigterm">#</a></span></h3> |
| <div class="signature"><ul> |
| <li><code>signal</code> <span class="type">String</span> Name of the kill signal to send to the worker |
| process.</li> |
| </div></ul> |
| <p>This function will kill the worker. In the master, it does this by disconnecting |
| the <code>worker.process</code>, and once disconnected, killing with <code>signal</code>. In the |
| worker, it does it by disconnecting the channel, and then exiting with code <code>0</code>. |
| |
| </p> |
| <p>Causes <code>.suicide</code> to be set. |
| |
| </p> |
| <p>This method is aliased as <code>worker.destroy()</code> for backwards compatibility. |
| |
| </p> |
| <p>Note that in a worker, <code>process.kill()</code> exists, but it is not this function, |
| it is <a href="process.html#process_process_kill_pid_signal">kill</a>. |
| |
| </p> |
| <h3>worker.disconnect()<span><a class="mark" href="#cluster_worker_disconnect" id="cluster_worker_disconnect">#</a></span></h3> |
| <p>In a worker, this function will close all servers, wait for the 'close' event on |
| those servers, and then disconnect the IPC channel. |
| |
| </p> |
| <p>In the master, an internal message is sent to the worker causing it to call |
| <code>.disconnect()</code> on itself. |
| |
| </p> |
| <p>Causes <code>.suicide</code> to be set. |
| |
| </p> |
| <p>Note that after a server is closed, it will no longer accept new connections, |
| but connections may be accepted by any other listening worker. Existing |
| connections will be allowed to close as usual. When no more connections exist, |
| see <a href="net.html#net_event_close">server.close()</a>, the IPC channel to the worker |
| will close allowing it to die gracefully. |
| |
| </p> |
| <p>The above applies <em>only</em> to server connections, client connections are not |
| automatically closed by workers, and disconnect does not wait for them to close |
| before exiting. |
| |
| </p> |
| <p>Note that in a worker, <code>process.disconnect</code> exists, but it is not this function, |
| it is <a href="child_process.html#child_process_child_disconnect">disconnect</a>. |
| |
| </p> |
| <p>Because long living server connections may block workers from disconnecting, it |
| may be useful to send a message, so application specific actions may be taken to |
| close them. It also may be useful to implement a timeout, killing a worker if |
| the <code>disconnect</code> event has not been emitted after some time. |
| |
| </p> |
| <pre><code>if (cluster.isMaster) { |
| var worker = cluster.fork(); |
| var timeout; |
| |
| worker.on('listening', function(address) { |
| worker.send('shutdown'); |
| worker.disconnect(); |
| timeout = setTimeout(function() { |
| worker.kill(); |
| }, 2000); |
| }); |
| |
| worker.on('disconnect', function() { |
| clearTimeout(timeout); |
| }); |
| |
| } else if (cluster.isWorker) { |
| var net = require('net'); |
| var server = net.createServer(function(socket) { |
| // connections never end |
| }); |
| |
| server.listen(8000); |
| |
| process.on('message', function(msg) { |
| if(msg === 'shutdown') { |
| // initiate graceful close of any connections to server |
| } |
| }); |
| }</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>. |
| |
| </p> |
| <p>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>Similar to the <code>cluster.on('online')</code> event, but specific to this worker. |
| |
| </p> |
| <pre><code>cluster.fork().on('online', function() { |
| // Worker is online |
| });</code></pre> |
| <p>It is not emitted in the worker. |
| |
| </p> |
| <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>Similar to the <code>cluster.on('listening')</code> event, but specific to this worker. |
| |
| </p> |
| <pre><code>cluster.fork().on('listening', function(address) { |
| // Worker is listening |
| });</code></pre> |
| <p>It is not emitted in the worker. |
| |
| </p> |
| <h3>Event: 'disconnect'<span><a class="mark" href="#cluster_event_disconnect_1" id="cluster_event_disconnect_1">#</a></span></h3> |
| <p>Similar to the <code>cluster.on('disconnect')</code> event, but specfic to this 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>Similar to the <code>cluster.on('exit')</code> event, but specific to this worker. |
| |
| </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> |
| <h3>Event: 'error'<span><a class="mark" href="#cluster_event_error" id="cluster_event_error">#</a></span></h3> |
| <p>This event is the same as the one provided by <code>child_process.fork()</code>. |
| |
| </p> |
| <p>In a worker you can also use <code>process.on('error')</code>. |
| </p> |
| |
| </div> |
| </div> |
| </div> |
| <div id="footer"> |
| <a href="http://joyent.com" class="joyent-logo">Joyent</a> |
| <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://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.10.24/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> |
| |