Cluster adapter
How it works#
The Cluster adapter allows to use Socket.IO within a Node.js cluster.
Every packet that is sent to multiple clients (e.g. io.to("room1").emit() or socket.broadcast.emit()) is also sent to other workers via the IPC channel.
The source code of this adapter can be found here.
Installation#
npm install @socket.io/cluster-adapterUsage#
With Node.js cluster#
const cluster = require("cluster");const http = require("http");const { Server } = require("socket.io");const numCPUs = require("os").cpus().length;const { setupMaster, setupWorker } = require("@socket.io/sticky");const { createAdapter, setupPrimary } = require("@socket.io/cluster-adapter");
if (cluster.isMaster) { console.log(`Master ${process.pid} is running`);
const httpServer = http.createServer();
// setup sticky sessions setupMaster(httpServer, { loadBalancingMethod: "least-connection", });
// setup connections between the workers setupPrimary();
// needed for packets containing buffers (you can ignore it if you only send plaintext objects) // Node.js < 16.0.0 cluster.setupMaster({ serialization: "advanced", }); // Node.js > 16.0.0 // cluster.setupPrimary({ // serialization: "advanced", // });
httpServer.listen(3000);
for (let i = 0; i < numCPUs; i++) { cluster.fork(); }
cluster.on("exit", (worker) => { console.log(`Worker ${worker.process.pid} died`); cluster.fork(); });} else { console.log(`Worker ${process.pid} started`);
const httpServer = http.createServer(); const io = new Server(httpServer);
// use the cluster adapter io.adapter(createAdapter());
// setup connection with the primary process setupWorker(io);
io.on("connection", (socket) => { /* ... */ });}With PM2#
See the associated documentation.
With recluster#
cluster.js
const cluster = require("cluster");const http = require("http");const { setupMaster } = require("@socket.io/sticky");const { setupPrimary } = require("@socket.io/cluster-adapter");const recluster = require("recluster");const path = require("path");
const httpServer = http.createServer();
// setup sticky sessionssetupMaster(httpServer, { loadBalancingMethod: "least-connection",});
// setup connections between the workerssetupPrimary();
// needed for packets containing buffers (you can ignore it if you only send plaintext objects)// Node.js < 16.0.0cluster.setupMaster({ serialization: "advanced",});// Node.js > 16.0.0// cluster.setupPrimary({// serialization: "advanced",// });
httpServer.listen(3000);
const balancer = recluster(path.join(__dirname, "worker.js"));
balancer.run();worker.js
const http = require("http");const { Server } = require("socket.io");const { setupWorker } = require("@socket.io/sticky");const { createAdapter } = require("@socket.io/cluster-adapter");
const httpServer = http.createServer();const io = new Server(httpServer);
// use the cluster adapterio.adapter(createAdapter());
// setup connection with the primary processsetupWorker(io);
io.on("connection", (socket) => { /* ... */});Options#
| Name | Description | Default value |
|---|---|---|
requestsTimeout | the timeout for inter-server requests such as fetchSockets() or serverSideEmit() with ack | 5000 |