3

I'm developing a web game that currently all runs on one server. It uses SignalR to maintain connections between the server and clients, and the server also sends all the web stuff to clients (HTML/CSS/JS/etc.)

I've been thinking about how this would scale up if many more clients were to start using the site. Reading the SignalR documentation on scaling up, they suggest adding extra SignalR servers and linking them using a Redis backplane, or Azure's equivalent.

Scaling diagram 1

However, the example given in their diagram seems such a trivial use-case as to actually be rather misleading - it has a server sending a "hello" message and that being forwarded to all clients. You're almost certainly going to want more complexity than this, and some kind of state, whereas this example conveniently omits the need for any persisted state. If you have a chatroom, you'll want to check that a client trying to send a message has permission to send to that room, for instance. In my case, the client will need to be established as a member of the game before they can participate in it.

This introduces the concept of state, which appears to be entirely undealt with by the aforementioned documentation. Because state would be needed, a DB would be needed and that would need to be frequently accessed by all servers upon each client request, adding a significant overhead.

There's also the overhead of serialization and deserialization. If you have the concept of a chatroom, or a game room, and there is an associated state, it seems to me that the suggested 'scaling up' solution with a Redis backplane simply pushes the problem of maintaining state to the back end; servers will have to coordinate with each other - again presumably through a DB - to communicate the current state of the game, because you can't rely on one server being dedicated to dealing with that game and having it stored in its memory. This introduces a large serialization/deserialization and DB access overhead too.

It seems to me that a better scaling alternative for virtually any scenario is to design a system where each SignalR server is wholly responsible for maintaining the state of certain instances - such as a game or a chatroom - and that there be a central coordination server that tells clients which SignalR server to connect to. This would bypass the need for the kind of scaling mentioned in the SignalR docs completely, because a client would just be connecting to the one SignalR server responsible for dealing with that game/chatroom, and it would also avoid the serialization/deserialization overhead because the server wouldn't need to keep storing/restoring state to/from the DB; it could just be kept in memory.

Scaling diagram 2

Are there any significant disadvantages to scaling up in the way I've just mentioned? In what circumstances would it be better to scale up using the "Redis backplane" style scaling? It seems to me that virtually any system is going to need to maintain state, and that state either has to be communicated between SignalR servers introducing significant overhead, or stored in one server's memory meaning that scaling would be done simply by introducing new, separate SignalR servers that have certain states dedicated entirely to them. I actually wonder whether there are any scenarios where that type of scaling would be worse than the Redis backplane type scaling?

7
  • I discuss the same thing here twitter.com/davidfowl/status/…
    – davidfowl
    Jan 22, 2023 at 19:24
  • Out of interest, why does your solution 3 have a LB at all? Why not give the client the game server's host and have it connect directly?
    – Jez
    Jan 23, 2023 at 10:02
  • I don't want to expose hosts to the interwebz. Also public IPs cost $$ on cloud providers, so there's just one exposed (the LB) and the rest of the networking infrastructure is internal and behind an LB. Not to mention reducing the attack surface.
    – davidfowl
    Jan 23, 2023 at 15:22
  • I guess. Couldn't you put the whole thing behind CloudFlare and let them handle the attack surface though?
    – Jez
    Jan 23, 2023 at 15:31
  • How many public IPs do you want to expose? How big is your game going to get? How much is it going to cost? Do you have to pre-provision them? Usually, you'd have some form of load balancer regardless (even if it's just for host names).
    – davidfowl
    Jan 23, 2023 at 15:49

1 Answer 1

2
+150

The approach you described, where each SignalR server is responsible for maintaining the state of certain instances and a central coordination server directs clients to the appropriate SignalR server, is called sharding. It can be a good solution for maintaining state and avoiding serialization/deserialization overhead when the number of clients and instances increases.

However, there are some disadvantages to this approach. One disadvantage is that it can be more complex to implement and maintain, as it requires a coordination server and a strategy for assigning instances to specific servers. Another disadvantage is that it may not work well for scenarios where instances need to be moved or re-assigned dynamically, as it would require additional logic to handle these changes.

The Redis backplane approach, on the other hand, is more suited for scenarios where the number of clients is increasing but the number of instances is not. In this case, the state of the instances can be shared among all the SignalR servers using a Redis cache, and the clients can connect to any of the SignalR servers. This approach is simpler to implement and maintain, but it may introduce more overhead for serialization/deserialization and cache access.

To summarize, the Redis backplane approach is better suited for scenarios where the number of clients is increasing but the number of instances is not, while sharding is better suited for scenarios where the number of instances is also increasing. Personally, I would recommend going with the first option and if the performance is not how you intended or you scale in the future, then try implementing sharding.

2
  • Isn't sharding a database thing?
    – Jez
    Jan 22, 2023 at 16:43
  • It is usually associated with DBs but you can generalize the term to any kind of computing concept. Jan 22, 2023 at 19:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.