1

my api endpoints are spread over multiple servers over multiple locations and i am trying to figure out how to deal with socket updates on connected clients. i would really like to avoid having a single redis db setup just to handle the connected clients over the many servers.

i wont have to broadcast messages, socket messages will always be sent to a single user. while i know each connected clients channel id i am not sure if its possible to just emit a message to a single user when i just have the channel id in my hand and for example the initial connection was made with another server in one of the clusters.

i see there is an option for sticky load balancing but I'm not completely sure thats is what i actually need.

thanks to everybody who could give me a more in depth explanation of whats the best way to do this.

aschmid00
  • 7,038
  • 2
  • 47
  • 66

1 Answers1

4

It's not clear exactly what you're asking. When you have users connected to a variety of servers and you want to send a message from one server to a particular user, then you must ultimately deliver that message to the server that the user is connected to so it can send the message over the user's connection.

There are a variety of ways to do that:

  1. Central Database. Maintain a central database that tells you which server a user is connected to at any given time. Then, when you want to send a message to userA, you can look them up in the central database and find that they are currently connected to Server12 and you can then ask Server12 to send the message to them. This is the strategy that the socket.io redis solution uses. This strategy can create a bottleneck in the central database since all servers must use the same central database to "lookup" where a given user is connected.

  2. Load Balancing Algorithm. Create a load balancing algorithm that calculates which server a given user will connect to based on their userID (often using a hash of the userID that it then evenly split among the number of servers currently active). In this scheme, when a user connects, they are load balanced to an algorithmically chosen server. So, userA would always be sent to Server12, for example. Then, elsewhere in your server farm, if you want to send a message to userA, you can use the same algorithm to calculate which server they would be connected to and can contact that server to ask it to send the message to them. This scheme can have difficulties when you want to change the number of active servers because that causes a change in the load balancing algorithm which requires all existing users to reconnect via the new algorithm to make their connection predictable again.

  3. Broadcast Outbound Messages to All Servers. Broadcast outgoing message for a particular user to all servers. In this case, if Server10 wants to send a message to userA, it first checks to see if it already has a connection for userA. If it does, it just sends the message. If it does not, then it just broadcasts to all the other active servers that it it wants to send this particular message to UserA. Each server will check its list of connections and, if it has a connection for UserA, it will send the message to UserA. This method does not scale well for high traffic (e.g. situations with lots of messages because all servers receive all outbound messages), but can scale well for lots of users, but low traffic.

  4. Each Server Maintains Its Own Connection Index, Broadcast incoming connections and disconnections to all servers. In this scheme, every server maintains an in-memory index for any connected user. Whenever a user connects to a particular server, that server then broadcasts to all the other servers that UserA is now connected to Server12. Whenever UserA disconnects, the disconnect is also broadcast. Each Server updates it's in-memory index on each of these events so at any given moment, every server has a live lookup table of where every user is currently connected. This method does not scale as well for large numbers of users because every server is tasked with keeping an in-memory index of all active connections and every server gets a message when any user connects or disconnects. But, it does work well for high traffic because each server already has a fast way to know where a given user is connected.

Depending upon the particular load characteristics of a given situation that you are trying to optimize for, one can combine aspects of each of these methods into hybrid solutions too. For example, connections and disconnections could be broadcast to N specialized database servers and the individual servers could then spread their load across those N database servers when looking up where a given user was connected to alleviate the central database being as much of a bottleneck.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • thanks a lot for this answer. sorry my question was not clear enough but you answered it completely. for my case i see there is no other solution than having a central db like redis handling all connected users. – aschmid00 Aug 10 '15 at 17:12