SignalR + Redis в кластере не работает

Фон

При запуске сайта с одним экземпляром приложения (контейнером) - SignalR работает отлично.

При масштабировании на большее количество экземпляров (>1) он выдает ошибки и просто не работает. Я искал объяснение в интернете и обнаружил, что мне нужно настроить мой Signalr для работы в кластере. Я выбираю Redis в качестве моей задней панели.

Я работал над многими уроками о том, как сделать это правильно, и это просто не работает для меня.

Среда

У меня работает asp.net core v2.1, размещенный в облаке Google. Приложение разворачивается как Docker-контейнер, используя Kestrel + nginx. Док-контейнер работает в кластере Kubernetes за балансировщиком нагрузки.

Моя конфигурация

Startup.cs:

public class Startup
{
    public Startup(IConfiguration configuration,
        IHostingEnvironment hostingEnvironment)
    {
        Configuration = configuration;
        HostingEnvironment = hostingEnvironment;
    }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // ...
        services.AddSignalR().AddRedis(options =>
        {
            options.Configuration = new ConfigurationOptions
            {
                EndPoints =
                    {
                        { ConfigurationManager.Configuration["settings:signalR:redis:host"], int.Parse(ConfigurationManager.Configuration["settings:signalR:redis:port"])}
                    },
                KeepAlive = 180,
                DefaultVersion = new Version(2, 8, 8),
                Password = ConfigurationManager.Configuration["settings:signalR:redis:password"]
            };
        });
        // ...
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/errors/general");
            app.UseHsts();
        }

        // nginx forward
        app.UseForwardedHeaders(new ForwardedHeadersOptions
        {
            ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
        });

        app.UseSignalR(routes =>
        {
            routes.MapHub<StatisticsHub>("/hubs/myhub");
        });
    }
}

Чтобы убедиться, что соединение с сервером Redis прошло успешно, я проверил окно вывода Kastrel:

Такое же поведение (подключено) обнаружено и на серверах (2 реплики, а не в среде разработки).

Чтобы убедиться, что Signalr "действительно" использует Redis (не просто подключается), я использовал redis-cli подключить сервер Redis и обнаружил, что:

Из этого я могу понять, что есть некоторые "разговоры" о Redis.

Я удалил сайт LoadBalancer (GCP) и развернул его снова. Теперь с Sticky-Session: ClientIP. Этот load balancer направляет запросы в разные контейнеры.

Единственное место, которое я не изменил, - это конфигурация nginx. Я не прав?

Результат

SignalR не работает в браузере. Эти ошибки из консоли браузера:

scripts.min.js:1 WebSocket connection to 'wss://site.com/hubs/myhub?id=VNxKLazEKr9FKM4GPZRDhA' failed: Error during WebSocket handshake: Unexpected response code: 404
scripts.min.js:1 Error: Failed to start the transport 'WebSockets': undefined
Error: Connection disconnected with error 'Error: Server returned handshake error: Handshake was canceled.'.
scripts.min.js:1 Error: Connection disconnected with error 'Error: Server returned handshake error: Handshake was canceled.'.
files.min.js:1 Uncaught (in promise) Error: Error connecting to signalR. Error= Error
...

Вопрос

Что я пропустил? Что проверить?

0 ответов

Другие вопросы по тегам