获取连接到 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<string> 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