I have an application written in Blazor WebAssembly under .Net8. This app is hosted model which means that has a client and server project. For the intercommunication web api is used. The app is using signalr hubs for broadcasting some messages to all users and all user's tabs.
The Server Program.cs file:
builder.Services.AddSignalR(hubOptions =>
{
hubOptions.ClientTimeoutInterval = TimeSpan.FromMinutes(30);
hubOptions.KeepAliveInterval = TimeSpan.FromMinutes(15);
});
//........
app.MapHub<ChatHub>("hubs/chathub");
On the Client page, under Index razor component:
hubConnection = new HubConnectionBuilder()
.WithUrl(navigationManager.ToAbsoluteUri("/hubs/chathub"))
.WithAutomaticReconnect()
.Build();
This gives various errors on page loading while replicas are grater than one into Kubernetes cluster, as there would be more server instances, i have done already some experiments:
When using options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets;
Then error is: WebSocket connection to 'ws://www,xxx.com/hubs/myhub'
failed
When using options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.ServerSentEvents;
Then error is: Unhandled exception rendering component:
ServerSentEvents can not be the only transport specified when
running in the browser
When using options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.LongPolling;
Then error is: LongPolling failed:
net_http_message_not_success_statuscode_reason, 404, Not Found
I am trying to sync messages across servers in order not to centralize the the signalr service (not having a central broker) into an another independent pod. Any ideas?
The breaking of the sticky sessions are caused by the clients connecting to a deployment and not a specific pod.
To avoid rolling out a centralized SignalR-Server, you have to either connect your existing Hubs with a Redis Backplane or use a different messaging system. Maybe you already deployed a redis in your cluster.
To implement redis as backplane, you can use the StackExchangeRedis:
builder.Services.AddSignalR()
.AddStackExchangeRedis(connectionString, options => {
options.Configuration.ChannelPrefix = RedisChannel.Literal("YourGreatApp");
});
Here is a list of all configuration options and also a few examples: https://stackexchange.github.io/StackExchange.Redis/Configuration#configuration-options
btw: to avoid latency issues, you should make sure, that all your pods with an active hub are running in the same datacenter
ps: Been there, done that. We eventually moved to managed SignalR Service from Azure to avoid all the struggle. We found the further scale-out much easier.