在水平伸缩的WebSocket服务器上负载均衡套接字?

每隔几个月,当我想通过一个涉及套接字的个人项目时,我发现自己的问题是: “如何在dynamic水平扩展的WebSocket服务器上正确加载平衡套接字?

我理解了横向扩展WebSockets背后的理论,并使用pub / sub模型将数据获取到保存特定用户的套接字连接的正确服务器。 我想我理解的方法是用最less的当前套接字连接来有效地识别服务器,我也希望路由一个新的套接字连接。 我不明白的是如何有效地将新的套接字连接路由到您select的低套接字计数的服务器。

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

首先,你需要定义你所问的问题的界限。 如果你真的在谈论dynamic水平扩展,那么你可以根据总负载在服务器上下旋转,那么这是一个更为复杂的问题,而不是仅仅是在哪里寻找最新的传入的新套接字连接。

要解决这个问题,你必须有一个“移动”从一个主机到另一个套接字的方式,所以你可以清除连接从一个主机,你想旋转下来(我假设真正的dynamic缩放既起来,下)。 我所看到的通常做法是通过让一个合作的客户端来告诉客户端重新连接,当它重新连接时,它被负载平衡到一个不同的服务器上,这样你就可以清除你想要closures的服务器。 如果你的客户端已经有了自动重新连接的逻辑(比如socket.io),你可以让服务器closures连接,客户端将自动重新连接。

至于负载均衡传入的客户端连接,您必须决定要使用的负载指标。 最终,每个服务器进程都需要一个分数,告诉您如何“忙碌”,这样您才能在最不繁忙的服务器上build立新的连接。 基本分数只是当前连接的数量。 如果每个服务器进程有数量巨大的连接(成千上万),并且在你的应用程序中没有特别的原因,有些人可能比其他人忙得多,那么大数定律可能会平均分配负载,所以你可以逃避每个服务器有多less个连接。 如果连接的使用不是那么公平甚至是不公平,那么你可能还必须考虑某种时间移动CPU负载的平均值以及连接总数。

如果要在多个物理服务器之间进行负载均衡,则需要每个人最初连接到的负载均衡器或代理服务,并且该代理可以查看池中所有当前正在运行的服务器的指标,并将连接分配给一个目前得分最低的。 这可以通过代理scheme完成,也可以通过redirect(更具扩展性)完成,这样代理在初始分配后就不会出现问题。

然后,您可以有一个过程,定期检查集群中所有服务器上的负载得分(但是您决定计算),并决定何时旋转新的服务器或何时旋转一个或者当事情太远的平衡在给定的服务器和该服务器需要被告知踢几个连接closures,迫使他们重新平衡。

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

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


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

将websocket请求路由到负载均衡器,负载均衡器决定发送连接的位置。

作为一个例子, HAProxy有一个长连接的最less连接方法,它select连接数最less的最近最less使用的服务器。

HAProxy后端服务器权重也可以通过外部input来修改 ,@ jfriend00详细说明了权重在他们的答案中的技术性。