【问题标题】:one consumer for many queues一个消费者多队列
【发布时间】:2014-12-17 04:51:49
【问题描述】:

在我的系统中,有很多用户写博客。我需要订阅不同的用户。没有集中式系统(这是一个摇摆应用程序)。

我正在使用 JMS。

用户可以关注一个用户、两个用户或 100 个用户。

m_destination1 = m_session.createQueue("USER.DEVID");
m_consumer1 = m_session.createConsumer(m_destination1);

m_destination2 = m_session.createQueue("USER.HARRY");
m_consumer2 = m_session.createConsumer(m_destination2);

是否有任何通用方法可以为未知号码编写上述代码行。的用户?就像一个消费者可以接收来自多个用户的消息一样。

这里的通配符不起作用。

【问题讨论】:

    标签: java jms activemq


    【解决方案1】:

    您可以使用的最好的东西是Mirrored Queue activeMQ 功能, 你可以在这里阅读文档

    镜像队列的基本作用是将队列上发送的所有消息转发到一个类似命名的主题,然后这个主题可以被多个消费者订阅。

    如果您使用镜像队列,您将需要您的消费者订阅不同的主题。

    您的设计需要发布-订阅(主题)域而不是点对点架构(即队列)。由于您已经拥有一个架构,它为不同的人写博客生成队列,更改为不需要系统,但会满足您的要求。

    除此之外,如果 2 个消费者在队列上侦听,那么他们将从队列中并行获取消息,即如果队列中有 2 条消息,那么两个消费者将独立处理 1 条消息,我认为这不是你想要的.

    希望这会有所帮助! 祝你好运!

    【讨论】:

    • 找到你要找的东西了吗?
    • 镜像队列如何帮助 OP 实现不必明确指定不同用户的目标?
    • 毫无疑问,必须创建不同的用户,但问题是如何让 2 个用户在一个队列上收听,因为它是一个博客,所以所有用户都需要拥有一份副本,这使用基于队列的方法是不可能的,镜像队列内部使用了可以使用的主题,并且由于我们使用队列作为接口,因此不需要更改 OP 的现有架构并且可以满足要求
    • OP 询问“是否有任何通用方法可以为未知数量的用户编写上述代码行?”,这似乎是镜像队列无法支持的要求(尽管主题可以) .我认为队列是一种不合适的方法是对的,我只是认为考虑到 OP 的规定要求(包括我刚刚引用的要求),镜像队列并没有更好,所以我不确定你为什么要提倡它们而不是仅仅告诉 OP 使用主题。
    【解决方案2】:

    @Vihar 的回答是正确的,您应该通过使用主题来使用发布-订阅范式,以允许多个消费者同时收到新博客文章的通知。听起来您的主要痛点是每个作者都有一个目的地,并且想要使用消息的用户必须单独订阅每个目的地。

    相反,将所有新发布消息发布到单个主题(我们称之为 NewPostNotificationTopic)。然后,客户可以订阅所有消息,但会立即对照他们关心的作者列表检查它们,并立即停止处理他们未关注的作者的任何通知。 (这将过滤放入消息处理程序而不是 ActiveMQ 网络。)这确实意味着每条消息都将传递给每个客户端,但只要消息很小并且您的网络速度很快并且您的用户通常连接到网络,这可能是一个可行的解决方案。但是,如果您负担不起将所有消息发送到所有客户端的网络带宽,或者如果您的消费者将长时间离线并且您无法拥有所有消息的副本在他们重新上线之前,这可能对您不起作用。

    或者,将所有消息发布到同一主题,但将作者 ID 设置为消息的标头,并使用消息选择器告诉 ActiveMQ 仅传递与给定作者 ID 匹配的消息。这将更有效率,但是您又需要明确告诉 ActiveMQ 您关心哪些作者,或者使用包含 OR 的选择器的单个订阅,或者每个作者一个订阅。后者更简洁,但让您回到每个作者每个读者订阅一个问题;前者只产生一个订阅,但每次为读者添加/删除作者时都必须更新它,并且您需要确保处理删除订阅和添加另一个订阅所固有的竞争条件。如果我提出的性能问题没有问题,我会采用我提出的第一个解决方案(在消息处理程序中而不是在 ActiveMQ 订阅中进行过滤);否则我可能会为每位读者每位作者订阅一次,而不是使用 ORed 选择器进行一次订阅,并且每次发生更改时都需要重做订阅。

    【讨论】: