Search code examples
c#blazorasp.net-core-signalrazure-signalr

Why is SignalR starting up to 8 servers per Blazor Server app start?


When I start my Blazor Server app, I can see in the SignalR service that 8 servers are connected. I don't understand why. My goal is that MyRazorPage is able to send and receive (from itself or some Azure Function) SignalR messages without creating so much (unnecessary?!) servers.

Here is my code and below are the DI service registrations I'm using:

Code

MyRazorPage.razor

@inject IHubConnectionFactory HubConnectionFactory // see HubConnectionFactory.cs below

MyRazorPage.razor.cs

public sealed partial class MyRazorPage
{
    private HubConnection _hubConnection;
    
    public async ValueTask DisposeAsync()
    {
        if (_hubConnection is not null)
        {
            _hubConnection.Remove("MyMethodName");
            await _hubConnection.DisposeAsync();
        }
    }
    
    private async Task HandleHubMessageReceived(ResultDto result)
    {
        // handle received result
    }
    
    private Task SendMessage()
    {
        // ... 
        await _hubConnection.SendAsync("MethodName", new ResultDto(Guid.Parse(CustomerId), ResultEnum.Success));        
    }
    
    protected override async Task OnInitializedAsync()
    {  
        _hubConnection = HubConnectionFactory.CreateHubConnection();
        await _hubConnection.StartAsync(CancellationToken);
        _hubConnection.On<ResultDto>("MyMethodName", HandleHubMessageReceived);
    }   
}

Setup, service registrations, SignalR middleware

Package references

<PackageReference Include="Microsoft.Azure.SignalR" Version="1.24.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.1" />

appsettings.json

"Azure": {
   "SignalR": {
     "Enabled": "true",
     "ConnectionString": "Endpoint=URL;AccessKey=KEY;Version=1.0;"
   },
 "SIGNALR_REFRESH_BILLING_PAGE_URI": "https://localhost:44362/MyHub",

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddSignalR();
    services.AddSignalRHubConnection(config =>{
               config.ConnectionString = Configuration["SIGNALR_REFRESH_BILLING_PAGE_URI"] ?? 
               string.Empty;
               });
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseRequestLocalization(app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>().Value);

    if (!env.IsProduction())
    {
        app.UseDeveloperExceptionPage();
        app.UseMigrationsEndPoint();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();
    
    app.UseCookiePolicy();
    
    app.UseEndpoints(endpoints =>
                     {
                         endpoints.MapControllers();
                         endpoints.MapBlazorHub();
                         endpoints.MapRazorPages();
                         endpoints.MapFallbackToPage("/_Host");
                         endpoints.MapHub<MyHub>($"/{MyHub.HubName}");
                     });
}

HubConnectionFactory.cs

public class HubConnectionFactory : IHubConnectionFactory
{
    private readonly SignalREndpointConfiguration _configuration;
    
    public HubConnectionFactory(IOptions<SignalREndpointConfiguration> configuration) => _configuration = configuration.Value;
    
    public HubConnection CreateHubConnection()
    {
        return new HubConnectionBuilder()
               .WithUrl(_configuration.ConnectionString)
               .Build();
    }  
}

MyHub.cs

public class MyHub : Hub
{
    public const string HubName = "MyHub";

    public async Task SendMessage(ResultDto dto)
    {
        await Clients.All.SendAsync("MyMethodName", dto);
    }
}

I also tried the following things, but without any success:

Approach Result
Removed "Azure setting" from appsettings.json HandleHubMessageReceived is not invoked anymore.
Added services.AddCors() to ConfigureServices in Startup.cs and app.UseCors(policy => policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin() to Startup.Configure() No difference

Solution

  • I can see in the SignalR service that 8 servers are connected. I don't understand why.

    enter image description here

    That's what you're talking about, right?

    It's server connections, not servers.

    Here is the official document about How connections are counted.

    And server_connections_count = 1 instance * 2 hubs * 5 (default value).
                                                         = 10

    Tips: Default value is 5 --> InitialHubServerConnectionCount

    If you want to reduce the connection count, you can refer to the official documentation.

    Configure options

    Why 8 server connections in your azure portal metrics?

    There should be a delay, in the charts in Azure Portal, the statistics may be related to the time span, so the data you see may have slight deviations, you can check it by looking at more detailed statistics.