在不广播 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 计时器为用户获取最新状态等解决方案不干净或不可取。
我担心在我的 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 计时器为用户获取最新状态等解决方案不干净或不可取。