I am working on setting up socket.io in cluster mode using PM2.
I am using socket.io-redis
package and it works fine in cluster mode.
But the problem arises when I want to access all connected sockets. Because processes don't know about socket connections in other processes in cluster mode.
I thought socket.io-redis
keeps track of all the connected sockets and all its session info but it didn't.
Is there any way or solution to access all the socket connection existing in all processes in socket.io/Nodejs?
Socket.io-redis does keep track in a sense..
From their docs
"The Redis adapter extends the broadcast function of the in-memory adapter: the packet is also published to a Redis channel (see below for the format of the channel name).
Each Socket.IO server receives this packet and broadcasts it to its own list of connected sockets."
So basically, redis is used as the broker to tell each socket server to emit based on X channel etc. Allowing you to have a socket.io server in cluster mode work, but as you have mentioned it can fall short when you need to keep track of things outside of just an emit.
So where does this leave us.. Well you can use custom hooks via socket.io-redis but personally I found it to be really difficult to understand and use and had limited success personally. I think with the new version of socket.io and socket.io redis there were some tweaks to make this simpler however I have not tried them.
Instead, what we do is use redis hset and jget to store the socket and an ID of a users, then when we want to get all users online we can query redis to get the list of online users or users in a specific room etc.
What you will want to do is add the redis package and connect in additon to the regular pub / sub.
Then, when a user joins a room or your server for that matter you will do an hset. On the first join ours looks something like this
redis.hset([collection-name],[Field],[value])
So in code it looks like
redis.hset(decoded.cID,"socket-" + socket.id,socket.nickname)
This will set a value in redis, so the collection name is a value ( for us its a unique id of the channel ) then we stock the 'socket.id' for the Field along with a 'nick-name' for the value. This value is the users ID OR its anonymous if they are not logged in
Then, when we want to grab who is in a room we use the hget command
redis.HGETALL([collection-name],function(err,results){}
So inside of say the emit, we call the redis.HGETALL command to get all items inside a specific collection that we pass in and send that back to all connected users.