SignalR 不适用于负载平衡
SignlaR not working with load balancing
我们已经有一个带有 signalr hub 的服务器,客户端使用 signalr 进行连接。我们最近将其移动到带有负载均衡器的两个节点以实现可扩展性。但是在将它移动到负载平衡器之后,现在客户端无法使用信号器连接到服务器。客户端首先尝试使用网络套接字,它在信号器跟踪中给出以下错误。
fae26beb-a806-4957-b52a-39b80856e492 - Auto: Failed to connect to using transport webSockets. System.Net.WebSockets.WebSocketException (0x80004005): Unable to connect to the remote server ---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
--- End of inner exception stack trace ---
at System.Net.Security._SslStream.EndRead(IAsyncResult asyncResult)
at System.Net.TlsStream.EndRead(IAsyncResult asyncResult)
at System.Net.PooledStream.EndRead(IAsyncResult asyncResult)
at System.Net.Connection.ReadCallback(IAsyncResult asyncResult)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.WebSockets.ClientWebSocket.<ConnectAsyncCore>d__21.MoveNext()
at System.Net.WebSockets.ClientWebSocket.<ConnectAsyncCore>d__21.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.SignalR.Client.Transports.WebSocketTransport.<PerformConnect>d__1.MoveNext()
但在尝试连接几次后,它设法使用 SSE(服务器发送的事件)进行连接。
fae26beb-a806-4957-b52a-39b80856e492 - SSE: OnMessage(Data: {"C":"s-0,BA9F","S":1,"M":[]})
fae26beb-a806-4957-b52a-39b80856e492 - ChangeState(Connecting, Connected)
fae26beb-a806-4957-b52a-39b80856e492 - SSE: OnMessage(Data: {"C":"s-0,BAA0","M":[{"H":"PrintConnectorHub","M":"SignalRConnectedSuccessfully","A":[true]}]})
fae26beb-a806-4957-b52a-39b80856e492 - OnMessage({"R":false,"I":"3"})
但是当服务器试图将消息发送回客户端时,客户端收不到消息。我们已经使用 SQL 服务器实现了 SignalR 横向扩展,以下是服务器中的日志跟踪。
TRACE SignalR.SqlMessageBus Stream 0 : SqlReceiver last payload ID=47781, new payload ID=47782 (Microsoft.AspNet.SignalR.SqlServer.SqlReceiver.ProcessRecord)
TRACE SignalR.SqlMessageBus Stream 0 : Updated receive reader initial payload ID parameter=47782 (Microsoft.AspNet.SignalR.SqlServer.SqlReceiver.ProcessRecord)
TRACE SignalR.SqlMessageBus Stream 0 : Payload 47782 containing 1 message(s) received (Microsoft.AspNet.SignalR.SqlServer.SqlReceiver.ProcessRecord)
TRACE SignalR.SqlMessageBus Stream 0 : 1 records received (Microsoft.AspNet.SignalR.SqlServer.ObservableDbOperation.ExecuteReaderWithUpdates)
TRACE SignalR.SqlMessageBus Created DbCommand: CommandType=Text, CommandText=SELECT [PayloadId], [Payload], [InsertedOn] FROM [SignalR].[Messages_0] WHERE [PayloadId] > @PayloadId, Parameters= [Name=PayloadId, Value=47782] (Microsoft.AspNet.SignalR.SqlServer.DbOperation.TraceCommand)
客户端中的信号器初始化
signalrHostUrl = "SignalR_Host";
try
{
hubConnection = new HubConnection(signalrHostUrl);
hubConnection.Error += ex =>
{
signalRlogger.Error(ex, "Exception from hubConnection");
};
hubConnection.ConnectionSlow += () => ConnectionSlow();
hubConnection.Closed += () => SignalrConnectionConnectionClosed();
hubConnection.StateChanged += signalRConnectionStateController.StateChanged;
hubConnection.Start().Wait();
}
catch (Exception ex)
{
signalRlogger.Error(ex, "initialzing hub connection");
}
在迁移到负载均衡器之前,客户端完全能够通过网络套接字进行连接和通信。但是在移动到负载平衡器之后,它完全无法通过网络套接字进行连接。我们甚至尝试通过此工具 (https://chrome.google.com/webstore/detail/simple-websocket-client/pfdhoblngboilpfeibdedpjgfnlcodoo?hl=en) 打开网络套接字连接,但也无法打开连接。虽然它设法通过 SSE 连接,但它仍然无法与客户端通信。在负载平衡中使用 Web 套接字时会出现哪些问题?在这种情况下,为什么 signalr 无法连接到客户端?
当另一台机器试图解密您在协商连接时获得的连接令牌时,它无法解密并且请求失败。您需要确保您使用的所有机器都具有相同的机器密钥。这样所有机器都可以解密其他机器创建的连接令牌。
你能在负载平衡器上启用粘性吗?例如基于会话的粘性。这将确保客户端连接到同一台机器。缺点是如果一台机器出现故障,客户端将无法重新连接。
我们已经有一个带有 signalr hub 的服务器,客户端使用 signalr 进行连接。我们最近将其移动到带有负载均衡器的两个节点以实现可扩展性。但是在将它移动到负载平衡器之后,现在客户端无法使用信号器连接到服务器。客户端首先尝试使用网络套接字,它在信号器跟踪中给出以下错误。
fae26beb-a806-4957-b52a-39b80856e492 - Auto: Failed to connect to using transport webSockets. System.Net.WebSockets.WebSocketException (0x80004005): Unable to connect to the remote server ---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
--- End of inner exception stack trace ---
at System.Net.Security._SslStream.EndRead(IAsyncResult asyncResult)
at System.Net.TlsStream.EndRead(IAsyncResult asyncResult)
at System.Net.PooledStream.EndRead(IAsyncResult asyncResult)
at System.Net.Connection.ReadCallback(IAsyncResult asyncResult)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.WebSockets.ClientWebSocket.<ConnectAsyncCore>d__21.MoveNext()
at System.Net.WebSockets.ClientWebSocket.<ConnectAsyncCore>d__21.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.SignalR.Client.Transports.WebSocketTransport.<PerformConnect>d__1.MoveNext()
但在尝试连接几次后,它设法使用 SSE(服务器发送的事件)进行连接。
fae26beb-a806-4957-b52a-39b80856e492 - SSE: OnMessage(Data: {"C":"s-0,BA9F","S":1,"M":[]})
fae26beb-a806-4957-b52a-39b80856e492 - ChangeState(Connecting, Connected)
fae26beb-a806-4957-b52a-39b80856e492 - SSE: OnMessage(Data: {"C":"s-0,BAA0","M":[{"H":"PrintConnectorHub","M":"SignalRConnectedSuccessfully","A":[true]}]})
fae26beb-a806-4957-b52a-39b80856e492 - OnMessage({"R":false,"I":"3"})
但是当服务器试图将消息发送回客户端时,客户端收不到消息。我们已经使用 SQL 服务器实现了 SignalR 横向扩展,以下是服务器中的日志跟踪。
TRACE SignalR.SqlMessageBus Stream 0 : SqlReceiver last payload ID=47781, new payload ID=47782 (Microsoft.AspNet.SignalR.SqlServer.SqlReceiver.ProcessRecord)
TRACE SignalR.SqlMessageBus Stream 0 : Updated receive reader initial payload ID parameter=47782 (Microsoft.AspNet.SignalR.SqlServer.SqlReceiver.ProcessRecord)
TRACE SignalR.SqlMessageBus Stream 0 : Payload 47782 containing 1 message(s) received (Microsoft.AspNet.SignalR.SqlServer.SqlReceiver.ProcessRecord)
TRACE SignalR.SqlMessageBus Stream 0 : 1 records received (Microsoft.AspNet.SignalR.SqlServer.ObservableDbOperation.ExecuteReaderWithUpdates)
TRACE SignalR.SqlMessageBus Created DbCommand: CommandType=Text, CommandText=SELECT [PayloadId], [Payload], [InsertedOn] FROM [SignalR].[Messages_0] WHERE [PayloadId] > @PayloadId, Parameters= [Name=PayloadId, Value=47782] (Microsoft.AspNet.SignalR.SqlServer.DbOperation.TraceCommand)
客户端中的信号器初始化
signalrHostUrl = "SignalR_Host";
try
{
hubConnection = new HubConnection(signalrHostUrl);
hubConnection.Error += ex =>
{
signalRlogger.Error(ex, "Exception from hubConnection");
};
hubConnection.ConnectionSlow += () => ConnectionSlow();
hubConnection.Closed += () => SignalrConnectionConnectionClosed();
hubConnection.StateChanged += signalRConnectionStateController.StateChanged;
hubConnection.Start().Wait();
}
catch (Exception ex)
{
signalRlogger.Error(ex, "initialzing hub connection");
}
在迁移到负载均衡器之前,客户端完全能够通过网络套接字进行连接和通信。但是在移动到负载平衡器之后,它完全无法通过网络套接字进行连接。我们甚至尝试通过此工具 (https://chrome.google.com/webstore/detail/simple-websocket-client/pfdhoblngboilpfeibdedpjgfnlcodoo?hl=en) 打开网络套接字连接,但也无法打开连接。虽然它设法通过 SSE 连接,但它仍然无法与客户端通信。在负载平衡中使用 Web 套接字时会出现哪些问题?在这种情况下,为什么 signalr 无法连接到客户端?
当另一台机器试图解密您在协商连接时获得的连接令牌时,它无法解密并且请求失败。您需要确保您使用的所有机器都具有相同的机器密钥。这样所有机器都可以解密其他机器创建的连接令牌。
你能在负载平衡器上启用粘性吗?例如基于会话的粘性。这将确保客户端连接到同一台机器。缺点是如果一台机器出现故障,客户端将无法重新连接。