20

每隔几个月,在考虑一个涉及套接字的个人项目时,我都会发现自己有一个问题:“如何在动态水平扩展的 WebSocket 服务器上正确地负载平衡套接字?”

我了解水平扩展 WebSocket 和使用 pub/sub 模型将数据获取到为特定用户保存套接字连接的正确服务器背后的理论。我想我了解有效识别具有最少当前套接字连接的服务器的方法,我也想路由一个新的套接字连接。我不明白的是如何有效地将新的套接字连接路由到您选择的具有低套接字数的服务器。

我不认为这个答案会与特定的服务器实现相关联,而是可以应用于大多数服务器。我可以很容易地看到自己使用 vert.x、node.js 甚至是完美的实现了这一点。

4

3 回答 3

28

首先,您需要定义您要询问的问题的范围。如果您真正谈论的是动态水平扩展,其中您根据总负载启动和关闭服务器,那么这比仅仅确定将最新传入的新套接字连接路由到哪里是一个更复杂的问题。

为了解决这个问题,您必须有一种将套接字从一个主机“移动”到另一个主机的方法,这样您就可以清除来自您想要降速的主机的连接(我在这里假设真正的动态缩放会上升和上升)向下)。我见过的通常方法是让一个合作的客户端参与进来,你告诉客户端重新连接,当它重新连接时,它会负载平衡到另一台服务器上,这样你就可以清除你想要关闭的服务器。如果您的客户端已经具有自动重新连接逻辑(如 socket.io 那样),您可以让服务器关闭连接,客户端将自动重新连接。

至于对传入客户端连接进行负载平衡,您必须决定要使用的负载指标。最终,您需要为每个服务器进程打一个分数,告诉您您认为它有多“忙”,这样您就可以将新连接放在最不忙的服务器上。基本分数只是当前连接的数量。如果您的每个服务器进程有大量连接(数万个),并且在您的应用程序中没有特别的理由表明有些人可能比其他人更忙,那么大数定律可能会平均负载,这样您就可以侥幸逃脱每个服务器有多少连接。如果连接的使用不是那么公平甚至不公平,那么您可能还必须考虑 CPU 负载的某种时间移动平均值以及连接总数。

如果您要跨多个物理服务器进行负载平衡,那么您将需要每个人最初都连接到的负载平衡器或代理服务,并且该代理可以查看池中所有当前正在运行的服务器的指标并将连接分配给当前分数最低的一个。这可以通过代理方案或(更具可扩展性)通过重定向来完成,以便代理在初始分配后不碍事。

然后,您还可以有一个流程,定期检查集群中所有服务器上的负载分数(无论您决定计算它),并决定何时启动新服务器或何时关闭或何时停止运行。给定服务器上的平衡,并且需要告诉该服务器关闭多个连接,迫使它们重新平衡。

我不明白的是如何有效地将新的套接字连接路由到您选择的具有低套接字数的服务器。

如上所述,您可以使用代理方案或重定向方案。在连接时成本稍高,我更喜欢重定向方案,因为它在运行时更具可扩展性,并且为现有连接创建的故障点更少。所有客户端都连接到您的传入连接网关服务器,该服务器负责了解场中每个服务器的当前负载分数,并基于此将传入连接分配给得分最低的主机,然后重定向此新连接重新连接到场中的特定服务器之一。


我还看到了纯粹由自定义 DNS 实现完成的负载平衡。客户端请求 IP 地址farm.somedomain.com,该自定义 DNS 服务器为它们提供它希望分配给它们的主机的 IP 地址。查找 IP 地址的每个客户端farm.somedomain.com可能会获得不同的 IP 地址。您可以通过在自定义 DNS 服务器中添加或删除主机来启动或关闭主机,并且该自定义 DNS 服务器必须包含用于了解负载平衡逻辑和所有正在运行的主机的当前负载分数的逻辑。

于 2017-11-16T04:59:15.883 回答
3

将 websocket 请求路由到负载均衡器,该负载均衡器决定将连接发送到何处。

例如,HAProxyleastconn一种用于长连接的方法,该方法可以选择最近最少使用且连接数最少的服务器。

HAProxy 后端服务器权重也可以通过外部输入进行修改,@jfriend00在他们的回答中详细介绍了权重的技术细节。

于 2017-11-16T06:24:16.103 回答
0

我发现这个项目可能有用: https ://github.com/apundir/wsbalancer

描述中的一个片段:

Websocket 平衡器是 websocket 的有状态反向代理。它在多个可用后端分发传入的 websocket。除了负载均衡外,均衡器还负责在会话中间异常失败的情况下透明地从一个后端切换到另一个后端。在此故障转移期间,远程客户端连接保持原样,因此远程客户端甚至看不到此故障转移。尽一切努力确保在此故障转移期间不会丢弃任何消息。

关于您的问题:如果配置为新连接,负载均衡器将路由该新连接。

正如@Matt 所提到的,例如使用 HAProxy 使用 minimumconn 选项。

于 2020-11-17T00:01:33.130 回答