首先,你需要定义你所询问的问题的范围。如果你真正谈论动态水平扩展,即根据总负载启动和关闭服务器,那么这比仅仅确定如何路由最新传入的新套接字连接更加复杂。
要解决这个问题,你必须有一种方法来“移动”一个套接字从一个主机到另一个主机,以便你可以清除你想要关闭的主机上的连接(我在这里假设真正的动态缩放既可以升又可以降)。通常我见过的方式是通过使用一个合作的客户端来实现,告诉客户端重新连接,当它重新连接时,它会被负载均衡到不同的服务器上,因此可以清除你想要关闭的服务器。如果你的客户端已经具有自动重新连接逻辑(像socket.io一样),你可以让服务器关闭连接,客户端将自动重新连接。
至于负载均衡传入的客户端连接,你必须决定要使用哪种负载度量。最终,你需要为每个服务器进程得出一个得分,以告诉你其有多“繁忙”,以便将新连接放置在最不繁忙的服务器上。一个基本的得分只是当前连接数。如果你每个服务器进程有大量连接(数万个),并且在你的应用程序中没有特定的原因使一些连接比其他连接更繁忙,那么大数定律可能平均了负载,因此你可以只考虑每台服务器有多少连接。如果使用连接不是那么公平或均匀,那么你还必须考虑一些时间移动CPU负载的平均值,以及总连接数。
如果你将负载分配到多台物理服务器上,则需要一个负载均衡器或代理服务,每个人最初连接到该服务,该代理可以查看池中所有当前运行的服务器的度量,并将连接分配给具有最低当前得分的服务器。这可以通过代理方案或(更可扩展的)重定向来实现,因此代理在初始分配后离开了。
你还可以设置一个定期检查所有服务器集群中的负载得分(无论你选择如何计算)的进程,决定何时启动一个新服务器或关闭一个服务器,或当某台服务器的负载过高且需要将其从多个连接中踢出时,告诉该服务器强制它们重新平衡。
“我不明白的是如何将新的套接字连接有效地路由到选定的低套接字计数服务器。” 如上所述,您可以使用代理方案或重定向方案。在连接时略微增加成本,我更喜欢重定向方案,因为它在运行时更具可扩展性,并为现有连接创建较少的故障点。所有客户端都连接到您的入站连接网关服务器,该服务器负责了解农场中每个服务器的当前负载得分,并基于此将传入的连接分配给具有最低得分的主机,然后重定向此新连接以重新连接到农场中的特定服务器之一。
我还看到过完全通过自定义DNS实现的负载平衡。客户端请求
farm.somedomain.com
的IP地址,而该自定义DNS服务器会给他们分配要分配的主机的IP地址。查询
farm.somedomain.com
的每个客户端可能会获得不同的IP地址。通过添加或删除它们的自定义DNS服务器来启动或关闭主机,并且该自定义DNS服务器必须包含了解所有运行主机的负载平衡逻辑和当前负载得分的逻辑。