我们将AWS Kubernetes集群(EKS)与ALB/Inress和redis-cache一起用于SignalR连接.如果我们的副本集为3,则连接到服务将随机抛出404错误.设置选项时:

SkipNegotiation = true
Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets

一切似乎都很顺利.我找不到将SkipNegotation设置为TRUE的任何缺点.但找不到这是否有任何副作用(默认设置为false肯定是有原因的).

SkipNegotation设置为true会导致进一步的问题吗?

正在运行的示例代码:

Console.WriteLine("Start");
HubConnection connection = new HubConnectionBuilder()
    .WithUrl("https://<url>/api/v1/taskboard", o =>
    {
        o.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets;
        o.SkipNegotiation = true;
    })
    .WithAutomaticReconnect()
    .Build();

await connection.StartAsync();


connection.On<string>("ReceiveMessage", message =>
{
    Console.WriteLine(message);
});

for (int i = 0; i < 20; i++)
{
    await connection.InvokeAsync("SendMessage", $"Hello {i}");
    await Task.Delay(55);
}

await connection.StopAsync();
await connection.DisposeAsync();

EDIT

这些设置已添加到入口:

alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:......
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
alb.ingress.kubernetes.io/ssl-redirect: '443'
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/subnets: subnet-..., subnet-...
alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=600
alb.ingress.kubernetes.io/target-group-attributes: stickiness.enabled=true,stickiness.lb_cookie.duration_seconds=600
alb.ingress.kubernetes.io/healthcheck-path: /HealthCheck
alb.ingress.kubernetes.io/healthcheck-port: '80'

推荐答案

使用SkipNeairation的主要原因是为了避免使用粘性会话. 当您想要与SignalR服务器建立连接时,客户端向服务器发送POST请求,直到客户端收到服务器的响应才会建立连接:

Client request:

{
   "connectionId":"807809a5-31bf-470d-9e23-afaee35d8a0d",
   "availableTransports":[
   {
      "transport": "WebSockets",
      "transferFormats": [ "Text", "Binary" ]
    },
    {
      "transport": "ServerSentEvents",
      "transferFormats": [ "Text" ]
    },
    {
      "transport": "LongPolling",
      "transferFormats": [ "Text", "Binary" ]
    }
    ]
}

Server response:

{
   "url": "https://myapp.com/chat",
   "accessToken": "accessToken"
}

为了避免使用粘性会话,客户端需要跳过协商,但仅限于使用WebSocket.

另一件需要注意的事情是,AutomaticReconnect方法的缺省值为[0,2000,10000,30000,NULL].这意味着,如果客户端与服务器断开连接,它将分别等待0、2、10和30秒,然后再try 重新连接.如果在这一点上没有重新连接,它将停止try .如果您希望您的客户端try 无限地重新连接,则必须创建您自己的重试策略:

public class RetryPolicyLoop : IRetryPolicy
{
    private const int ReconnectionWaitSeconds = 5;

    public TimeSpan? NextRetryDelay(RetryContext retryContext)
    {
        return TimeSpan.FromSeconds(ReconnectionWaitSeconds);
    }
}

在您的HubConnectionBuilder中:

.WithAutomaticReconnect(new RetryPolicyLoop())

这样,您的客户端将无限期地try 重新连接(每次try 失败后等待5秒).

EDIT:

资料来源: https://github.com/aspnet/SignalR/blob/release/2.2/specs/TransportProtocols.md

Csharp相关问答推荐

C#将参数传递给具有变化引用的变量

如何从泛型方法返回一个可为空的T,其中T:notnull?

使用LINQ to XML获取元素值列表是不起作用的

(乌龙)1&#比c#中的UL&#慢吗?

C#方法从AJAX调用接收NULL

实体框架核心中的ComplexType和OwnsOne有什么不同?

使用HttpResponseMessage中的嵌套列表初始化JSON

当用户右键单击文本框并单击粘贴时触发什么事件?

我的MRG32k3a算法实现返回的数字超出了预期的[0,1]范围

DbContext-传递自定义配置选项

当空判断结果赋给变量时,为什么会出现可能空异常警告的解引用?

是否可以在Entity Framework Core中使用只读 struct 作为拥有实体?

如何在Polly重试策略成功之前将HttpClient请求排队?

C#使用相同内存的多个数组

为什么我在使用有效令牌的情况下仍未获授权?

如何在.NET MAUI上在iOS和Mac之间共享代码?(no条件编译和无代码重复)

避免在特定区域中设置Visual Studio代码的自动格式

如何在C#中反序列化Java持续时间?

身份验证中间件如何处理多个方案

带有类约束的C#泛型