Consistent hashing/routing with HAProxy?

Hello,

I have a web-based game platform that relies on WebSockets. In this game, a group of users (up to 10) can be matched together in a room to play a game against each other. There can be more than tens of thousands of players playing the game at the same time.

I have been using the default load balancer service provided by my cloud platform which distributes user connection to one of many available HTTP servers in the backend. When 10 users, who are in the same room, end up in different backend HTTP servers, the servers communicate with each other using Messaging platform (something similar to Apache Kafka) to relay and communicate actions happening within a room.

Things are working fine, but this approach has few issues.

  • Messaging platform can become a bottleneck when we scale. (As # of backend server increases, the messaging platform has to do substantially more work to pubsub messages)
  • Messaging platform adds latency.

Therefore, I am looking for a solution to see if I can somehow route users who are supposed to be in the same room to the same backend game server. If all users/players from the same room are connected to the same server, there is no more need for an inter-server messaging platform.

So my requirements would be something like

  1. If no player has joined for a room or match A1 yet, then the first player to join can end up in any one of the backend HTTP servers, preferably one with the least conn.
  2. When there is at least one player already connected to backend server S1 for match A1, HAProxy should forward later joining players to server S1.
  3. The number of backend servers up and running can change any time before/during/after when 1 and 2 are happening.

While I do not have a good understanding of load-balancer, nor reverse-proxy, I learned about HAProxy and started reading its documentation, but I couldn’t figure out if HAProxy will be able to support my use case. As far as I can tell, HAProxy’s hash-based load balancing can route same-hash requests to different servers if # of servers in the backend change.

Would HAProxy be able to fulfill my use case?

I think you are complicating #1 & #2 – but I don’t understand your case.

Really, you want all users in case 1 to go to the same server, until that server is full (say by a certain number of connections, or load average or whatever). and then roll to server 2 and so on… and if 1 goes away, send everyone to 2 or whatever is up.

Haproxy can absolutely do this. I personally use cookies to make this happen, for example, you can have the first connection go to whatever server, and it can set a cookie (in your web server) to send the user to server 1 after they authenticate… and haproxy will consistently route them to server 1 based on this cookie. Or you can have haproxy set this cookie based on least connections or most connections or whatever and stick with it forever or until it expires assuming the server is up.

It works great. Just search for cookies & haproxy.

@fusion, thanks for the reply. In the approach that you mentioned (it sounds similar to greedy algorithm), it may cause problem in my situation.

In ideal world, if server A is configured to accept up to 100 connections, we could have 10 rooms with 10 players each in the room to fill up those 100 connections for server A.

However, there are multiple rooms for users to select from, and server A might end up with 100 players aiming to join 20 rooms rooms, (5 players per room). When the remaining players for the room connect, they will be sent to the next server, say server B. In this case, users from those 20 rooms will be spliced in both server A, and server B, and in the worst case, they can all be splitted in different servers (chance is low, but can still happen).

If you can describe your concern, it can be managed. HAProxy can’t know anything you don’t teach it.

If you want to limit connections to 10 per chat room and not more than 100 per server, that just means you need a cookie or cookies that contain both pieces of information (or you can use stick tables) to capture this logic. something like A-1-10 where A is the server, 1 is the chat room and 10 is the number in this room the person represents. When someone drops out of a chatroom, you reassign that position, or you let it time out, or whatever you wish. When there are more than 100 A’s at a time, haproxy kicks someone to server B. When there are more than 10 in a chatroom, they kick them wherever you want (either a different chat room on A or to server B, etc)… but you have to decide that.

It really sounds like you could put each chat room under a separate subdomain or a separate URL (serverA/chatroom1) and HAproxy can balance the number of connections to each, but it sounds like you are still hashing out your desired behavior.

Best.

I see. I will take a look at path based routing (or subdomain based), and stick tables and give it a try. I might also use runtime API to update HAProxy config live. Thank you for the help.

Greetings,
You are using a load balancer to try to direct 10 people to the same place. Maybe you could do that with cookie based routing and make a rule that says BLAHBLAH_HASH cookie goes to this server? Have the server assign that cookie and redirect them and poof - they go to the new server that has all 10? I’m not an HAProxy export but I’m interested in the solution.
Bet Regards,
Dean