Scale node.js socket.io with 3 servers - node.js

I know their are a lot of questions and answers about this issue on the net but I can't get it to work.
I have a server written in node.js and listening to connections with socket.io
Now, The sockets can exchange messages between them, like a chat and I'm broadcasting the incoming messages to all other sockets on the server.
I want to run my node server on 3 different servers, each one of them have different IP, Lets call them: SERVER1, SERVER2 and SERVER3.
Here comes my confusion, if i'm sending a message from a socket which connected to SERVER1, How the sockets that connected to SERVER2 and SERVER3 will see this message?
I heard about RedisStore, RabbitMQ and other stuff but i can't find a good article/post/book that can explain me how to do it right...
Can someone help me please?

I believe RedisStore does this automatically for you, here's a good post about it: http://www.ranu.com.ar/2011/11/redisstore-and-rooms-with-socketio.html
How is this done internally?
Well as you have heard, Redis, RabbitMQ, ZeroMQ etc have pub-sub functionality, meaning you can subscribe to channels and publish info on them (to all the connected peers):
https://github.com/mranney/node_redis#publish--subscribe
So server A, B and C are subscribed to the same channel. When a client connected to server A wants to send a message for all the users connected to the chat room "js" for example, he sends a message to the server A and server A publishes a message on the "js" channel.
All the rest of the servers get that message and broadcast it to all their clients.

Related

node js, socket.io, redis and pm2

Our system includes a NodeJs Restful API server. This server also serves as a socket IO server. Many devices will connect to the server by socket io, the user can control the device by calling restful API, the server will transfer command to the device through the socket IO. We used pm2 to cluster the API server. Can you help how to use Redis.io server to support to send a message from a cluster to a specific socket instance?
If you already have a redis server setup, all you have to do is setup the socket.io-redis adapter: https://www.npmjs.com/package/socket.io-redis
From there, it's best to have the incoming socket.io connections join a device specific room. This is typically achieved with a socket.join() from the connection event.
From there, you can call your .to().emit() method to send the data to the device. Using rooms allows you to ignore the socket and transmit the message to the device no matter which instance they are connected to

Persist websocket connection object across the multiple server

I am using a websocket library on server for establishing socket connection.
https://github.com/websockets/ws
I have a more than one server in cluster, I want to know how can I use same socket connection object on another server in cluster.
And also I want to know what is the best option for webchat implementation native websocket or socket.io
You cannot use the same actual socket object across multiple servers. The socket object represents a socket connection between a client and one physical server process. It is possible to build a virtual socket object that would know what server its connection is on, send that server a message to then send out over the actual socket from that other server.
The socket.io/redis adapter is one such virtual ways of doing this. You set up a node.js cluster and you use the redis adapter with socket.io. It uses a central redis-based store to keep track of which serve process each physical connection is one. Then, when you want to send a message to a particular client from any of the server processes, you send that message through socket.io and it looks up for you in the redis database where that socket is connected, contacts that actual server and asks it to send the message to that particular client over the socket.io connection that is currently present on that other server process. Similarly, you can broadcast to groups of sockets and it will do all the work under the covers of making sure the message gets to the clients no matter which actual server they are connected to.
You could surely build something similar yourself for plain webSocket connections and others have built pieces of it. I'm not familiar enough with what exists out there in the wild to offer any recommendations for a plain webSocket. There plenty of articles on scaling webSocket servers horizontally which you can find with Google and read to get started if you want to do it with a plain webSocket.

Horizontally scaling socket.io across multiple Amazon EC2 instances

Have everything setup and working correctly with 2 Amazon EC2 servers running my node application. Currently sitting behind an Application Load Balancer.
I am emitting socket messages using code like this
const ioredis = require('socket.io-redis');
io = require('socket.io')(server);
io.adapter(ioredis({
host: 'localhost',
port: 6379
}));
io.to('roomName').emit('message', data);
However, when emitting a message using socket.io, the message is only broadcast from the originating node server.
Server 1 emits a socket.io message -> Anyone connected to Server 1 hears the message, but anyone connected to Server 2 doesn't.
Server 2 emits a socket.io message -> Anyone connected to Server 2 hears the message, but anyone connected to Server 1 doesn't.
What i need help with is how to emit the socket.io message from Server 1 and either Relay it to all other server's aswell, possibly by using a single instance of redis on a seperate server?
OR
Have another Server as a socket emitter that Server 1 and Server 2 send and receive socket messages from.
Not quite sure which option is the best and correct way to go, any help would be appreciated.
I managed to solve the problem by creating a 3rd server, installing Redis on it and setting all of the other servers to use that single instance of redis.
Now socket messages are broadcast to all servers regardless of the originating server.

socketio inter server communication with redis and haproxy

I'm working on a project which uses SocketIO and should be Horizontally scalable. Im using
A Load Balancer using HAProxy
Multiple Node Servers (2-4)
Database server(Redis and MongoDB)
I'm able to redirect my incoming Socket connections to Node servers using roundrobin method. Socket connection is stable and if I use socket.emit() I'm receiving the data. I'm also able to emit to the Other socket connection connected to the same Node server.
I'm facing issue in the following scenario:
User A connected to Node server 1 and User B connected to Node Server 2
My intention is to store the Socket data in redis
If User A wants to send some data to User B, how can I tell the Node server 2 to emit the data to User B from Node server 1
Please let me know how can I achieve this (with ref if possible).
Thanks in advance.
This scenario is a match for the case Pub/Sub of Redis.
If you haven't already, you should try Pub/Sub.
Have a look at socket.io Redis adapter. It should be exactly what you need.
clients() method in particular looks promising. Keep in mind, that socket.io creates a unique room for each client.

Is it possible to both listen and send messages to a remote socket using node-red's websocket node?

The Almond Plus router and home automation hub now exposes the state of its registered z-wave and zigbee sensors via a websocket.
The websocket API is here:
https://wiki.securifi.com/index.php/Websockets_Documentation
I've aimed a node-red websocket node at the router's local IP address, and have included authentication information in the URL. This seems to work for receiving status changes to devices.
But I need to also be able to send commands over the websocket to flip switches and whatnot. When I create both 'listen on' and 'connect to' websocket nodes in node-red, only the node that's listening connects. Do I need to make two nodes at all? I would have hoped there'd be a way to make one connection to the websocket and use it for two-way communication, but maybe this question just exposes my ignorance of how either websockets or node-red function.
Thanks for any help or information.
You should need both a Websocket in and a Websocket out, but both should be set to "connect to" mode. These handle the input and output side of the connection
I'd have to double check the code, but they should share the same client connection under the covers so there will only be one real Websocket connection. But even if the 2 nodes don't share the connection having 2 separate websocket connections to the same address shouldn't be a problem.

Resources