I need to understand the concept of handling websockets on multiple instances so that it could be shared across all the instances. For e.g I have three nodes running which is being connected by the load balancer. On receiving the data which needs to be emit on the specific socket. My initial idea was to create a hashmap or json objects to holds the websocket connections. But I realize that this couldn't be done in this way as it will be only specific to its particular instance. If I will receive the data on any of the instances then most of the data will not be going to emit on that websocket connection as it doesn't know on which instance the websocket is created. Is there a good way to handle websocket connections so that it could be shared on all instances. My ideas was to use redis or postgres sql database because they are shared among all the instances.
Also I have tried the postgres solution to store the websocket connection but when I save the connection it says
TypeError: Converting circular structure to JSON
Is there some good solution to handle websocket connections that could be shared among all instances. If database is a good solution how can I resolve
TypeError: Converting circular structure to JSON
I guess the thing you are looking for are Adapters, and it's being documented relatively well in the official socket.io documentation (/v4/adapter/).
When scaling to multiple Socket.IO servers, you will need to replace the default in-memory adapter by another implementation, so the events are properly routed to all clients.
You have several official adapters you can choose from :
Here is an example using the MongoDB Adapter :
npm install @socket.io/mongo-adapter mongodb
const { Server } = require("socket.io");
const { createAdapter } = require("@socket.io/mongo-adapter");
const { MongoClient } = require("mongodb");
// DATABASE CONNECTION
const DB = "mydb";
const COLLECTION = "socket.io-adapter-events";
const mongoClient = new MongoClient("mongodb://localhost:27017/?replicaSet=rs0", {
useUnifiedTopology: true,
});
const io = new Server();
const main = async () => {
await mongoClient.connect();
try {
await mongoClient.db(DB).createCollection(COLLECTION, {
capped: true,
size: 1e6
});
} catch (e) {
// collection already exists
}
const mongoCollection = mongoClient.db(DB).collection(COLLECTION);
// HERE COMES THE IMPORTANT PART :)
// CREATE MONGO DB ADAPTER AND USE IT
io.adapter(createAdapter(mongoCollection));
io.listen(3000);
}
main();
The adapter then will take care of the rest. Every packet that is sent to multiple clients (e.g. io.to("room1").emit() or socket.broadcast.emit()) will be