集群TCP服务器,以便向所有客户端发送数据

2 投票
4 回答
1705 浏览
提问于 2025-04-17 10:06

重要说明:

我之前在ServerFault上问过这个问题:https://serverfault.com/questions/349065/clustering-tcp-servers-so-can-send-data-to-all-clients,但我也想听听程序员的看法


我正在开发一个实时的移动应用,通过在应用和服务器后台之间建立TCP连接。每个用户都可以向所有其他用户发送消息。

(我用Python和Twisted搭建TCP服务器,正在为应用和后台之间的通信创建自己的“协议”,并将其托管在亚马逊网络服务上。)


目前,我正在努力让后台系统具备可扩展性(和可靠性)。据我了解,系统可以通过升级到更大的服务器来支持更多用户(但这可能会有些限制),或者通过添加新的服务器以集群的方式配置——也就是说,多个服务器放在负载均衡器后面,可能共享一个数据库。

我已经大致勾画出了这个架构:

TCP服务器集群问题

但是,如果红色用户想给所有其他连接的用户发送消息呢?红色用户的服务器与红色用户有TCP连接,但与绿色用户没有。

我想到了一种解决这个问题的方法:

  • 每个服务器可以与其他服务器保持一个开放的TCP(或SSL)连接。当一个服务器想向所有用户发送消息时,它只需通过与其他服务器的连接将消息传递过去。可以在数据库中记录哪些服务器在线(以及它们的IP地址),其中一个服务器可以作为“老板”——也就是说,决定其他服务器是否正常运行,如果不正常,可以将它们从数据库中移除(如果某个服务器在线但失去了与“老板”的连接,它可以检查数据库,看看自己是否被移除,如果被移除就重启——否则可以假设“老板”也掉线了)。

显然,这个方法需要进一步完善,但展示了大致的原则。

另外,我不确定这是否可行(这似乎有点不切实际):

  • 也许用户可以直接连接到一个盒子或路由器,所有服务器可以通过它向所有用户发送消息?


如果你知道如何有效地集群TCP服务器,或者有什么设计模式可以提供解决方案,或者有任何意见,我将非常感激。谢谢你 :-)

4 个回答

0

一个很明显的选择就是把数据库当作消息的中转站。你总得把收到的消息存放在某个地方,不然如果服务器突然崩溃,这些消息就会丢失。把收到的消息放进中央数据库,然后让TCP服务器上的通知程序去取这些消息,并把它们发送给正确的用户。

2

看看IRC服务器是怎么处理这个问题的。其实它们已经能做到这一点了。每个人都可以在所有服务器上互相发送消息,或者只给某个单独的用户发消息,甚至可以给叫做“频道”的群组发消息。它的工作原理主要是通过服务器之间的路由来实现的。

其实这并不难,只要确保服务器之间相互认识并能进行沟通就行。

顺便提一下:在911事件发生时,最可靠的互联网新闻来源就是IRC网络。那时候所有的网站都因为流量太大而瘫痪,恢复一个简单的网页都花了很长时间。在这段时间里,IRC网络能够提供几乎实时的、经过审核的新闻频道,跨越大西洋。虽然你可能无法登录到另一边的服务器,但至少这些服务器之间的连接还是能保持的。

3

你需要决定一下你系统的可靠性要求(如果你已经决定了,也可以跟我们分享这些决定)。比如说,所有的消息在任何情况下都需要发送给所有用户吗?(例如,有一个或多个服务器崩溃了)如果服务器崩溃了,你能接受同一条消息被发送给同一个用户两次吗?这些决定会直接影响到你系统的复杂程度。

最简单的情况是,当服务器崩溃时,并不是所有的用户都能收到消息。你所有的服务器之间保持着TCP连接。某个服务器接收到用户的消息后,会把这条消息发送给所有连接到它的用户,以及所有其他连接的服务器。其他服务器再把这条消息发送给它们的用户。为了扩展系统,你只需要再增加一台服务器,让它连接到所有现有的服务器上。

撰写回答