首页 > 解决方案 > SignalR(原始)不向客户端发送消息

问题描述

我们正在使用 SignalR(原始版本,而不是核心版本)并注意到一些莫名其妙的行为。我们的情况如下:

  1. 我们有一个通过 GenericCommand() 方法接受命令的集线器(见下文)。
  2. 这些命令使用 NServiceBus 放置在消息总线上
  3. 命令的执行产生一个事件
  4. 事件处理程序导致向所有 SignalR 客户端发送消息(见下文)

使用 Chrome 中的调试器工具查看 Websocket 消息,很明显有时(但不总是) “InvokeToAll”消息永远不会发送到任何客户端。不会抛出任何错误,所有连接的客户端只会发送它们的心跳信号,表明它们仍然连接。

此外,服务器上的跟踪(见下文)日志表明连接始终处于活动状态,但出于某种原因,立即从集线器发送的三个测试“已接收”消息被发送回客户端,但是从事件处理程序发送的结果“InvokeToAll”由于某种原因没有使用 Websocket 发送。我们知道事件处理程序被调用是因为_notificationService.MarkAsDone()调用在数据库中留下了确认它被调用的痕迹。

我们注意到的最后一件事是,此设置有效并且有效,直到无效为止。一旦消息停止发送给客户端,它就会一直停止发送给所有客户端。我们完全不知道可能会发生什么,或者我们还能做些什么来进一步调试它。没有错误被抛出,并且可以正常工作的东西突然停止工作,恕不另行通知......

任何帮助或指示将不胜感激。

这是集线器的代码(步骤 1):

public async Task GenericCommand(GenericEventData data) {
    await _messageBus.PublishEvent(new GenericSignalrCommandReceivedEvent {
        CorrelationId = Guid.Parse(data.CorrelationId),
        Command = data.Command,
        DataJson = data.DataJson,
        ConnectionId = Context.ConnectionId
    });

    // Added for debugging purposes
    var ctx = GlobalHost.ConnectionManager.GetHubContext<EventHub>();
    IClientProxy proxy = ctx.Clients.Client(Context.ConnectionId);
    await proxy.Invoke(data.CorrelationId, "Received - ConnectionId");

    proxy = ctx.Clients.User(Context.User.Identity.Name);
    await proxy.Invoke(data.CorrelationId, "Received - Clients.User");
    proxy = ctx.Clients.Group("JCUSER:" + Context.User.Identity.Name);
    await proxy.Invoke(data.CorrelationId, "Received - Clients.Group");
}

这是事件处理程序的代码(第 4 步)

private async Task ReplyViaSignalR(SignalrCompletedData data, IMessageHandlerContext context) {
    var ctx = GlobalHost.ConnectionManager.GetHubContext<EventHub>();
    var proxy = ctx.Clients.All;
    await proxy.Invoke("InvokeToAll", "Yay message received!");
    await _notificationService.MarkAsDone(data);
}

以下是此客户端连接的服务器上跟踪日志的摘录:

SignalR.Transports.TransportHeartBeat Information: 0 : Connection 1d603a67-1161-4a27-82f0-9046ec73cd60 is New.
SignalR.Transports.WebSocketTransport Verbose: 0 : Sending outgoing message. Connection id: 1d603a67-1161-4a27-82f0-9046ec73cd60, transport: WebSocketTransport, message: {"C":"d-498F7600-B,15|rS,0|pP,A|rT,1","S":1,"M":[]}
SignalR.Transports.WebSocketTransport Verbose: 0 : Sending outgoing message. Connection id: 1d603a67-1161-4a27-82f0-9046ec73cd60, transport: WebSocketTransport, message: {"C":"d-498F7600-B,15|rS,0|pP,A|rT,2|pR,1E","G":"F2q+KKxufchVxQUnH9leeyYR6fGPfHYRCIQW55XZbNEbbibRlbVYld/b0fzihC34VrDwmoaNy2uTJYnRCeQO9zGEoqNk+9qbAi72dPep52CgpicyPGQOlvNzUOlNK1v2j34SdPXHI8DwpDwx/7SA317XJMJPxrCE5Qsgt/kgTzE=","M":[]}
SignalR.Transports.TransportHeartBeat Verbose: 0 : KeepAlive(1d603a67-1161-4a27-82f0-9046ec73cd60)
SignalR.Transports.TransportHeartBeat Verbose: 0 : KeepAlive(1d603a67-1161-4a27-82f0-9046ec73cd60)
SignalR.Transports.TransportHeartBeat Verbose: 0 : KeepAlive(1d603a67-1161-4a27-82f0-9046ec73cd60)
SignalR.Transports.TransportHeartBeat Verbose: 0 : KeepAlive(1d603a67-1161-4a27-82f0-9046ec73cd60)
SignalR.Transports.WebSocketTransport Verbose: 0 : Sending outgoing message. Connection id: 1d603a67-1161-4a27-82f0-9046ec73cd60, transport: WebSocketTransport, message: {"C":"d-498F7600-B,1F|rS,5|pP,19|rT,2|pR,43","M":[{"H":"EventHub","M":"a1ec2fa6-f33c-4161-9166-07ee64558be1","A":["Received - ConnectionId"]},{"H":"EventHub","M":"a1ec2fa6-f33c-4161-9166-07ee64558be1","A":["Received - Clients.User"]}]}
SignalR.Transports.WebSocketTransport Verbose: 0 : Sending outgoing message. Connection id: 1d603a67-1161-4a27-82f0-9046ec73cd60, transport: WebSocketTransport, message: {"C":"d-498F7600-B,1F|rS,5|pP,19|rT,2|pR,44","M":[{"H":"EventHub","M":"a1ec2fa6-f33c-4161-9166-07ee64558be1","A":["Received - Clients.Group"]}]}
SignalR.Transports.WebSocketTransport Verbose: 0 : Sending outgoing message. Connection id: 1d603a67-1161-4a27-82f0-9046ec73cd60, transport: WebSocketTransport, message: {"I":"4"}
SignalR.Transports.WebSocketTransport Verbose: 0 : Sending outgoing message. Connection id: 1d603a67-1161-4a27-82f0-9046ec73cd60, transport: WebSocketTransport, message: {"C":"d-498F7600-B,1F|rS,5|pP,19|rT,2|pR,45","M":[]}
SignalR.Transports.TransportHeartBeat Verbose: 0 : KeepAlive(1d603a67-1161-4a27-82f0-9046ec73cd60)
SignalR.Transports.TransportHeartBeat Verbose: 0 : KeepAlive(1d603a67-1161-4a27-82f0-9046ec73cd60)
SignalR.Transports.TransportHeartBeat Verbose: 0 : KeepAlive(1d603a67-1161-4a27-82f0-9046ec73cd60)

标签: signalrnservicebus

解决方案


事实证明,这个问题是因为我们在同一个应用程序池中有多个站点使用不同的主机名指向同一个目录。

这导致应用程序运行该站点的多个并发实例,尽管只显示了一个 w3wp.exe 进程(我们认为这是为了消除同时运行多个实例的可能性)。

我们计划在有机会时通过简单地将绑定组合到同一个网站实例来改变这种情况。我完全期望到那时问题会得到解决。


推荐阅读