3

服务器广播如下消息:

protected override Task OnReceived(IRequest request, string connectionId, string data)
{
    if (_messagesToSent == 0)
    {
        int.TryParse(data, out _messagesToSent);
    }
    else
        return Task.Delay(0);

    // Broadcast data to all clients
    return new TaskFactory().StartNew(() =>
        {
            _log.InfoFormat("Starting broadcasting of {0} messages.", _messagesToSent);
            int sentMessages = 0;

            if (_messagesToSent > 0)
                Connection.Broadcast(GetInfoMessage());

            while (_messagesToSent > 0)
            {
                Connection.Broadcast(GetDataMessage(sentMessages));
                _messagesToSent--;
                sentMessages++;
                if (sentMessages % 1000 == 0)
                    _log.InfoFormat("{0} messages of total {1} messages sent.", sentMessages,
                                    sentMessages + _messagesToSent);
            }
            _log.InfoFormat("{0} messages were sent.", sentMessages);
        });
}

基本思想是在开始时服务器从客户端接收消息以及要发送的消息数。然后在 while 循环中,它会广播这么多消息并进行一些日志记录。客户端也很简单,它只计算接收到的消息数量并记录输入数据:

private void ConnectionOnReceived(string s)
{
    ReceivedMessagesCount++;
    _log.Info(s);
}

我做了几个测试:

  • 广播多达 1000 条消息工作正常,客户端接收所有消息
  • 广播 2000 条消息,客户端只收到大约 1500 条消息
  • 广播 10K 条消息,收到的 1500-1600 条消息相同

当服务器托管在云服务中时,测试是在本地和 Azure 上执行的。

那么,我做错了什么?我是否错过了配置中的某些内容或其他内容?

4

1 回答 1

3

您发送消息的速度比您的客户接收它们的速度快,导致您的客户错过消息。

当广播 1000 条或更少的消息时,您的客户端会收到所有消息,因为 SignalR 的 aDefaultMessageBufferSize为 1000。这可以通过 SignalR 进行更改IConfigurationManager,例如:

GlobalHost.Configuration.DefaultMessageBufferSize = 2000;

然而,改变DefaultMessageBufferSize只是一个创可贴,因为如果你持续发送消息的速度比你的客户端接收它们的速度快,你将超出任何大小的缓冲区。

真正的解决方案涉及限制您发送消息的速率。这种限制可以通过让您的客户端定期向您发送 ACK 来PersistentConnection指示它已收到多少消息来实现。

于 2013-03-17T12:13:20.830 回答