我正在尝试构建即时通讯应用程序。客户不仅会发送消息,还经常发送音频。我决定使用 websocket 连接与客户端进行通信。它速度很快并且允许发送二进制数据。
主要思想是接收来自 client1 的消息并通知 client2。但事情是这样的。我的应用程序将在 GAE 上运行。如果 client1 的套接字在 server1 上打开,并且 client2 的套接字在 server2 上打开,会怎么样。该服务器不了解彼此的客户端。
我有一个想法如何解决它,但我确信这是一种糟糕的方式。我将在服务器之间使用某种通信(例如 JMS 或在服务器之间打开另一个 Websocket 连接,现在并不重要)。
但这肯定会导致灾难。我什至无法想象这些服务器相互通信的频率。对于每条消息,server1应通知server2,server2应通知client2。但当 serverN 发挥作用时,事情会变得更糟。
我认为此方法有效的另一种方式是 Firebase。但它将消息大小限制为 4KB。所以我无法通过它发送音频。作为解决方案,我可以通知客户有关新音频的信息,然后他会前往我的服务器获取该音频。
希望我清楚地解释了问题。有谁知道如何解决它?或者也许还有其他方法来构建此类应用程序?
如果您正在构建消息集群并期望通信客户端连接到服务器的不同实例,那么服务器到服务器的通信是不可避免的。通常这不是问题。
问题的第二部分是关于传递大型媒体文件。将其发送到带外是一种常见的最佳实践 - 存储在服务器上并仅传递对其的引用。就像评论中有人建议的那样,将音频保存在服务器上,然后发送一条消息,例如“音频可用,从这里获取......”。您不需要为此轮询服务器。只需在接收客户端请求时获取一次即可。
总的来说,你似乎在尝试重新发明轮子。只需使用现成的东西即可。
上述方法的缺点:
每个服务器将与 n-1 个服务器建立连接,创建网状拓扑
中心化系统(zookeeper)成为单点故障(这是可以解决的)
Whatsapp、G-Talk 等应用程序使用 XMPP 和 TCP/IP。
我是这样实现的:我使用 Redis 进行服务器到服务器的通信。每个客户端都分配有一个唯一的集线器代码,该代码在连接时将它们与特定的集线器关联起来。发送消息时,发件人会检查收件人是否位于同一集线器上。如果是,则直接传递消息。如果没有,则查询 Redis 以确定收件人的中心代码。
每个集线器还监听专用频道。如果收件人(用户 B)位于不同的集线器或服务器上,但其集线器代码与 Redis 中存储的集线器匹配,则邮件将路由到该服务器。如果未找到匹配项,则表示收件人离线。在这种情况下,该消息将被标记为未读并存储在 Redis 和数据库中。
我希望这个解释有帮助!