分布式问题在EC2实例上扩展TCP服务器

时间:2012-03-25 17:46:21

标签: tcp amazon-ec2 amazon-web-services tcpserver tcpsocket

使用EC2实例(以及Amazon Auto Scaling和Elastic Load Balancing)我在Amazon Web Services中运行了几个TCP服务器实例。每个EC2实例都可以访问集中式数据库(在Amazon RDS上运行)。为了使这个后端可扩展,新的EC2实例(TCP服务器)根据需求按比例放大和缩小。

服务器是使用Python Twisted框架制作的。系统为自定义即时消息服务提供支持,具有用户可以加入的多个组聊天。

当用户开始使用该服务时,他们会与其中一个TCP服务器建立TCP套接字。每个服务器在存储器中存储当前连接的用户(即,打开的TCP套接字)以及每个用户当前“进入”(并因此订阅)的“群聊”。创建的所有聊天数据都存储在数据库中。

问题

当UserA在GroupChatZ中发布消息时,'GroupChatZ中的所有用户'都应该收到该消息。如果只有1个TCP服务器,这很简单:它会在其内存中搜索'那个'群组聊天'中的所有用户,并向他们发送新消息。但是,由于存在多个服务器,因此在创建新消息时,该服务器必须将消息传递给所有其他服务器(即EC2实例)。

这个问题最有效的解决方案是什么? 也许使用AWS组件。


我能想到的一个解决方案是每个服务器在首次启动时将其IP地址存储在数据库中,并获取所有其他连接服务器的IP地址并与它们建立TCP连接。收到每条新消息后,处理它的服务器可以将其发送给它所连接的所有其他服务器。

然而,TCP连接不是100%可靠,而且这种解决方案增加了复杂性。


我怀疑实际上有一种很好的方法可以使用某些Amazon Web Services组件来实现简单的订阅者 - 发布者类型机制(想想Observer设计模式)。即其中一个服务器添加一些东西,所有其他服务器实时从中获取消息。

2 个答案:

答案 0 :(得分:0)

TCP连接不仅100%可靠,EC2实例也不是。他们可以随时消失(相信我,他们有时会这样做)。实例的内部IP地址也可能会发生变化(例如,如果它重新启动)。如果您使用弹性IP地址,AWS数据中心外部的连接(例如聊天客户端)将具有要连接的稳定(一组)IP。但是,使用弹性IP在服务器之间进行通信的速度相对较慢,因为连接在AWS防火墙外部路由然后重新进入(上次我无论如何都要检查)。

以下是一些需要考虑的策略:

  1. 如果您的可用性要求如此规定,请使用可以处理所有连接的较大EC2实例,并使用热备用。如果流量的上限已知(例如,如果这是一个企业聊天应用程序而不是面向互联网的应用程序),您可能会发现扩展比扩展更便宜,如果它可以大大简化您的工程工作。

  2. 如果您仍然希望扩展,请考虑使用EH Cache等事务性分布式缓存来存储聊天数据。这类问题已经解决了。您将花费大量的工程时间来处理已建立的分布式缓存已经处理的所有情况。

答案 1 :(得分:0)

我认为Amazon SQS(简单队列系统)可以提供帮助。您为每个服务器创建一个消息队列。收到消息后,服务器会将消息放入每个服务器的队列中。服务器经常轮询队列中的新消息。如果服务器抓取指向未与其连接的用户的消息,则忽略该消息,否则将传递该消息。