3

我正在尝试在 Clojure 中构建一个可扩展的聊天服务器。我正在使用 http-kit、compojure 和 redis pub/sub 在不同节点之间进行通信(扇出方法)。服务器将使用 websockets 连接 b/w 客户端-服务器,并回退到长轮询。单个用户可以有多个连接以与浏览器中的每个选项卡的一个连接聊天,并且消息应传递给所有连接。

所以基本上当用户连接时,我将通道存储在一个原子中,随机 uuid 为

{:userid1 [{:socketuuid "random uuid#1 for uerid1" :socket "channel#1 for userid1"}
          {:socketuuid "random uuid#2" :socket "channel#2"}]
:userid2 [{:socketuuid "random uuid#1 for userid2" :socket "channel#1 for userid2}]}

消息被发布到 websockets 和长轮询通道的公共路由,消息结构看起来像

{:from "userid1" :to "userid2" :message "message content"}

服务器在原子中查找 :from 和 :to 用户 ID 的所有通道,并将消息发送到相应用户的连接通道,它还将消息发布到 redis 服务器上,连接节点在其中查找存储在其中的通道拥有 atom 并将消息传递给相应的用户。

所以我遇到的问题是,如何正确实现存在。基本上,当通道断开连接时,http-kit 会向您发送一个状态,状态可以是“服务器关闭”或“客户端关闭”,而我可以处理服务器断开连接(客户端将自动重新连接)但是当断开连接时我遇到了问题例如,从客户端发生。用户导航到另一个页面并在几秒钟后连接。当客户端断开连接时,如何确定用户已下线。此外,我担心消息到达 b/w 在长轮询模式下重新连接(我的长轮询超时为 30 秒)。

还请为上述架构提出一个好的存在机制。谢谢。

如果您需要更多信息,请发表评论。谢谢

编辑#1:

你能推荐一个关于在聊天服务器中实现存在的好教程/材料吗,我似乎找不到任何东西。

我当前的解决方案-> 我目前正在为特定用户 ID 的连接通道维护全局计数和最后连接时间戳,当用户断开连接时,计数会减少,并且会执行 10 秒的超时,这将检查用户是否有再次重新连接(即最后一个连接的标记是 10 秒前并且计数仍然为零),如果不是,那么据说用户已经离线,你会推荐这个解决方案,如果不是为什么,或者任何改进或更好的方法表示赞赏。另请注意,我在 http-kit 中使用计时器/计划任务,这些超时会显着影响性能吗?

4

1 回答 1

3

从客户端这里有两种不同的情况。

  1. 长轮询。我看不出这是个问题,如果客户端窗口关闭,将不再有轮询。少一个客户要求数据。
  2. 网络套接字。协议中有一个 close 方法可用。如果您正确实施,客户端应发送通知。请参阅此处:例如,正确关闭 WebSocket(HTML5、Javascript) 。

这是否回答你的问题?

于 2014-03-03T12:58:04.957 回答