使用发布/订阅和长轮询

时间:2014-08-18 19:55:11

标签: architecture chat scalability

我想实现一个可伸缩的聊天应用程序。 因此,我想使用pub / sub技术(当有人发送消息时,它被发送到整个房间)。由于它的简单,我选择了Redis缓存服务器。

此外,我想使用长轮询将新消息从服务器传输到客户端。我不使用网络套接字的原因是因为我在组织代理中遇到了一些麻烦。

据我在网上看到的,这听起来像问题的标准解决方案。

您能否建议处理长轮询请求之间发送的消息的最佳解决方案是什么?用户如何不错过邮件?

听起来我需要为每个客户端保存一个缓存,其中包含自己的消息。但这样 - 我没有利用pub / sub技术。我可以向房间中的每个用户发送消息,而不是发布/订阅。

1 个答案:

答案 0 :(得分:1)

使用长轮询方法,客户端可能会像这样对您的服务器进行API调用(在此示例中查看1034室中已经有3个聊天的所有聊天):

GET /rooms/1034/chats

由于有数据存在,您的服务器会立即做出响应。

响应:

{
  "chats": [
    { "sequence": 0, "by": "fred", "message": "hey guys, anyone in this room?" },
    { "sequence": 1, "by": "fred", "message": "anyone at all?" },
    { "sequence": 2, "by": "bill", "message": "yeah I'm here!" }
  ]
}

现在客户端可以显示三个聊天记录,然后向服务器询问更多信息。这是长轮询开始的地方 - 因为服务器没有更多的聊天,API调用会阻止,直到新的聊天结束。

GET /rooms/1034/chats?after=2

..服务器阻止,直到有人添加新聊天..

响应:

{
  "chats": [
    { "sequence": 4, "by": "frodo", "message": "I'm here too!" }
  ]
}

关键是客户端本身维护一个"光标"它的位置,因此您不需要维护服务器上的任何每个客户端缓存等。

当然还有更多。服务器无法永久阻止,因此在一段时间(可能是60秒)之后它应该回复,但是有超时消息。

在Spring中,通过DeferredResult支持服务器处理这个问题,而不会占用每个客户端的整个线程。