node.jsexpresssocket.ionode-worker-threads

How to use socket.io with node.js worker_threads


Currently I am introducing worker_threads to a game I am developing. Thea idea is to have each game room in a separate thread, so that they can be processed in parallel (yeah I know that will only really happen if there isn't more threads than cores).

However, I cannot get socket.io to work with worker_threads. So far I have tried the following:

1. Create the socket.io server within the server:

server.js

const { Worker, isMainThread } = require("worker_threads");

const express = require("express");
const app = express();
app.use(express.static(__dirname));

app.post("/newGame", (request, response) => {
  let roomCode = request.query.room_code;
  const worker = new Worker("./server-worker.js", {
    workerData: {
      roomCode: roomCode
    },
  });
});

app.listen(8080, () => {
  console.info("Server started on http://localhost:8080");
});

server-worker.js

const { parentPort, workerData, threadId } = require("worker_threads");


const server = require("http").createServer();
const io = require("socket.io")(server);

server.listen(8080, () => {
  console.info("Server socket.io on port 8080");
});

io.on("connection", (socket) => {
  console.log(`Client with ID ${socket.id} connected to thread with ID ${threadID}`);
});

This results in the browser logging this: GET http://localhost:8080/socket.io/?EIO=3&transport=polling&t= 404 (Not Found)

Also even if I got Express to forward the polling request to the worker I am guessing that I would not be able to open more than one room since the port would already be in use.

2. Create socket.io instance in main thread and pass it on

server.js

const { Worker, isMainThread } = require("worker_threads");

const express = require("express");
const app = express();
app.use(express.static(__dirname));

const server = require("http").createServer(app);
const io = require("socket.io")(server);

app.post("/newGame", (request, response) => {
  let roomCode = request.query.room_code;
  const worker = new Worker("./server-worker.js", {
    workerData: {
      roomCode: roomCode,
      io: io
    },
  });
});

However, this does not work since I get a DataCloneError because worker_threads can only send native objects to workers.

Questions:


Solution

  • Node's worker threads are not suitable for your purpose. They're for doing long-running computations, not handling network connections.

    Also, it probably does not make sense to assign your rooms to particular server resources. Node is good at concurrently handling multiple app contexts and so is socket.io.

    To scale up your app to use more processor cores, node offers clustering. To use a cluster you'll need to sort out session stickiness.