Skip to main content
Version: 4.x

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-adapter

Usage#

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#

NameDescriptionDefault value
requestsTimeoutthe timeout for inter-server requests such as fetchSockets() or serverSideEmit() with ack5000