SOLFIND
Web Lens
Portal home

Cluster | Node.js v22.23.2 Documentation

https://nodejs.org/docs/latest-v22.x/api/cluster.html • 93 KB fetched
Open original page


Cluster | Node.js v22.23.2 Documentation Skip to content Node.js * About this documentation * Usage and example * Assertion testing * Asynchronous context tracking * Async hooks * Buffer * C++ addons * C/C++ addons with Node-API * C++ embedder API * Child processes * Cluster * Command-line options * Console * Crypto * Debugger * Deprecated APIs * Diagnostics Channel * DNS * Domain * Environment Variables * Errors * Events * File system * Globals * HTTP * HTTP/2 * HTTPS * Inspector * Internationalization * Modules: CommonJS modules * Modules: ECMAScript modules * Modules: node:module API * Modules: Packages * Modules: TypeScript * Net * OS * Path * Performance hooks * Permissions * Process * Punycode * Query strings * Readline * REPL * Report * Single executable applications * SQLite * Stream * String decoder * Test runner * Timers * TLS/SSL * Trace events * TTY * UDP/datagram * URL * Utilities * V8 * VM * WASI * Web Crypto API * Web Streams API * Worker threads * Zlib * Code repository and issue tracker Node.js v22.23.2 documentation * Node.js v22.23.2 * Table of contents * Cluster * How it works * Class: Worker * Event: 'disconnect' * Event: 'error' * Event: 'exit' * Event: 'listening' * Event: 'message' * Event: 'online' * worker.disconnect() * worker.exitedAfterDisconnect * worker.id * worker.isConnected() * worker.isDead() * worker.kill([signal]) * worker.process * worker.send(message[, sendHandle[, options]][, callback]) * Event: 'disconnect' * Event: 'exit' * Event: 'fork' * Event: 'listening' * Event: 'message' * Event: 'online' * Event: 'setup' * cluster.disconnect([callback]) * cluster.fork([env]) * cluster.isMaster * cluster.isPrimary * cluster.isWorker * cluster.schedulingPolicy * cluster.settings * cluster.setupMaster([settings]) * cluster.setupPrimary([settings]) * cluster.worker * cluster.workers * Index * About this documentation * Usage and example * Index * Assertion testing * Asynchronous context tracking * Async hooks * Buffer * C++ addons * C/C++ addons with Node-API * C++ embedder API * Child processes * Cluster * Command-line options * Console * Crypto * Debugger * Deprecated APIs * Diagnostics Channel * DNS * Domain * Environment Variables * Errors * Events * File system * Globals * HTTP * HTTP/2 * HTTPS * Inspector * Internationalization * Modules: CommonJS modules * Modules: ECMAScript modules * Modules: node:module API * Modules: Packages * Modules: TypeScript * Net * OS * Path * Performance hooks * Permissions * Process * Punycode * Query strings * Readline * REPL * Report * Single executable applications * SQLite * Stream * String decoder * Test runner * Timers * TLS/SSL * Trace events * TTY * UDP/datagram * URL * Utilities * V8 * VM * WASI * Web Crypto API * Web Streams API * Worker threads * Zlib * Code repository and issue tracker * Other versions * 26.x * 25.x * 24.x LTS * 23.x * 22.x LTS * 21.x * 20.x * 19.x * 18.x * 17.x * 16.x * 15.x * 14.x * 13.x * 12.x * 11.x * 10.x * 9.x * 8.x * 7.x * 6.x * 5.x * 4.x * 0.12.x * 0.10.x * Options * View on single page * View as JSON * Edit on GitHub Table of contents * Cluster * How it works * Class: Worker * Event: 'disconnect' * Event: 'error' * Event: 'exit' * Event: 'listening' * Event: 'message' * Event: 'online' * worker.disconnect() * worker.exitedAfterDisconnect * worker.id * worker.isConnected() * worker.isDead() * worker.kill([signal]) * worker.process * worker.send(message[, sendHandle[, options]][, callback]) * Event: 'disconnect' * Event: 'exit' * Event: 'fork' * Event: 'listening' * Event: 'message' * Event: 'online' * Event: 'setup' * cluster.disconnect([callback]) * cluster.fork([env]) * cluster.isMaster * cluster.isPrimary * cluster.isWorker * cluster.schedulingPolicy * cluster.settings * cluster.setupMaster([settings]) * cluster.setupPrimary([settings]) * cluster.worker * cluster.workers Cluster # Stability: 2 - Stable Source Code: lib/cluster.js Clusters of Node.js processes can be used to run multiple instances of Node.js that can distribute workloads among their application threads. When process isolation is not needed, use the worker_threads module instead, which allows running multiple application threads within a single Node.js instance. The cluster module allows easy creation of child processes that all share server ports. import cluster from 'node:cluster' ; import http from 'node:http' ; import { availableParallelism } from 'node:os' ; import process from 'node:process' ; const numCPUs = availableParallelism (); if (cluster. isPrimary ) { console . log ( `Primary ${process.pid} is running` ); // Fork workers. for ( let i = 0 ; i < numCPUs; i++) { cluster. fork (); } cluster. on ( 'exit' , ( worker, code, signal ) => { console . log ( `worker ${worker.process.pid} died` ); }); } else { // Workers can share any TCP connection // In this case it is an HTTP server http. createServer ( ( req, res ) => { res. writeHead ( 200 ); res. end ( 'hello world\n' ); }). listen ( 8000 ); console . log ( `Worker ${process.pid} started` ); } const cluster = require ( 'node:cluster' ); const http = require ( 'node:http' ); const numCPUs = require ( 'node:os' ). availableParallelism (); const process = require ( 'node:process' ); if (cluster. isPrimary ) { console . log ( `Primary ${process.pid} is running` ); // Fork workers. for ( let i = 0 ; i < numCPUs; i++) { cluster. fork (); } cluster. on ( 'exit' , ( worker, code, signal ) => { console . log ( `worker ${worker.process.pid} died` ); }); } else { // Workers can share any TCP connection // In this case it is an HTTP server http. createServer ( ( req, res ) => { res. writeHead ( 200 ); res. end ( 'hello world\n' ); }). listen ( 8000 ); console . log ( `Worker ${process.pid} started` ); } copy Running Node.js will now share port 8000 between the workers: $ node server.js Primary 3596 is running Worker 4324 started Worker 4520 started Worker 6056 started Worker 5644 started copy On Windows, it is not yet possible to set up a named pipe server in a worker. How it works # The worker processes are spawned using the child_process.fork() method, so that they can communicate with the parent via IPC and pass server handles back and forth. The cluster module supports two methods of distributing incoming connections. The first one (and the default one on all platforms except Windows) is the round-robin approach, where the primary process listens on a port, accepts new connections and distributes them across the workers in a round-robin fashion, with some built-in smarts to avoid overloading a worker process. The second approach is where the primary process creates the listen socket and sends it to interested workers. The workers then accept incoming connections directly. The second approach should, in theory, give the best performance. In practice however, distribution tends to be very unbalanced due to operating system scheduler vagaries. Loads have been observed where over 70% of all connections ended up in just two processes, out of a total of eight. Because server.listen() hands off most of the work to the primary process, there are three cases where the behavior between a normal Node.js process and a cluster worker differs: * server.listen({fd: 7}) Because the message is passed to the primary, file descriptor 7 in the parent 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. * server.listen(handle) Listening on handles explicitly will cause the worker to use the supplied handle, rather than talk to the primary process. * server.listen(0) 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 listen(0) . In essence, the port is random the first time, but predictable thereafter. To listen on a unique port, generate a port number based on the cluster worker ID. Node.js does not provide routing logic. It is therefore important to design an application such that it does not rely too heavily on in-memory data objects for things like sessions and login. Because workers are all separate processes, they can be killed or re-spawned depending on a program's needs, without affecting other workers. As long as there are some workers still alive, the server will continue to accept connections. If no workers are alive, existing connections will be dropped and new connections will be refused. Node.js does not automatically manage the number of workers, however. It is the application's responsibility to manage the worker pool based on its own needs. Although a primary use case for the node:cluster module is networking, it can also be used for other use cases requiring worker processes. Class: Worker # Added in: v0.7.0 * Extends: <EventEmitter> A Worker object contains all public information and method about a worker. In the primary it can be obtained using cluster.workers . In a worker it can be obtained using cluster.worker . Event: 'disconnect' # Added in: v0.7.7 Similar to the cluster.on('disconnect') event, but specific to this worker. cluster. fork (). on ( 'disconnect' , () => { // Worker has disconnected }); copy Event: 'error' # Added in: v0.7.3 This event is the same as the one provided by child_process.fork() . Within a worker, process.on('error') may also be used. Event: 'exit' # Added in: v0.11.2 * code <number> The exit code, if it exited normally. * signal <string> The name of the signal (e.g. 'SIGHUP' ) that caused the process to be killed. Similar to the cluster.on('exit') event, but specific to this worker. import cluster from 'node:cluster' ; if (cluster. isPrimary ) { const worker = cluster. fork (); worker. on ( 'exit' , ( 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!' ); } }); } const cluster = require ( 'node:cluster' ); if (cluster. isPrimary ) { const worker = cluster. fork (); worker. on ( 'exit' , ( 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!' ); } }); } copy Event: 'listening' # Added in: v0.7.0 * address <Object> Similar to the cluster.on('listening') event, but specific to this worker. cluster. fork (). on ( 'listening' , ( address ) => { // Worker is listening }); cluster. fork (). on ( 'listening' , ( address ) => { // Worker is listening }); copy It is not emitted in the worker. Event: 'message' # Added in: v0.7.0 * message <Object> * handle <undefined> | <Object> Similar to the 'message' event of cluster , but specific to this worker. Within a worker, process.on('message') may also be used. See process event: 'message' . Here is an example using the message system. It keeps a count in the primary process of the number of HTTP requests received by the workers: import cluster from 'node:cluster' ; import http from 'node:http' ; import { availableParallelism } from 'node:os' ; import process from 'node:process' ; if (cluster. isPrimary ) { // Keep track of http requests let numReqs = 0 ; setInterval ( () => { console . log ( `numReqs = ${numReqs} ` ); }, 1000 ); // Count requests function messageHandler ( msg ) { if (msg. cmd && msg. cmd === 'notifyRequest' ) { numReqs += 1 ; } } // Start workers and listen for messages containing notifyRequest const numCPUs = availableParallelism (); for ( let i = 0 ; i < numCPUs; i++) { cluster. fork (); } for ( const id in cluster. workers ) { cluster. workers [id]. on ( 'message' , messageHandler); } } else { // Worker processes have a http server. http. Server ( ( req, res ) => { res. writeHead ( 200 ); res. end ( 'hello world\n' ); // Notify primary about the request process. send ({ cmd : 'notifyRequest' }); }). listen ( 8000 ); } const cluster = require ( 'node:cluster' ); const http = require ( 'node:http' ); const numCPUs = require ( 'node:os' ). availableParallelism (); const process = require ( 'node:process' ); if (cluster. isPrimary ) { // Keep track of http requests let numReqs = 0 ; setInterval ( () => { console . log ( `numReqs = ${numReqs} ` ); }, 1000 ); // Count requests function messageHandler ( msg ) { if (msg. cmd && msg. cmd === 'notifyRequest' ) { numReqs += 1 ; } } // Start workers and listen for messages containing notifyRequest for ( let i = 0 ; i < numCPUs; i++) { cluster. fork (); } for ( const id in cluster. workers ) { cluster. workers [id]. on ( 'message' , messageHandler); } } else { // Worker processes have a http server. http. Server ( ( req, res ) => { res. writeHead ( 200 ); res. end ( 'hello world\n' ); // Notify primary about the request process. send ({ cmd : 'notifyRequest' }); }). listen ( 8000 ); } copy Event: 'online' # Added in: v0.7.0 Similar to the cluster.on('online') event, but specific to this worker. cluster. fork (). on ( 'online' , () => { // Worker is online }); copy It is not emitted in the worker. worker.disconnect() # History Version Changes v7.3.0 This method now returns a reference to worker . v0.7.7 Added in: v0.7.7 * Returns: <cluster.Worker> A reference to worker . In a worker, this function will close all servers, wait for the 'close' event on those servers, and then disconnect the IPC channel. In the primary, an internal message is sent to the worker causing it to call .disconnect() on itself. Causes .exitedAfterDisconnect to be set. 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 server.close() , the IPC channel to the worker will close allowing it to die gracefully. The above applies only to server connections, client connections are not automatically closed by workers, and disconnect does not wait for them to close before exiting. In a worker, process.disconnect exists, but it is not this function; it is disconnect() . 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 'disconnect' event has not been emitted after some time. if (cluster. isPrimary ) { const worker = cluster. fork (); let timeout; worker. on ( 'listening' , ( address ) => { worker. send ( 'shutdown' ); worker. disconnect (); timeout = setTimeout ( () => { worker. kill (); }, 2000 ); }); worker. on ( 'disconnect' , () => { clearTimeout (timeout); }); } else if (cluster. isWorker ) { const net = require ( 'node:net' ); const server = net. createServer ( ( socket ) => { // Connections never end }); server. listen ( 8000 ); process. on ( 'message' , ( msg ) => { if (msg === 'shutdown' ) { // Initiate graceful close of any connections to server } }); } copy worker.exitedAfterDisconnect # Added in: v6.0.0 * Type: <boolean> This property is true if the worker exited due to .disconnect() . If the worker exited any other way, it is false . If the worker has not exited, it is undefined . The boolean worker.exitedAfterDisconnect allows distinguishing between voluntary and accidental exit, the primary may choose not to respawn a worker based on this value. cluster. on ( 'exit' , ( worker, code, signal ) => { if (worker. exitedAfterDisconnect === true ) { console . log ( 'Oh, it was just voluntary – no need to worry' ); } }); // kill worker worker. kill (); copy worker.id # Added in: v0.8.0 * Type: <integer> Each new worker is given its own unique id, this id is stored in the id . While a worker is alive, this is the key that indexes it in cluster.workers . worker.isConnected() # Added in: v0.11.14 This function returns true if the worker is connected to its primary via its IPC channel, false otherwise. A worker is connected to its primary after it has been created. It is disconnected after the 'disconnect' event is emitted. worker.isDead() # Added in: v0.11.14 This function returns true if the worker's process has terminated (either because of exiting or being signaled). Otherwise, it returns false . import cluster from 'node:cluster' ; import http from 'node:http' ; import { availableParallelism } from 'node:os' ; import process from 'node:process' ; const numCPUs = availableParallelism (); if (cluster. isPrimary ) { console . log ( `Primary ${process.pid} is running` ); // Fork workers. for ( let i = 0 ; i < numCPUs; i++) { cluster. fork (); } cluster. on ( 'fork' , ( worker ) => { console . log ( 'worker is dead:' , worker. isDead ()); }); cluster. on ( 'exit' , ( worker, code, signal ) => { console . log ( 'worker is dead:' , worker. isDead ()); }); } else { // Workers can share any TCP connection. In this case, it is an HTTP server. http. createServer ( ( req, res ) => { res. writeHead ( 200 ); res. end ( `Current process\n ${process.pid} ` ); process. kill (process. pid ); }). listen ( 8000 ); } const cluster = require ( 'node:cluster' ); const http = require ( 'node:http' ); const numCPUs = require ( 'node:os' ). availableParallelism (); const process = require ( 'node:process' ); if (cluster. isPrimary ) { console . log ( `Primary ${process.pid} is running` ); // Fork workers. for ( let i = 0 ; i < numCPUs; i++) { cluster. fork (); } cluster. on ( 'fork' , ( worker ) => { console . log ( 'worker is dead:' , worker. isDead ()); }); cluster. on ( 'exit' , ( worker, code, signal ) => { c

Links found on this page

  1. Skip to content [direct]
  2. Node.js [direct]
  3. About this documentation [direct]
  4. Usage and example [direct]
  5. Assertion testing [direct]
  6. Asynchronous context tracking [direct]
  7. Async hooks [direct]
  8. Buffer [direct]
  9. C++ addons [direct]
  10. C/C++ addons with Node-API [direct]
  11. C++ embedder API [direct]
  12. Child processes [direct]
  13. Command-line options [direct]
  14. Console [direct]
  15. Crypto [direct]
  16. Debugger [direct]
  17. Deprecated APIs [direct]
  18. Diagnostics Channel [direct]
  19. DNS [direct]
  20. Domain [direct]
  21. Environment Variables [direct]
  22. Errors [direct]
  23. Events [direct]
  24. File system [direct]
  25. Globals [direct]
  26. HTTP [direct]
  27. HTTP/2 [direct]
  28. HTTPS [direct]
  29. Inspector [direct]
  30. Internationalization [direct]
  31. Modules: CommonJS modules [direct]
  32. Modules: ECMAScript modules [direct]
  33. Modules: node:module API [direct]
  34. Modules: Packages [direct]
  35. Modules: TypeScript [direct]
  36. Net [direct]
  37. OS [direct]
  38. Path [direct]
  39. Performance hooks [direct]
  40. Permissions [direct]
  41. Process [direct]
  42. Punycode [direct]
  43. Query strings [direct]
  44. Readline [direct]
  45. REPL [direct]
  46. Report [direct]
  47. Single executable applications [direct]
  48. SQLite [direct]
  49. Stream [direct]
  50. String decoder [direct]
  51. Test runner [direct]
  52. Timers [direct]
  53. TLS/SSL [direct]
  54. Trace events [direct]
  55. TTY [direct]
  56. UDP/datagram [direct]
  57. URL [direct]
  58. Utilities [direct]
  59. V8 [direct]
  60. VM [direct]
  61. WASI [direct]
  62. Web Crypto API [direct]
  63. Web Streams API [direct]
  64. Worker threads [direct]
  65. Zlib [direct]
  66. Code repository and issue tracker [direct]
  67. Index [direct]
  68. 26.x [direct]
  69. 25.x [direct]
  70. 24.x LTS [direct]
  71. 23.x [direct]
  72. 21.x [direct]
  73. 20.x [direct]
  74. 19.x [direct]
  75. 18.x [direct]
  76. 17.x [direct]
  77. 16.x [direct]
  78. 15.x [direct]
  79. 14.x [direct]
  80. 13.x [direct]