【问题标题】:Unable to set connection timeout on a .NET SignalR Client HubConnection (dotnet core/signalr 2.2)无法在 .NET SignalR 客户端 HubConnection 上设置连接超时(dotnet core/signalr 2.2)
【发布时间】:2020-04-27 10:36:04
【问题描述】:

我在后台服务中使用 .NET SignalR 客户端(SignalR Core 2.2 和 DotNet Core 2.2)。在我的循环中,我检查我的连接对象是否已断开连接,如果是,则触发 ConnectAsync。

我正在尝试使用 SignalR 进行高可用性故障转移检测(以及其他事情,例如配置同步),因此有关远程主机关闭或变得不可用的时间至关重要。

我遇到的问题是,在 Linux 上,超时似乎没有正确响应。虽然我将所有可配置的超时设置为以秒为单位的非常短的激进时间,但在 Linux 上运行时需要几分钟才能超时。 Windows 似乎没有同样的问题。

if (_connection.State != HubConnectionState.Connected) {
    _connection = new HubConnectionBuilder()
        .ConfigureLogging(logging => {
            logging.SetMinimumLevel(LogLevel.Information);
            logging.AddConsole();
        })
        .WithUrl("https://" + settings.RemoteIP + ":" + settings.RemotePort + "/api/hub/ha", options => {
            options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets | Microsoft.AspNetCore.Http.Connections.HttpTransportType.ServerSentEvents;
            options.AccessTokenProvider = () => Task.FromResult(settings.RemoteJWT);         
            options.CloseTimeout = new TimeSpan(0, 0, 8);                       
        })
        .Build();

    _connection.HandshakeTimeout = new TimeSpan(0, 0, 5);
    _connection.ServerTimeout = new TimeSpan(0, 0, 10);
    _connection.KeepAliveInterval = new TimeSpan(0, 0, 5);

    _connection.On("ExampleEvent", async () =>
    {
        await ExampleProcessor(_logger, cancellation);
    });

    await _connection.StartAsync(cancellation);
}                               

在尝试连接到不可用的服务器后正好 120 秒后,我收到以下超时错误:

System.OperationCanceledException: The operation was canceled. at 
System.Net.Http.HttpClient.HandleFinishSendAsyncError(Exception e, CancellationTokenSource cts) at 
System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts) at 
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.NegotiateAsync(Uri url, HttpClient httpClient, ILogger logger) at 
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.GetNegotiationResponseAsync(Uri uri) at 
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.SelectAndStartTransport(TransferFormat transferFormat) at 
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsyncCore(TransferFormat transferFormat) at 
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsync(TransferFormat transferFormat, CancellationToken cancellationToken) at 
Microsoft.AspNetCore.SignalR.Client.HttpConnectionFactory.ConnectAsync(TransferFormat transferFormat, CancellationToken cancellationToken) at 
Microsoft.AspNetCore.SignalR.Client.HttpConnectionFactory.ConnectAsync(TransferFormat transferFormat, CancellationToken cancellationToken) at 
Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncCore(CancellationToken cancellationToken) at 
Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsync(CancellationToken cancellationToken) 

在 Windows 上,超时需要 21 秒,但出现不同的错误:

System.Net.Http.HttpRequestException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond ---> System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken) --- End of inner exception stack trace --- at 
System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken) at 
System.Threading.Tasks.ValueTask`1.get_Result() at 
System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken) at System.Threading.Tasks.ValueTask`1.get_Result() at 
System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask`1 creationTask) at System.Threading.Tasks.ValueTask`1.get_Result() at 
System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken) at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at 
Microsoft.AspNetCore.Http.Connections.Client.Internal.AccessTokenHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at Microsoft.AspNetCore.Http.Connections.Client.Internal.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at 
System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts) at 
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.NegotiateAsync(Uri url, HttpClient httpClient, ILogger logger) at 
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.GetNegotiationResponseAsync(Uri uri) at 
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.SelectAndStartTransport(TransferFormat transferFormat) at 
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsyncCore(TransferFormat transferFormat) at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsync(TransferFormat transferFormat, CancellationToken cancellationToken) at 
Microsoft.AspNetCore.SignalR.Client.HttpConnectionFactory.ConnectAsync(TransferFormat transferFormat, CancellationToken cancellationToken) at 
Microsoft.AspNetCore.SignalR.Client.HttpConnectionFactory.ConnectAsync(TransferFormat transferFormat, CancellationToken cancellationToken) at 
Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncCore(CancellationToken cancellationToken) at 
Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsync(CancellationToken cancellationToken)

我没有正确设置超时吗?还是 DotNet Core SignalR 2.2 存在潜在问题?

【问题讨论】:

  • 你的意思是你为连接设置了server timeout interval,当客户端应用在Linux上运行时,它不能正常工作?
  • 我不确定要为初始 ConnectAsync() 寻找哪个超时设置;如果远程服务器关闭并且我调用 ConnectAsync(),我希望它在几秒钟内超时,而不是几分钟。如果那是 ServerTimeout 设置,那么是的,它的行为不像预期的那样,真的是在 windows 或 linux 上 - linux 更糟糕。我不确定 Negotiate 超时不是初始超时,也不知道 CloseTimeout 的用途。
  • 这不是一个答案,但我只是想提一下 .NET Core 2.2 在December 23, 2019 已终止生命周期。您可能需要考虑更新到 Core 3.1,看看您的问题在该设置中是否仍然存在。

标签: c# asp.net-core .net-core signalr.client asp.net-core-signalr


【解决方案1】:

我遇到了同样的问题。

我的(也许不是最好的)解决方法是:

Task hubConnection = _hubConnection.StartAsync();
Task timeout = Task.Delay(ThreeSeconds);

await Task.WhenAny(hubConnection, timeout);

if (_hubConnection.State != HubConnectionState.Connected)
{
    return false;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-06
    • 1970-01-01
    相关资源
    最近更新 更多