JMS(或任何消息传递解决方案)是否适用于关注者/关注模型

时间:2010-08-31 07:15:58

标签: java architecture jms scalability messaging

为了简单起见,我们假设我正在克隆twitter(我不是)。因此,每个用户都可以关注其他用户,并被其他用户关注。对于您关注的每个用户,您会收到他发送的所有推文。一切都存储在数据存储中(无论是NoSQL解决方案还是分片关系数据库)。

但是,当用户在线时,您认为让他们通过JMS接收推文是合适的,而不是轮询数据库并检索新的推文:

  • 当用户注册(或登录时)时,会创建一个以他(或他的id)命名的JMS主题
  • 当用户登录时,他订阅了他所关注的每个用户的JMS主题
  • 会话范围的对象(每用户)充当JMS消息侦听器
  • 所有收到的消息都存储在会话中(内存中)
  • 通过会话范围对象的ajax轮询更新UI
  • 当用户注销或其会话超时时,消息监听器被销毁
据称,这背后的想法是为了提高性能 - 即不是过于频繁地查询数据存储区,而是将直接内容缓存在内存中。

当然,整个事情应该在集群中运行,并且可以扩展。

但是我不确定:

  • 这是否真的值得(在性能和可扩展性增益方面)
  • JMS是否不会增加不良开销,这等于查询数据存储区(从而使整个复杂化无用)

在某些时候(当事情有效时)我会做一些基准测试,但我想听一些初步的评论。

2 个答案:

答案 0 :(得分:3)

听起来很合理。您需要确保您选择的JMS实现支持可能非常多的主题 - 并非所有主题都可以优雅地完成。

我的主要设计问题是,当用户首次登录时,他的会话消息存储将为空,您必须等待它填满。那么你是不是必须打到数据库,或者这不是问题。

另外,你并没有真正利用JMS的事件驱动特性。从主题接收的消息将被转储到会话存储中以供以后检索。

由于它不是真正的事件驱动,你可以考虑使用分布式内存数据存储,例如EhCache + JGroups或JBossCache3(我强烈推荐)。新的推文将被放入这个分布式商店,读者只需要搜索那些寻找感兴趣的项目。这可能更节省内存,因为每个推文上只存储一个每个推文的副本。您也可以在系统启动时预加载缓存。

答案 1 :(得分:1)

注意:我对您在问题中描述的系统设置没有实际经验,因此以下是理论上的考虑因素。

一个因素是问题,您的用户将在下次登录时看到的内容:

  1. 在之前的会话中尚未发送给用户的所有推文。或
  2. 过去x小时内发布的所有推文。
  3. 案例1:JMS很好,因为队列可以记住,哪些消息已经被传递。但是等一下:这意味着,每条消息接收器必须有一个队列。

    案例2:在这里,您可以真正处理每封邮件发件人的主题,并使超过x小时的邮件过期。再说一遍,JMS可能是个不错的选择。

    <强>性能

    JMS实现通常可以将消息保留在内存中,并且为了访问队列/主题中的消息,您不必搜索大型索引 - 所以我认为这应该比数据库更快,可能仍然比内存数据库更快。当节点出现故障时,您可以从后备数据库重新创建队列,也可以使用内置于某些JMS实现中的high-availabilitypersistence

    但我完全同意skaffman:与分布式内存数据存储相比,你将使用更多内存。 JMS的优点是,它简化了消息(以及其他一些东西)的自动过期,我不知道重新实现该功能是否是个好主意。

    所以也许我会做的只是在队列中保存ID,并将实际消息保存在Java对象缓存中。这样,您将再次使用索引,但是您可以从JMS获得对象缓存的大部分内存效率。当缓存仅在发送方时,它甚至不必分发,假设来自一个发送方的所有消息都驻留在一个(复制的)节点上 - 但这可能取决于许多其他架构决策。