Signalr-Redis "No Connection with that ID"

Signalr-Redis "No Connection with that ID"

背景

我有一个部署在 Google 云上的网站。本网站使用 asp.net 核心 (v2.2) 和 signalr 编写。

我的应用程序架构是我有两台机器,运行ning Linux,服务于同一个站点。该站点由 Kastrel(本地主机)提供服务并由 nginx 包装(用于外部网络)。我有云负载平衡器,它在这两个实例之间分配流量。 LB 定义为按会话亲和性拆分流量。

我将 SignalR 定义为使用 Redis,以便在多实例环境中正常工作。

我的startup.cs代码:

var redisCs = ConfigurationOptions.Parse("REDIS CS");
services.AddSignalR().AddRedis(options =>
{
    options.ConnectionFactory = async writer =>
    {
        var connection = await ConnectionMultiplexer.ConnectAsync(redisCs, writer);
        return connection;
    };
    options.Configuration.ClientName = "Main-website-Signalr";
});

问题

当我测试它时,有时它能正常工作,而有时却不行。

当它失败时,我在浏览器控制台上看到这个日志:

WebSocket connection to 'wss://mysite.com/hubs/myhub?id=R_Zmaew-lRN_r2d_c-xOyg' failed: Error during WebSocket handshake: Unexpected response code: 404

在我的浏览器 "Network" 选项卡上,我看到浏览器尝试与地址 wss://mysite.com/hubs/myhub?id=R_Zmaew-lRN_r2d_c-xOyg 通信并获得 404 响应。

我的调查

我担心 nginx 以某种方式阻止连接,所以我决定在没有任何中介的情况下与 Kestrel 连接。我通过 ssh 进入机器并 运行 这个命令:

$ curl 127.0.0.1:5000/hubs/businesses?id=Tta4PmrjMrzHBHa8CT0SPQ -v
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 5000 (#0)
> GET /hubs/myhub?id=Tta4PmrjMrzHBHa8CT0SPQ HTTP/1.1
> Host: 127.0.0.1:5000
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Date: Wed, 05 Jun 2019 06:26:09 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
<
* Curl_http_done: called premature == 0
* Connection #0 to host 127.0.0.1 left intact
No Connection with that ID

所以,我遇到了 404 错误 - 就像我从浏览器上得到的一样。我想现在没有人以某种方式阻止连接。它只是 SignalR 配置的某些东西被破坏了。

为什么SignalR能找到连接?

我登录的是哪台机器有关系吗?连接不是通过 Redis 以某种方式传递的吗?

当您在单个 load-balancer 后面有多个服务器实例时,您需要启用粘性会话,这意味着唯一的客户端将永远只连接到一台机器。

您可以在 https://docs.microsoft.com/en-us/aspnet/core/signalr/scale?view=aspnetcore-2.2#redis-backplane

中查看有关 Redis 背板的一些信息

SignalR 是一种协议,该协议的一部分意味着将在 "negotiate" 期间在服务器上创建连接 ID。这意味着您不能随机地使用 ID 卷曲端点,因为卷曲不理解 SignalR 协议。

如果您对该协议感兴趣,可以阅读 https://github.com/aspnet/AspNetCore/tree/master/src/SignalR/docs/specs