获取连接到 SignalR 集线器的侦听器和客户端的数量

Posted

技术标签:

【中文标题】获取连接到 SignalR 集线器的侦听器和客户端的数量【英文标题】:Get number of listeners, clients connected to SignalR hub 【发布时间】: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;
    

谢谢

【问题讨论】:

看看***.com/questions/21066657/… 【参考方案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

【讨论】:

以上是关于获取连接到 SignalR 集线器的侦听器和客户端的数量的主要内容,如果未能解决你的问题,请参考以下文章

从 SignalR .NET 客户端连接到工作集线器时出现 HttpClientException

如何从 iOS 上的 PhoneGap 应用程序连接到 SignalR 集线器?

SignalR JavaScript客户端API调用连接

SignalR 控制台应用程序示例

建立连接时的 SignalR Core 调用函数

SignalR HubConnectionState = 正在连接