在负载均衡器后面使用多个 SignalR 服务器进行客户端管理
clients managment with multi SignalR servers behind a load balancer
假设我有 2 个股票代码服务器,它们将报价推送到 Web 浏览器客户端。 2 台服务器位于负载均衡器(循环模式)后面。
考虑以下情况:
客户端 A 订阅 Server1 上的 Google 股票,如下所示:Groups.Add(Context.ConnectionId, "Google");
客户端 B 在服务器 2 上订阅雅虎股票:Groups.Add(Context.ConnectionId, "Yahoo");
客户端 C 在 Server2 上订阅 Google 股票:Groups.Add(Context.ConnectionId, "Google");
现在两台服务器都已经与股票市场同步,所以当股票更新时,它们都会实时获得更新。
我的问题是:
当服务器 2 像这样推送新更新时:
Clients.Group("Google").tick(quote);
它将向哪些客户发送消息?它会永远是客户C吗?我猜不是,我们之间有一个负载平衡器,所以在给定时间连接的客户端可能会改变,对吧?现在可能是 C,但下一个勾号可能是客户端 A&C 或仅 A。Web 套接字的连接应该保持打开状态,那么负载均衡器将如何处理它,它是否始终将连接从 1 个客户端转发到特定服务器?
背板在这里帮不了我,因为我的 2 个服务器已经同步并且会同时发送相同的消息。所以如果我强迫他们通过背板将消息路由到另一台服务器,它最终会向客户端发送重复的消息,如下所示:
服务器 1 在 10:00 获得代码 X 到 Google --> 路由到背板 --> 路由到服务器 2
服务器 2 在 10:00--> 到背板的路由 --> 到服务器 1
的路由到 Google 获得代码 X
服务器 1 向他的客户发送 2 X Google 代码
服务器 2 发送 2 X Google 代码给他的客户
好的,最终我通过共享缓存 (Redis) 同步了所有组订阅,因此所有服务器都知道所有用户及其订阅。这样每个服务器都会知道他当前个客户注册的组,并推送相关数据。
更新:
经过深思熟虑,这就是我们最终要做的事情:
- 负载均衡器将为传入连接分配一个粘性会话,因此每个新连接都将有一个常量 SignalR 服务器。
- 第 1 部分将使 Redis 同步成为冗余,因为每个服务器都知道他的所有客户端。
- 如果出现 server\network 故障,SignalR 客户端将重新连接并由负载均衡器分配一个新的(如果服务器出现故障)服务器。
- 重新连接后,SignalR 客户端将重新订阅相关股票(如果故障发生在网络上并且负载平衡器将其重定向到旧的 SignalR 服务器,则可能是多余的,但我会接受)。
假设我有 2 个股票代码服务器,它们将报价推送到 Web 浏览器客户端。 2 台服务器位于负载均衡器(循环模式)后面。 考虑以下情况:
客户端 A 订阅 Server1 上的 Google 股票,如下所示:
Groups.Add(Context.ConnectionId, "Google");
客户端 B 在服务器 2 上订阅雅虎股票:
Groups.Add(Context.ConnectionId, "Yahoo");
客户端 C 在 Server2 上订阅 Google 股票:
Groups.Add(Context.ConnectionId, "Google");
现在两台服务器都已经与股票市场同步,所以当股票更新时,它们都会实时获得更新。
我的问题是:
当服务器 2 像这样推送新更新时:
Clients.Group("Google").tick(quote);
它将向哪些客户发送消息?它会永远是客户C吗?我猜不是,我们之间有一个负载平衡器,所以在给定时间连接的客户端可能会改变,对吧?现在可能是 C,但下一个勾号可能是客户端 A&C 或仅 A。Web 套接字的连接应该保持打开状态,那么负载均衡器将如何处理它,它是否始终将连接从 1 个客户端转发到特定服务器?
背板在这里帮不了我,因为我的 2 个服务器已经同步并且会同时发送相同的消息。所以如果我强迫他们通过背板将消息路由到另一台服务器,它最终会向客户端发送重复的消息,如下所示:
服务器 1 在 10:00 获得代码 X 到 Google --> 路由到背板 --> 路由到服务器 2 服务器 2 在 10:00--> 到背板的路由 --> 到服务器 1
的路由到 Google 获得代码 X服务器 1 向他的客户发送 2 X Google 代码 服务器 2 发送 2 X Google 代码给他的客户
好的,最终我通过共享缓存 (Redis) 同步了所有组订阅,因此所有服务器都知道所有用户及其订阅。这样每个服务器都会知道他当前个客户注册的组,并推送相关数据。
更新:
经过深思熟虑,这就是我们最终要做的事情:
- 负载均衡器将为传入连接分配一个粘性会话,因此每个新连接都将有一个常量 SignalR 服务器。
- 第 1 部分将使 Redis 同步成为冗余,因为每个服务器都知道他的所有客户端。
- 如果出现 server\network 故障,SignalR 客户端将重新连接并由负载均衡器分配一个新的(如果服务器出现故障)服务器。
- 重新连接后,SignalR 客户端将重新订阅相关股票(如果故障发生在网络上并且负载平衡器将其重定向到旧的 SignalR 服务器,则可能是多余的,但我会接受)。