1

使用 EC2 实例(以及 Amazon Auto Scaling 和 Elastic Load Balancing)我有几个 TCP 服务器实例在Amazon Web Services中运行。每个 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 组件来实现简单的订阅者-发布者类型机制(想想观察者设计模式)。即,一台服务器添加了一些东西,所有其他服务器都从它那里实时获取消息。

4

2 回答 2

0

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

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

  1. 使用可以处理所有连接的更大 EC2 实例,如果您的可用性要求有此要求,则使用热备用。如果流量上限已知(例如,如果这是一个企业聊天应用程序而不是面向 Internet 的应用程序),您可能会发现,如果它可以大大简化您的工程工作,那么扩展比扩展成本更低。

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

于 2012-03-25T17:56:54.257 回答
0

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

于 2012-03-25T17:59:17.200 回答