用于聊天场景的 Azure 的 SignalR 横向扩展

SignalR scaleout with Azure for chat scenario

对于聊天应用程序,我使用带有 SignalR 的 Azure 架构,网络角色充当 SignalR 服务器(消息不是广播类型,而是针对特定 user/client)。

我想扩展 SignalR 服务器以及网络角色,以处理繁重的用户负载。虽然,SignalR 文档不建议在消息数量随着更多用户连接(或用户事件驱动的场景)而增加的情况下使用使用背板(Redis、服务总线)的预烘焙 SignalR 横向扩展方法。它明确指出:"Client-to-client (e.g., chat): In this scenario, the backplane might be a bottleneck if the number of messages scales with the number of clients; that is, if the rate of messages grows proportionally as more clients join."

问题: 有谁知道针对这种高频情况的任何自定义横向扩展解决方案,它不会将消息推送到每个服务器实例或其他一些横向扩展解决方案?

已经在 SignalR 文档和相关视频中到处查看,但找不到任何东西,除了一个词 "filtered-bus",没有解释它是什么以及应该如何使用。

我自己想出来了:基本思路是服务器 affinity/sticky 会话。

Web 角色的每个实例都充当独立的 SignalR 服务器。在第一次连接时,我让 Azure 负载均衡器选择任何 web 角色实例,并将该 web 角色实例的 IP 地址与客户端标识符保存在映射中。如果有来自同一个客户端的另一个连接请求(例如在页面刷新之后),那么我检查当前角色实例的 IP 地址,如果它与映射中的条目匹配,那么我让它继续,否则我断开客户端并将它连接到网络角色的正确实例。

worker-role 的每个实例还充当 SignalR .net 客户端并连接到所有可用的 SignalR 服务器(所有 web-role 实例)。在向 SignalR 服务器(网络角色)发送消息之前,我在地图中查找以确定正确的 SignalR 服务器实例(取决于预期的 JS 接收者)。

好处:

  • 不需要背板技术(因此不会延迟消息传递)。

  • 每个 web 角色实例都关心连接到它的客户端,并且不必在每个 SignalR 服务器上复制每条消息。因此它可以很好地扩展。

  • 易于实施。