带有“消息屏障”功能的消息队列?

时间:2010-03-07 20:42:26

标签: java jms

是否有消息队列实现允许通过在消息流中插入“消息障碍”将工作分解为“批处理”?让我澄清一下。在消息障碍之后,消息不应传递给队列的任何消费者,直到屏障之前的所有消息被消耗为止。有点像同步点。如果所有消费者在到达障碍时收到通知,我也会更喜欢。

那里有这样的东西吗?

2 个答案:

答案 0 :(得分:1)

我不知道现有的,广泛可用的实现,但如果你允许我,我会提出一个非常简单的通用实现使用代理,其中:

  • 生产者写入代理队列/主题
  • 代理转发到原始队列/主题,直到代理读取屏障消息,此时:
    • 代理可以通过将屏障消息转发到原始主题通知主题订阅者,或
    • 代理可以通过以下方式通知队列订阅者
      • 定期发布屏障消息,直到屏障被清除;这并不能保证所有消费者都会收到一个通知,尽管所有消费者最终都会清除障碍(有些可能会收到0个通知,其他可能会收到1个通知 - 所有这些都取决于用于向消费者分发消息的调度程序的类型,例如,如果不是-roundrobin)
      • 使用专门主题每个障碍通知每个消费者一次
    • 代理停止转发来自代理队列的任何消息,直到屏障被清除,也就是说,直到原始队列清空和/或所有消费者都已确认通向屏障的所有队列/主题消息(如果有)
  • 代理恢复转发

更新

感谢Miklos指出,在JMS下,框架不提供异步交付的确认(JMS中所谓的“确认”纯粹是消费者方面的概念,并且不能代理。)

因此,在JMS ,现有的实现(适用于障碍)可能已经通过“确认队列”提供应用程序级别的确认(而不是原始队列 - 这将是“请求队列”。消费者必须通过向代理确认队列发送确认消息来确认请求的执行。在将确认消息转发给生产者之后,代理将使用确认消息来跟踪屏障何时被清除。

如果现有的实施(适用于障碍)已经通过“确认队列”提供了应用程序级别的确认,那么您可以:

  • 让代理使用QueueBrowser提供
    1. 你正在处理的是queueus而不是事件,
    2. 您希望在交付时同步而不是执行确认,
    3. 可以同步第一次传递,即使请求实际已中止并且必须重新传递(即使屏障已被清除。)我认为Miklos已经指出了这个问题IIRC。
  • 否则,添加代理使用的确认队列,并调整使用者以向其写入确认(实际上是上面的JMS场景,除非代理不需要将确认消息转发给生产者,除非你的生产者需要这个功能。)

答案 1 :(得分:0)

您可以使用“障碍消息”的主题和“选择接收器”使用的“批量项目”的队列来实现此目的。
将障碍消息发布到主题可确保所有消费者都收到他们自己的障碍消息副本。

每个消费者都需要两个订阅:

  1. 走向障碍主题
  2. 使用屏障消息定义的选择标准对批处理队列的选择性接收器。
  3. 屏障消息需要包含必须应用于队列消费者选择标准的批处理密钥 例如batchId = n
    或JMSMessageID< 100个
    或JMSTimestamp< xxx

    每当收到屏障消息时,

    • 必须关闭当前队列使用者
    • 必须使用屏障消息的内容修改队列选择标准
    • 必须使用修改后的选择标准
    • 启动新的选择性消费者

    如果您要使用自定义批处理键作为选择条件,例如上面的'batchId',则假设所有消息生产者都能够设置该JMS属性,否则代理将必须使用消息集该属性并重新发布到选择性消费者正在监听的队列中。

    有关选择性接收器的更多信息,请参阅以下链接:

    1. http://java.sun.com/j2ee/1.4/docs/api/javax/jms/Message.html
    2. http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/jms/QueueSession.html#createReceiver(javax.jms.Queue,%20java.lang.String)