群集中的SignalR + Redis无法正常工作

时间:2018-07-26 06:57:49

标签: docker asp.net-core redis signalr signalr-backplane

背景

当使用单个应用程序实例(容器)运行网站时-SignalR运行正常。

当扩展到更多实例(> 1)时,它会引发错误并且无法正常工作。我在互联网上寻找解释,发现需要配置Signalr使其在集群中工作。我选择Redis as my backplane

我遍历了许多教程,以正确地做到这一点,但对我来说并不奏效。

环境

我正在托管在Google云中的asp.net core v2.1。使用Kestrel + nginx将应用程序部署为Docker容器。 Docker容器在负载均衡器后面的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的输出窗口: enter image description here

在服务器(2个副本,而不是开发环境)上也发现了相同的行为(已连接)。

为了验证Signaler是否确实使用Redis(不仅仅是连接),我使用redis-cli连接Redis服务器,发现:

enter image description here

由此我可以了解到Redis上存在一些“话题”。

我删除了网站LoadBalancer(GCP)并将其部署为Agian。现在有了Sticky-Session:ClientIP。该负载均衡器将请求路由到不同的容器。

我唯一没有更改的地方是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 个答案:

没有答案