在不广播 Clients.All.someMethod() 和炸毁客户端资源的情况下确定 Signal R 连接状态

Determine Signal R connection status without broadcasting Clients.All.someMethod() and blowing up client side resources

我担心在我的 C# Signal R 集线器中使用 Clients.All class

Clients.All.setConnectionStatus(profileId, true);

我在 OnConnected()OnDisconnected(bool stopCalled) 中都调用它 显示我登录用户的在线状态。 OnDisconnected() 没那么糟糕,因为只有在有人实际注销时才会调用它

例如

public override Task OnConnected()
{
   string profileId = Context.User.Identity.Name;
   _connections.Add(profileId, Context.ConnectionId);
    Clients.All.setConnectionStatus(profileId, true);
    return base.OnConnected();
 }

public override Task OnDisconnected(bool stopCalled)
{
    string profileId = Context.User.Identity.Name;
    _connections.Remove(profileId, Context.ConnectionId);
    if (stopCalled == false) // log off only
        Clients.All.setConnectionStatus(profileId, false);
     return base.OnDisconnected(stopCalled);
}

我的担忧 -> 在浏览器中使用 javascript 代码不断 运行 炸毁用户机器客户端!

场景 -> 如果我有 > ~1000 个用户在线并登录并遍历不同的页面,我将向他们所有人广播信号 R 连接 Clients.All.setConnectionStatus(profileId, true);

在 javascript 集线器中看起来像下面这样,很容易导致用户浏览器崩溃,因为它会不断收到这些广播连接状态调用!!!

scope.chat = $.connection.chatHub;

// Receive and set the connection status
scope.chat.client.setConnectionStatus = function(profileId, isConnected) {
  // look for prfileId in html
  var $profileStatusElement = $(".online-status-profile[data-id='" + profileId + "']");
  var $profileChatElement = $(".online-status-chat[data-id='" + profileId + "']");
  
  if (isConnected === true) {
    // change the online status
  } else {
    // change the online status
  }
};

我与如下用户(在线)聊天windows,在他们的名字旁边显示用户状态。所以我知道我要向其发送消息的人是否在线!

当我第一次加载聊天框时,我会在服务器端获取在线状态,但之后由我中心的 OnConnected()OnDisconnected() 方法来设置此人的在线状态我正在聊天。

是否有更好的方法将信号广播到我网站上的 'all' 在线用户?但我能想到的唯一方法是每隔一段时间在某个 javascript 计时器上轮询状态,但我讨厌这个主意!!

另一种方法是在内存中保存每个人正在与之聊天的人的某种集合,但这看起来可能会变得非常混乱并且最终可能不是很准确,因为可能是这样客户端和服务器之间的许多事情可能会导致中断,从而导致对谁连接到谁的内存集合管理不善!如有任何想法或想法,我们将不胜感激!!

仅供参考 -> 我还有一个消息页面,其中显示了我最近与用户进行的所有对话的列表,如下所示。在此页面上,我还显示了这些用户的在线状态。在这个页面上,我在呈现页面之前获取服务器上每个用户的在线状态,与聊天框相同,但是一旦加载页面,就由 OnConnected()OnDisconnected(bool stopCalled) 来设置页面上每个用户的在线状态。

您使用 signalR 的方式正确。我根据你的concerns/scenarios:

指导你

My concern -> Blowing up the users machine client side with javascript code constantly running in the browser!

不要忘记您正在使用浏览器底层功能 (WebSocket),所以我们别无选择,除非 运行 客户端加载页面中的一些 js 代码。您可以在这里利用浏览器功能。

Scenario -> If I have > ~1000 users online and logged in traversing to different pages, I will be broadcasting to all of them a signal R connection Clients.All.setConnectionStatus(profileId, true);

在提出任何解决方案之前,我建议您在申请中employ grouping logic分组减少了同步量

如果您在 public 聊天室(可能包含大量人员)中工作,只需采用服务器端策略,您就可以使代码一个肮脏的!是的,任何导航或刷新页面的用户都可能导致对所有客户端的冗余更新。 最佳解决方案是 将您的页面转到 SPA(使用 API 调用或 Ajax 调用)而不刷新页面。 我相信任何实时网络应用程序都应该利用现代网络技术。这将解决几乎所有您遇到的问题(例如,没有页面刷新、没有重新运行、没有断开连接等...)。

使用 js 计时器为用户获取最新状态等解决方案不干净或不可取。