仅当重复消息仍在使用 ActiveMQ Artemis 和 JBoss EAP 7.1 排队时才丢弃它们

Discard duplicate message only if they are still queued with ActiveMQ Artemis and JBoss EAP 7.1

我们在 JBoss EAP 7.1 上使用 ActiveMQ Artemis。

我们注意到,一旦具有特定 _AMQ_DUPL_ID 值的消息通过队列,如果消息生产者尝试再次将具有相同 _AMQ_DUPL_ID 值的消息发送到同一队列,它被经纪人丢弃。然而,我们的需求是仅当它们仍在队列中时才丢弃重复消息。

有没有办法实现这个目标?

我们使用数据库中的主键作为 _AMQ_DUPL_ID 值。这是我们使用的代码

public void sendMessage(final T msg, final String id) { 
   jmsTemplate.send(destination, new MessageCreator() { 
      @Override
      public Message createMessage(Session session) throws JMSException { 
         Message message = session.createObjectMessage(msg);
         message.setStringProperty("_AMQ_DUPL_ID", id);
         return message;
      }
   });
}

我们正在寻找解决方案,因为我们有一个计时器,每 30 秒从数据库加载所有具有 status 字段特定值的记录,并将它们放入 JMS 队列.

消费者使用 JMS 消息,处理它们,更新它们的 status 字段,insert/update 它们进入数据库并打开与我们不使用的另一个应用程序的 websocket 连接控制。有时消费者会挂起 websocket 调用,因此,当计时器继续填充队列时它仍然很忙。

为了解决这个问题,我们认为像 Artemis 重复消息检测这样的东西会有所帮助。然而,当外部应用挂起我们的消费者时,我们需要我们的计时器能够再次将消息放入队列。

A​​ctiveMQ Artemis 上的重复消息检测按设计工作。它的目标是避免消费者收到重复消息的任何机会,这意味着即使消息可能不再在队列中(例如,因为它已被消费),该消息的任何重复仍应被拒绝。

您在这里的要求类似于询问如何将具有相同主键的多条记录插入数据库 table。它根本不能,因为拥有主键的全部意义在于避免重复记录。

我建议您为 websocket 调用实施某种超时,否则您的应用程序将受到您无法控制的资源的负面影响。

除此之外,您 可能 能够使用 last-value queue 并使用主键作为 _AMQ_LVQ_NAME 的值。这将保证在任何时候只有 1 个消息实例在队列中。阅读文档了解更多详情。