Base solution for your next web application
Open Closed

Configure SignalR to Use Redis Backplane - Scaling SignalR Multi Instances #12241


User avatar
0
pliaspzero created

Hi,

V13.4 - Angular & ASPNET CORE - we want to scale up - we host in Azure and have Abp.RedisCache setup - like *redis.cache.windows.net:6380

could we use this also for scalling SignalR ? How could that be done?

Thanks Oliver


13 Answer(s)
  • User Avatar
    0
    pliaspzero created

    like this? // Retrieve Redis connection string var redisConnectionString = _appConfiguration["Abp:RedisCache:ConnectionString"]; var redisDatabaseId = _appConfiguration.GetValue<int>("Abp:RedisCache:DatabaseId");

            if (!string.Equals(redisConnectionString, "localhost", StringComparison.OrdinalIgnoreCase))
            {
                // Configure SignalR with Redis backplane and set DatabaseId
                services.AddSignalR().AddStackExchangeRedis(options =>
                {
                    options.Configuration = redisConnectionString;
                    options.InstanceName = "SignalRBackplane"; // Optional: Instance name for namespacing
                    options.ConfigurationOptions = new StackExchange.Redis.ConfigurationOptions
                    {
                        EndPoints = { redisConnectionString },
                        DefaultDatabase = redisDatabaseId,
                        Ssl = true,
                        AbortOnConnectFail = false
                    };
                });
            }
            else
            {
                // Use in-memory SignalR setup as a fallback if Redis isn't configured
                services.AddSignalR();
            }
    
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi

    You can apply the following code in Startup.cs. If you will need the "Microsoft.AspNetCore.SignalR.StackExchangeRedis" package here.

    public void ConfigureServices(IServiceCollection services)
    {
        //...
        
        // Retrieve Redis connection string and database ID from configuration
        var redisConnectionString = _appConfiguration["Abp:RedisCache:ConnectionString"];
        var redisDatabaseId = _appConfiguration.GetValue<int>("Abp:RedisCache:DatabaseId");
    
        if (!string.IsNullOrWhiteSpace(redisConnectionString))
        {
            // Configure SignalR to use Redis backplane
            services.AddSignalR().AddStackExchangeRedis(options =>
            {
                options.Configuration = redisConnectionString;
                options.InstanceName = "SignalRBackplane"; // Optional: Set a custom instance name for your SignalR hub
                options.ConfigurationOptions = new StackExchange.Redis.ConfigurationOptions
                {
                    EndPoints = { redisConnectionString },
                    DefaultDatabase = redisDatabaseId,
                    Ssl = true, // Enable SSL for secure connection
                    AbortOnConnectFail = false
                };
            });
        }
        else
        {
            // Fallback to in-memory SignalR if Redis is not configured
            services.AddSignalR();
        }
    
        //...
    }
    
  • User Avatar
    0
    pliaspzero created

    ok - I've adapted like this - but seems not to work - any further ideas? For ex. when I press on "new version available" - I see it in another client only if site is reloaded - I think this should not be the behaviour - but get the message without reloading?

            var redisConnectionString = _appConfiguration["Abp:RedisCache:ConnectionString"];
            var redisDatabaseId = _appConfiguration.GetValue&lt;int&gt;("Abp:RedisCache:DatabaseId");
    
            if (!string.Equals(redisConnectionString, "localhost", StringComparison.OrdinalIgnoreCase))
            {
                // Parse the connection string into ConfigurationOptions
                var configurationOptions = ConfigurationOptions.Parse(redisConnectionString);
                configurationOptions.DefaultDatabase = redisDatabaseId; 
                configurationOptions.Ssl = true;
                configurationOptions.AbortOnConnectFail = false;
    
                // Configure SignalR with Redis backplane and set DatabaseId
                services.AddSignalR().AddStackExchangeRedis(options =>
                {
                    options.Configuration = configurationOptions;
                });
            }
            else
            {
                // Use in-memory SignalR setup as a fallback if Redis isn't configured
                services.AddSignalR();
            }
    
  • User Avatar
    0
    pliaspzero created

    maybe it is a timezone issue?

    We are currently using ASPZero with Redis configured as the SignalR backplane for our application. However, we are encountering an issue where Redis messages (published through SignalR) are not being immediately received by connected clients. Messages only appear after the page is reloaded, which suggests a potential issue with Redis and/or SignalR configuration.

    Our application is deployed on Azure, and the site's timezone is set to W. Europe Standard Time. We suspect that this may be causing an issue with how SignalR and Redis interact, particularly in terms of time synchronization. We understand that Redis uses UTC for timestamps, and we believe there might be a mismatch with the timezone settings that could be affecting message delivery. Here's a summary of our setup and the issue:

    Redis Connection String: Configured correctly with the Azure Redis Cache endpoint.
    SignalR Configuration: We are using the Redis backplane with the AddStackExchangeRedis method.
    Timezone: The site's timezone is set to W. Europe Standard Time.
    Problem: Messages published to Redis (e.g., PUBLISH WFMOne.Web.Chat.SignalR.ChatHub:all "Hello from Redis!") are only visible to clients after they reload the page. We suspect this could be related to time handling, either in Redis or SignalR, or potentially the timezone mismatch.
    

    Our steps taken:

    We have confirmed that Redis is correctly receiving and publishing messages.
    We checked that the connection and channel subscriptions work, but messages only appear after reloading the page.
    We also ensured that the Redis time stamps are in UTC as expected, but we're unsure how this aligns with our local timezone (W. Europe Standard Time) and whether this is causing a delay or missed messages.
    

    Could you please assist us in confirming if there is an issue with the timezone settings or Redis/SignalR configuration that could be causing this delay in message delivery? We would appreciate any guidance on how to properly handle timezones between SignalR and Redis in our setup.

    Thank you in advance for your support.

  • User Avatar
    0
    pliaspzero created

    maybe this helps - I get this in Angualr app F12 in browser: DEBUG: scripts.c7f035c4f2b95935.js:1 Cannot start the connection using WebSockets transport. Unable to connect to the server with any of the available transports. ServerSentEvents failed: Error: 'ServerSentEvents' is disabled by the client. LongPolling failed: Error: 'LongPolling' is disabled by the client. scripts.c7f035c4f2b95935.js:1 DEBUG: scripts.c7f035c4f2b95935.js:1 Starting connection using ServerSentEvents transport polyfills.ce1ab5650c81c793.js:1 N: Unable to connect to the server with any of the available transports. ServerSentEvents failed: Error: 'ServerSentEvents' is disabled by the client. LongPolling failed: Error: 'LongPolling' is disabled by the client.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @pliaspzero

    Where do you host your apps ? Could it be similar to this one ? https://stackoverflow.com/a/78635829

  • User Avatar
    0
    pliaspzero created

    Hi, no - we host in Azure - Web App Services.. and did this enhancement var redisConnectionString = _appConfiguration["Abp:RedisCache:ConnectionString"]; var redisDatabaseId = _appConfiguration.GetValue<int>("Abp:RedisCache:DatabaseId");

        if (!string.Equals(redisConnectionString, "localhost", StringComparison.OrdinalIgnoreCase))...
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Could you check if this is enabled on your Azure app https://stackoverflow.com/a/71446349 ?

  • User Avatar
    0
    pliaspzero created

    Thanks for that - now one step forward. But still I need to reload - any further idea?

    DEBUG: scripts.c7f035c4f2b95935.js:1 Starting connection using WebSockets transport scripts.c7f035c4f2b95935.js:1 DEBUG: scripts.c7f035c4f2b95935.js:1 Starting connection using WebSockets transport scripts.c7f035c4f2b95935.js:1 [2024-11-19T12:37:44.397Z] Information: WebSocket connected to wss://myURL/signalr?id=3KFUWjao_Q7rNmiSHUB_iA. scripts.c7f035c4f2b95935.js:1 DEBUG: scripts.c7f035c4f2b95935.js:1 Connected to SignalR server! scripts.c7f035c4f2b95935.js:1 DEBUG: scripts.c7f035c4f2b95935.js:1 Registered to the SignalR server! scripts.c7f035c4f2b95935.js:1 [2024-11-19T12:37:44.550Z] Information: WebSocket connected to wss://myURL/signalr-chat?id=hAmuvL5relNB_lA0fuU5Cg.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @pliaspzero

    Could you share your Abp NuGet package version ? I remember a problem with Redis in one of the old versions.

    Thanks,

  • User Avatar
    0
    pliaspzero created

    We have latest version - V13.4 - installed

  • User Avatar
    0
    pliaspzero created

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @pliaspzero

    Is it possible to share your project with [email protected] ? We will cehck the problem on your project.

    Thanks,