【问题标题】:Get number of listeners, clients connected to SignalR hub获取连接到 SignalR 集线器的侦听器和客户端的数量
【发布时间】:2012-11-10 22:38:49
【问题描述】:

有没有办法找出侦听器的数量(连接到集线器的客户端?)

如果至少连接了一个客户端,我正在尝试运行/启动一项任务,否则不要启动它:

[HubName("taskActionStatus")]
public class TaskActionStatus : Hub, IDisconnect
{
    static CancellationTokenSource tokenSource;

    public void GetTasksStatus(int? siteId)
    {
        tokenSource = new CancellationTokenSource();
        CancellationToken ct = tokenSource.Token;

        ITaskRepository taskRepository = UnityContainerSetup.Container.Resolve<ITaskRepository>();

        // init task for checking task statuses
        var tasksItem = new DownloadTaskItem();
        taskRepository.GetTasksStatusAsync(siteId, tasksItem, ct);

        // subscribe to event [ listener ]
        tasksItem.Changed += new EventHandler<TaskEventArgs>(UpdateTasksStatus);
    }

    public void UpdateTasksStatus(object sender, TaskEventArgs e)
    {
        Clients.updateMessages(e.Tasks);
    }

    // when browsing away from page
    public Task Disconnect()
    {
        try
        {
            tokenSource.Cancel();
        }
        catch (Exception)
        {
            //
        }

        return null;
    }
}

谢谢

【问题讨论】:

标签: c# asp.net asp.net-mvc-3 signalr signalr-hub


【解决方案1】:

没有办法从 SignalR 获得这个计数。您必须使用 Hub 上的 OnConnect()OnDisconnect() 方法自己保持计数。

使用静态类保存计数的简单示例:

public static class UserHandler
{
    public static HashSet<string> ConnectedIds = new HashSet<string>();
}

public class MyHub : Hub
{
    public override Task OnConnectedAsync()
    {
        UserHandler.ConnectedIds.Add(Context.ConnectionId);
        return base.OnConnectedAsync();
    }

    public override Task OnDisconnectedAsync(Exception exception)
    {
        UserHandler.ConnectedIds.Remove(Context.ConnectionId);
        return base.OnDisconnectedAsync(exception);
    }
}

然后您从UserHandler.ConnectedIds.Count 获取计数。

【讨论】:

  • +1 只记得在应用程序域重新启动时该对象将被重置;您应该考虑在某个时候持久化该对象;我通常每次添加或删除某人时都会这样做。
  • 如果您只打算运行一台服务器,则使用这样的静态类可以正常工作,但如果您在云中并且在多台服务器之间使用负载平衡器,则此解决方案将失败。但是,您可以使用缓存服务器来存储连接的用户。我们使用托管在 Azure 中的 Redis。
  • @Anj 运行 SignalR 本身的服务器,即应用服务器。这不是你最大的担心,但这是一个担心。您可以保存有关侦听器的更多信息,而不仅仅是一个计数器,并实现一个应用程序级的心跳来删除孤立的客户端。然而实际上这样的信息必须存在于 SignalR 中,但是(正如 MS 所说)你不能通过设计查询它。
  • 不要忘记在 SignalR 2.2.1 中覆盖 OnReconnected。如果客户端使用相同的 connection_id 重新连接,则不会调用 OnConnect。
  • static HashSet&lt;string&gt; ConnectedIds 似乎根本不是线程安全的。
【解决方案2】:

对于版本 2.1.1

public static class UserHandler
{
    public static HashSet<string> ConnectedIds = new HashSet<string>();
}

public class MyHub : Hub
{
    public override Task OnConnected()
    {
        UserHandler.ConnectedIds.Add(Context.ConnectionId);
        return base.OnConnected();
    }

    public override Task OnDisconnected(bool stopCalled)
    {
        UserHandler.ConnectedIds.Remove(Context.ConnectionId);
        return base.OnDisconnected(stopCalled);
    }
}

【讨论】:

  • 在服务器分片的情况下要小心。更喜欢使用 Cache 或 Db 来存储你的慢跑。
  • 请记住,如果您的服务器应用程序在 Azure 中运行并且它是垂直扩展的,那么这将不起作用。您需要像 Redis 这样的共享缓存或 SQL/NoSQL 数据库(或任何其他共享资源)来跟踪连接。
  • 现在你需要 OnConnectedAsync 和 OnDisconnectedAsync
  • 据我所知,HasSet 不是线程安全的,因此我认为我们需要在这种方法中进行一些同步,同时访问 ConnectedIds
【解决方案3】:

在 SIGnalR(2.4.1 版)中,这相当简单:

public int GetOnline()
{
   return GlobalHost.DependencyResolver.Resolve<ITransportHeartbeat>().GetConnections().Count;
}

只需从客户端调用此方法(:

【讨论】:

    【解决方案4】:

    现在你需要:

    public override Task OnConnectedAsync()
    {
        UserHandler.ConnectedIds.Add(Context.ConnectionId);
    
        return base.OnConnectedAsync();
    }
    
    public override Task OnDisconnectedAsync(Exception exception)
    {
        UserHandler.ConnectedIds.Remove(Context.ConnectionId);
        return base.OnDisconnectedAsync(exception);
    }
    

    【讨论】:

    • 恕我直言,也许您应该编辑已接受的答案而不是添加新答案?保持线程清洁以减少答案。此外,人们更有可能抓住第一个(在这种情况下,被接受)的答案。
    【解决方案5】:

    我想补充一点,如果您使用 Azure Functions 和 Azure SignalR 服务的无服务器解决方案,则会出现以下已解决问题:https://github.com/Azure/azure-functions-signalrservice-extension/issues/54

    它指的是这个示例,您可以在其中使用事件网格来获取连接的实时计数,非常棒。 https://github.com/aspnet/AzureSignalR-samples/tree/master/samples/EventGridIntegration

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-08
      • 2019-10-07
      相关资源
      最近更新 更多