这是我的问题:
我的应用程序是用于Web应用程序的分布式实时消息代理。来自Web浏览器的客户端连接到其中一个应用程序节点。那些节点通过ZeroMQ PUB / SUB机制连接。如果一个客户端发送消息 - 节点将其发布到PUB套接字,则其他节点从SUB套接字接收这些消息并将其发送到它们自己的连接客户端。
但现在我需要在场和历史功能。存在 - 提供一个列表,其中包含所有已连接(到所有节点)客户端的描述。历史记录 - 提供最近发送的几条消息的列表。即我需要获得整个应用程序状态。我考虑了几种实现方法:
1)将有关已连接客户端的所有信息发送到中央服务器。然后,当客户端要求存在时 - 询问中央服务器并将响应返回给客户端。
2)保留每个节点的所有信息。当客户端连接到任何节点时,使用PUBLISH操作将有关它的信息发送到其他节点。因此,当客户要求存在时,我可以立即返回响应。
3)从所有节点收集有关需求的信息。我真的无法想象如何对此进行编程,但这可以摆脱重复的信息,从而减少内存消耗。在这种情况下,我不需要担心在内存中拟合所有信息。
4)使用一些分布式数据存储,例如Dooserd。但由于额外的依赖性,我不喜欢这个想法。
客户端需要每次连接到节点的状态信息,每个客户端连接/断开连接时状态信息都会发生变化,每条消息的历史信息都会发生变化。
这是一个开源应用程序,因此我不知道它必须支持多少连接的客户端。最后的负载测试会说明这个数字。
对这些存在和历史数据的可靠性没有强烈要求。
我真的需要你的建议,这些选项中的哪一种是解决我问题的正确方法。或许还有另一种更好的方法?
答案 0 :(得分:2)
在某些情况下,基本上所有选项都是有效选项。
如果没有具体要求,我会选择最简单的解决方案。
我认为最简单的解决方案是使用像Redis这样的东西。它很稳定,被许多公司使用(据我所知,包括SO),它非常快速且非常灵活,很容易实现历史记录的上限列表。迭代您的需求非常容易,因为您可以快速更改功能。
如果您不想要额外的依赖/部署,另一个选择是在服务器之间对信息进行分区(使用散列分区或一致性散列),这样您就知道在哪里存储/检索有关特定客户端或其他实体的信息。
HTH
答案 1 :(得分:1)
存在和历史数据很自然地按照它所属的渠道划分。
那么您是否考虑过跨应用服务器分发频道?每个应用程序节点都可以有一些它知道的通道。有关其他通道的查询将发送到可以回答它们的特定节点。
这可能最接近列表中的选项3。
这样,每个通道的状态数据都成为可管理的数据块,可能小到足以保留在内存中。历史数据可以缓存在内存中,也可以缓存在特定于通道的服务器上。使用某种逐出算法来确定哪些历史数据不再足够有趣以进行缓存。它将从内存中删除,随时可以从存储中检索。
另一个想法供你考虑:你知道0MQ的Clustered Hashmap Protocol吗?我认为您可以使用它(或受其启发)来推送关于客户端连接到的那些通道的状态和历史数据,而不是让它们从应用程序服务器中提取它。
CHP服务器将散列图数据中的所有更改发布到所有订阅客户端。订阅者过滤数据。这是订阅0MQ主题的工作原理,而不仅仅是CHP。但是,如果服务器拥有多个频道但客户通常只对少数频道感兴趣,那么对于您的客户来说,这可能会产生一些数据。
我认为你已经面临这个问题,所以我想知道:你现在如何组织这个问题?
客户端在加入时检索快照,并根据子树 进行过滤。用户指南中有一些有趣的细节,介绍如何在快照到达之前保留已发布的更新,以及如何丢弃更新之前的消息。
所以我们将在客户端进行同步,如下所示:
客户端首先订阅更新,然后发出状态请求。这可以保证状态比最新的更新更新。
客户端等待服务器回复状态,同时排队所有更新。它只是通过不读取它来实现这一点:ØMQ使它们在套接字队列上排队。
当客户端收到状态更新时,它会再次开始读取更新。但是,它会丢弃任何早于状态更新的更新。因此,如果状态更新包含最多200个更新,则客户端将丢弃最多201个更新。
然后,客户端将更新应用于自己的状态快照。
我认为这一点肯定会让你感兴趣。