SignalR In Load Balanced Environments
When load balancing the backoffice, we also need to take care of the client-to-server communication outside of web requests. Umbraco uses SignalR to abstract away these types of communication. This also allows us to support load balancing by replacing how the communication is done by introducing a backplane.
Understanding SignalR Backplanes
A traditional SignalR backplane (such as SQL Server or Redis) distributes messages between servers. Any server can broadcast messages to clients connected to other servers. However, the WebSocket connection remains tied to the server the client initially connected to.
Using a traditional backplane, routing HTTP requests to a server without the active WebSocket connection causes "No connection with that ID" errors.
Azure SignalR Service works differently. Instead of clients connecting directly to your servers, they connect to the Azure SignalR Service. This centralizes connection management, allowing requests to be handled by any server without sticky sessions.
Sticky Sessions vs Stateless
When load balancing the backoffice, you need to decide between two approaches:
Option 1: Sticky Sessions with Any Backplane
Configure your load balancer to use sticky sessions (session affinity). This ensures that once a client connects to a server, all subsequent requests from that client go to the same server.
With sticky sessions enabled, any SignalR backplane works:
SQL Server backplane
Redis backplane
Other third-party backplanes
This approach works if your load balancer supports sticky sessions.
Option 2: Stateless with Azure SignalR Service
If you want fully stateless servers without sticky sessions, you need:
Azure SignalR Service for SignalR connection management.
IDistributedCache for session state management (see Distributed Cache documentation).
This approach requires additional setup but allows for true horizontal scaling without server affinity.
Umbraco's cache is built on Microsoft's HybridCache, which automatically uses IDistributedCache as a second-level cache when configured. This means that setting up IDistributedCache for session management also enables distributed caching of Umbraco content across all servers. See Cache Settings for more information.
Choosing the Right Backplane
Choosing the right backplane comes down to a few factors:
Whether you can use sticky sessions
Message throughput requirements
Cost
The infrastructure you already have in place
Microsoft has a good list of available backplanes in its SignalR load balancing article, including a list of well-known third-party offerings.
Code examples
The following code examples show how you can activate SignalR load balancing using an Umbraco composer.
Both Umbraco and these composers use .AddSignalR(). This duplication isn't a concern as the underlying code registers the required services as singletons.
Using existing infrastructure
It is possible to use your existing database as a backplane. If this database is hosted in Azure it is not possible to enable Service Broker which will have an impact on message throughput. Nevertheless, it might be sufficient to cover your needs. For more information, check out the GitHub page.
Add a reference to the
IntelliTect.AspNetCore.SignalR.SqlServerNuGet package.Add the following composer to your project:
Azure SignalR Service
Set up a resource as described in the Microsoft tutorial.
Make sure the
connectionstringis set up under the following key:Azure:SignalR:ConnectionString.Add a reference to
Microsoft.Azure.SignalRNuGet package.Add the following composer to your project:
Last updated
Was this helpful?