JMS 主题与队列 - 意图

Posted

技术标签:

【中文标题】JMS 主题与队列 - 意图【英文标题】:JMS Topic vs Queue - Intent 【发布时间】:2013-06-30 01:05:53 【问题描述】:

我正在尝试了解使用队列的用例。

我的理解: 队列意味着一对一。唯一的用例(如果不是罕见的话,非常少)是:消息仅用于一次消费。

但即使在这些情况下,我也可能想使用主题(只是为了将来的安全)。唯一额外的谨慎是使订阅持久。或者,在特殊情况下,我会使用桥接/调度机制。

鉴于上述情况,我总是(或在大多数情况下)想要发布到某个主题。订阅者可以是持久主题或分派队列。

请让我知道我在这里遗漏了什么或者我遗漏了最初的意图?

【问题讨论】:

不是 cmets 比“只是”downvote 更好吗? 【参考方案1】:

您可能错过了队列和主题都可以有多个订阅者。队列将消息传递给可能的多个订阅者之一,而主题将消息传递给所有订阅者。

如果您确定只有一个订阅者,那么队列订阅者和持久主题订阅者的行为将相似。我宁愿将这种情况视为“特例”。

【讨论】:

2.我的观点是:即使在“特殊情况”下,我也想选择 Topic,因为将来我可能希望有多个订阅者订阅该消息。 1:请澄清您的问题。您不明白让多个订阅者(JMS 语言中的接收者)加入队列意味着什么吗?由于 PTP 语义和 JMS 保证确认的消息不会重新传递,您可以假设队列消息仅传递给一个接收者。 JMS 没有指定将消息传递给哪个接收者。 2:没有人知道队列或主题是否适合满足您的业务需求。 好的。我正在尝试重新构建我的问题:使用队列的令人信服的理由是什么?队列可以实现的任何事情都可以通过 Topic 实现(以及更大的灵活性),而无需额外注意使订阅者持久化。 队列保证一条消息只传递给一个接收者。使用一个主题,一条消息将被传递给所有接收者。我已经在原始答案中写过。 有时,消息发送者并不关心谁处理队列中的消息,但消息代表一个任务。可能有许多相互竞争的队列消费者,有效地“多线程”执行任务。但是您只希望每个任务执行一次,所以我知道当我将消息放入队列时,在某个时候,消费者会拿起它并执行它。我不明白主题,因为每个订阅者都会收到我的消息副本。【参考方案2】:

JMS 中的队列和主题代表两种不同的模型——点对点和发布/订阅。主题将保留一条消息,直到所有客户端都收到它们,所有订阅者都在处理它们。队列将等待第一个消费者拉取消息,并在此时认为它已读取。

【讨论】:

除非订阅者是持久的,否则离线订阅者的消息将被丢弃。【参考方案3】:

如果您从实际示例的角度考虑,关于何时使用队列的设计要求很简单:

提交在线订单(一次性处理以避免收取信用费用) 卡两次) 私人点对点聊天(每条消息只有一个接收者) 并行任务分配(在网络系统中的许多工作人员之间分配任务)

...以及何时使用主题的示例...

向多个订阅者广播新闻;通知服务、股票代码等。 电子邮件客户端(唯一的持久订阅者;断开连接后您仍会收到电子邮件)

你说...

但即使在这些情况下,我也可能想使用主题(只是为了将来 安全的)。我唯一要做的额外情况是制作(每个) 订阅持久。或者,在特殊情况下,我会使用桥接 / 调度机制。

您对设计进行了过度设计。确实,您可以使用主题和持久订阅者实现一次性处理,但您将被限制为单个持久订阅者;当您为该主题启动另一个订阅者时,您将获得对同一消息的重复处理,更不用说,单个持久订阅者几乎不是可扩展的解决方案;这肯定会成为您系统的瓶颈。使用队列,您可以为同一个队列在 100 个节点上部署 1000 个接收器,并且您仍然可以对单个消息进行一次性处理。

你说...

在上面给出,我总是(或在大多数情况下)想要发布到 话题。订阅者可以是持久主题或已调度 队列。

对主题订阅者使用调度队列有点多余。使用队列时,您基本上会获得异步调度,那么为什么不直接使用队列呢?...没有理由将主题放在它前面。

【讨论】:

以上是关于JMS 主题与队列 - 意图的主要内容,如果未能解决你的问题,请参考以下文章

JMS 工作流 - 混合队列和主题

activeMQ队列模式和主题模式的Java实现

Android中的相机意图和优先级队列

如何使用 Spring JMS 发布 JMS 主题?

Spring Integration JMS 创建 ActiveMQ 队列而不是主题

是否可以在运行时手动将消息驱动 bean 订阅到 JMS 队列/主题?