Signalr-Redis“与该ID无关”

时间:2019-06-05 07:15:44

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

背景

我有一个部署在Google Cloud上的网站。该网站使用asp.net core(v2.2)和signalr编写。

我的应用程序体系结构是我有两台运行Linux的计算机,服务于同一站点。该站点由Kastrel(localhost)提供服务,并由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

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

我的调查

我担心Nginx会以某种方式阻止连接,所以我决定在没有任何中介的情况下与Kestrel连接。我进入了计算机并运行以下命令:

$ 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通过的吗?

1 个答案:

答案 0 :(得分:0)

当单个负载均衡器后面有多个服务器实例时,您需要启用粘性会话,这意味着唯一的客户端将只能连接到一台计算机。

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

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

SignalR是一个协议,该协议的一部分意味着在“协商”期间将在服务器上创建连接ID。这意味着您不能随便用ID随机卷曲端点,因为curl无法理解SignalR协议。

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