SignalR 调用方法不适用于受限连接
SignalR invoke method doesn't work on throttled connections
我有一个带有 SignalR 的 .net 核心后端和一个反应前端。我有一个使用 ConcurrentDictionary 设置的基本集线器来管理连接 ID:
namespace backend.Hubs
{
public class OrderHub : Hub, IOrderHub
{
private readonly IHubContext<OrderHub> hubContext;
public static ConcurrentDictionary<string, List<string>> ConnectedUsers = new ConcurrentDictionary<string, List<string>>();
public OrderHub(IHubContext<OrderHub> hubContext)
{
this.hubContext = hubContext;
}
public async Task SendMessage(OrderResponseDto order, string id)
{
List<string> connectedUser = null;
ConnectedUsers.TryGetValue(id, out connectedUser);
await hubContext.Clients.Clients(connectedUser).SendAsync("neworder",order);
}
public void AddMapping(string id)
{
List<string> existingUserConnectionIds;
ConnectedUsers.TryGetValue(id, out existingUserConnectionIds);
if (existingUserConnectionIds == null)
{
existingUserConnectionIds = new List<string>();
}
existingUserConnectionIds.Add(Context.ConnectionId);
ConnectedUsers.TryAdd(id, existingUserConnectionIds);
}
public override Task OnDisconnectedAsync(Exception e)
{
List<string> existingUserConnectionIds = null;
foreach(var val in ConnectedUsers.Values)
{
if (val.Contains(Context.ConnectionId))
{
existingUserConnectionIds = val;
break;
}
}
if (existingUserConnectionIds != null)
{
existingUserConnectionIds.Remove(Context.ConnectionId);
}
var keys = ConnectedUsers.Where(en => en.Value.Count == 0).Select(k => k.Key);
foreach(var key in keys)
{
List<string> garb = null;
ConnectedUsers.TryRemove(key, out garb);
}
return base.OnDisconnectedAsync(e);
}
}
}
在前端,我建立连接并调用 AddMapping
方法将客户端连接 ID 保存到并发字典中。当前端的开发人员控制台中未启用节流时,一切正常。但是,如果我将限制更改为慢速或快速 3g,我会遇到一个奇怪的问题。连接像往常一样建立,我调用该方法。通过.net core 中的调试,我看到在后端调用了该方法,但是该值未保存在并发字典中,也没有 return 任何内容。 React 客户端认为连接丢失并重新连接。具体来说,我收到以下错误:
此错误仅在我尝试从受限连接的客户端调用集线器方法时发生。在不受限制的连接上,它工作正常。
其他客户端代码:
const newConnection = new HubConnectionBuilder()
.withUrl(env.realtimeBaseUrl+'orderhub', {
// skipNegotiation: true,
// transport: HttpTransportType.WebSockets
})
.withAutomaticReconnect()
.build();
newConnection.start().then(r => {
fetchOrders()
setConnectionStatus(connectingForFirstTime);
newConnection.invoke("AddMapping",business.id.toString()).then(res=>{
console.log(res)
setConnection(newConnection);
setConnectionStatus(connected)
})
newConnection.on("neworder",(order)=>{
// data handling
})
newConnection.onreconnecting(()=>setConnectionStatus(reconnecting))
newConnection.onreconnected(()=>{
newConnection.invoke("AddMapping",business.id.toString()).then(res=>{
console.log(res)
setConnection(newConnection);
setConnectionStatus(connected)
})
});
newConnection.onclose(()=>setConnection(null));
}).catch(err => setConnectionStatus(off));
我刚刚在我的一个网站上尝试过,开发工具执行节流的方式似乎会中断 websocket 连接,以至于它似乎无法正常工作 bi-directionally 无论它是否在 slow3g 上或fast3g模拟。我可以在我的其他工作站点上重现您的错误。我怀疑是模拟器,不是你的代码。
我有一个带有 SignalR 的 .net 核心后端和一个反应前端。我有一个使用 ConcurrentDictionary 设置的基本集线器来管理连接 ID:
namespace backend.Hubs
{
public class OrderHub : Hub, IOrderHub
{
private readonly IHubContext<OrderHub> hubContext;
public static ConcurrentDictionary<string, List<string>> ConnectedUsers = new ConcurrentDictionary<string, List<string>>();
public OrderHub(IHubContext<OrderHub> hubContext)
{
this.hubContext = hubContext;
}
public async Task SendMessage(OrderResponseDto order, string id)
{
List<string> connectedUser = null;
ConnectedUsers.TryGetValue(id, out connectedUser);
await hubContext.Clients.Clients(connectedUser).SendAsync("neworder",order);
}
public void AddMapping(string id)
{
List<string> existingUserConnectionIds;
ConnectedUsers.TryGetValue(id, out existingUserConnectionIds);
if (existingUserConnectionIds == null)
{
existingUserConnectionIds = new List<string>();
}
existingUserConnectionIds.Add(Context.ConnectionId);
ConnectedUsers.TryAdd(id, existingUserConnectionIds);
}
public override Task OnDisconnectedAsync(Exception e)
{
List<string> existingUserConnectionIds = null;
foreach(var val in ConnectedUsers.Values)
{
if (val.Contains(Context.ConnectionId))
{
existingUserConnectionIds = val;
break;
}
}
if (existingUserConnectionIds != null)
{
existingUserConnectionIds.Remove(Context.ConnectionId);
}
var keys = ConnectedUsers.Where(en => en.Value.Count == 0).Select(k => k.Key);
foreach(var key in keys)
{
List<string> garb = null;
ConnectedUsers.TryRemove(key, out garb);
}
return base.OnDisconnectedAsync(e);
}
}
}
在前端,我建立连接并调用 AddMapping
方法将客户端连接 ID 保存到并发字典中。当前端的开发人员控制台中未启用节流时,一切正常。但是,如果我将限制更改为慢速或快速 3g,我会遇到一个奇怪的问题。连接像往常一样建立,我调用该方法。通过.net core 中的调试,我看到在后端调用了该方法,但是该值未保存在并发字典中,也没有 return 任何内容。 React 客户端认为连接丢失并重新连接。具体来说,我收到以下错误:
此错误仅在我尝试从受限连接的客户端调用集线器方法时发生。在不受限制的连接上,它工作正常。
其他客户端代码:
const newConnection = new HubConnectionBuilder()
.withUrl(env.realtimeBaseUrl+'orderhub', {
// skipNegotiation: true,
// transport: HttpTransportType.WebSockets
})
.withAutomaticReconnect()
.build();
newConnection.start().then(r => {
fetchOrders()
setConnectionStatus(connectingForFirstTime);
newConnection.invoke("AddMapping",business.id.toString()).then(res=>{
console.log(res)
setConnection(newConnection);
setConnectionStatus(connected)
})
newConnection.on("neworder",(order)=>{
// data handling
})
newConnection.onreconnecting(()=>setConnectionStatus(reconnecting))
newConnection.onreconnected(()=>{
newConnection.invoke("AddMapping",business.id.toString()).then(res=>{
console.log(res)
setConnection(newConnection);
setConnectionStatus(connected)
})
});
newConnection.onclose(()=>setConnection(null));
}).catch(err => setConnectionStatus(off));
我刚刚在我的一个网站上尝试过,开发工具执行节流的方式似乎会中断 websocket 连接,以至于它似乎无法正常工作 bi-directionally 无论它是否在 slow3g 上或fast3g模拟。我可以在我的其他工作站点上重现您的错误。我怀疑是模拟器,不是你的代码。