Usage with PM2

PM2 is a production process manager for Node.js applications with a built-in load balancer. It allows you to keep applications alive forever, to reload them without downtime and to facilitate common system admin tasks.

You can find its documentation here: https://pm2.keymetrics.io/docs/usage/pm2-doc-single-page/

To scale a Socket.IO server with PM2, there are three solutions:

  • disable HTTP long-polling on the client-side
const socket = io({
  transports: ["websocket"]
});

Though in that case, there will be no fallback to HTTP long-polling if the WebSocket connection cannot be established.

  • use a distinct port for each worker, and a load-balancer like nginx in front of them

  • use @socket.io/pm2

Installation

npm install -g @socket.io/pm2

If pm2 is already installed, you will have to remove it first:

npm remove -g pm2

@socket.io/pm2 can be used as a drop-in replacement for pm2, and supports all the commands of the class pm2 utility.

The only difference comes from this commit.

Usage

worker.js

const { createServer } = require("http");
const { Server } = require("socket.io");
const { createAdapter } = require("@socket.io/cluster-adapter");
const { setupWorker } = require("@socket.io/sticky");

const httpServer = createServer();
const io = new Server(httpServer);

io.adapter(createAdapter());

setupWorker(io);

io.on("connection", (socket) => {
  console.log(`connect ${socket.id}`);
});

ecosystem.config.js

module.exports = {
  apps : [{
    script    : "worker.js",
    instances : "max",
    exec_mode : "cluster"
  }]
}

And then run pm2 start ecosystem.config.js (or pm2 start worker.js -i 0). That’s it! You can now reach the Socket.IO cluster on port 8080.

How it works

When scaling to multiple nodes, there are two things to do:

  • enable sticky sessions, so that the HTTP requests of a Socket.IO session are routed to the same worker
  • use a custom adapter, so that the packets are broadcast to all clients, even if they are connected to another worker

In order to achieve this, @socket.io/pm2 includes two additional packages:

The only difference with pm2 comes from this commit:

  • the God process now creates its own HTTP server and routes the HTTP requests to the right worker
  • the God process also relays the packets between the workers, so that io.emit() correctly reaches all clients

Please note that if you have several hosts each running a PM2 cluster, you will have to use another adapter, like the Redis adapter.

The source code of the fork can be found here. We will try to closely follow the releases of the pm2 package.

© 2014–2021 Automattic
Licensed under the MIT License.
https://socket.io/docs/v4/pm2