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
...
Вопрос
Что я пропустил? Что проверить?