避免 JMS/ActiveMQ 上的重复消息

发布于 2024-10-16 04:35:59 字数 549 浏览 11 评论 0原文

有没有办法抑制 ActiveMQ 服务器上定义的队列上的重复消息?

我尝试手动定义 JMSMessageID (message.setJMSMessageID("uniqueid")),但服务器忽略此修改并使用内置生成的 JMSMessageID 传递消息。

根据规范,我没有找到有关如何删除重复消息的参考。

在HornetQ中,为了处理这个问题,我们需要在消息定义上声明HQ特定的属性org.hornetq.core.message.impl.HDR_DUPLICATE_DETECTION_ID。

即:

Message jmsMessage = session.createMessage();
String myUniqueID = "This is my unique id"; // Could use a UUID for this
message.setStringProperty(HDR_DUPLICATE_DETECTION_ID.toString(), myUniqueID);

有人知道 ActiveMQ 是否有类似的解决方案?

Is there a way to suppress duplicated messages on a queue defined on ActiveMQ server?

I tried to define manually JMSMessageID, (message.setJMSMessageID("uniqueid")), but server ignores this modification and deliver a message with built-in generated JMSMessageID.

By specification, I didn't found a reference about how to deduplicate messages.

In HornetQ, to deal with this problem, we need to declare the HQ specific property org.hornetq.core.message.impl.HDR_DUPLICATE_DETECTION_ID on message definition.

i.e.:

Message jmsMessage = session.createMessage();
String myUniqueID = "This is my unique id"; // Could use a UUID for this
message.setStringProperty(HDR_DUPLICATE_DETECTION_ID.toString(), myUniqueID);

Somebody knows if there's a similar solution for ActiveMQ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

空城仅有旧梦在 2024-10-23 04:35:59

您应该查看 Apache Camel,它提供了一个幂等消费者组件,可以与任何 JMS 提供程序一起使用,请参阅: http://camel.apache.org/idempot-consumer.html

将其与 ActiveMQ 组件结合使用使得 JMS 的使用变得非常简单,请参阅:
http://camel.apache.org/activemq.html

You should look at Apache Camel, it provides an Idempotent consumer component that would work with any JMS provider, see: http://camel.apache.org/idempotent-consumer.html

Using that in combination with the ActiveMQ component makes using JMS quite simple, see:
http://camel.apache.org/activemq.html

懷念過去 2024-10-23 04:35:59

我怀疑 ActiveMQ 是否原生支持它,但实现幂等消费者应该很容易。实现此目的的一种方法是在生产者端为每条消息添加唯一标识符,现在在消费者端使用存储(数据库、缓存等),可以检查该消息之前是否已收到,并且根据该检查继续处理。

我看到以前的 stackoverflow 问题也有同样的思路 - Apache ActiveMQ 5.3 - 如何配置队列以拒绝重复消息?,这也可能有帮助。

I doubt if ActiveMQ supports it natively, but it should be easy to implement an idempotent consumer. A way to do this would be to add a unique identifier to each message at the producer end, now at the consumer end using a store(db, cache etc), a check can be made to see if the message has been received before and continue to process based on that check.

I see a previous stackoverflow question along the same lines - Apache ActiveMQ 5.3 - How to configure a queue to reject duplicate messages? , that may also help.

长安忆 2024-10-23 04:35:59

现在支持删除 ActiveMQ 传输中包含的重复消息。请参阅 连接配置指南

There is now support for removing duplicate messages baked into ActiveMQ transports. See the configuration values auditDepth and auditMaximumProducerNumber in the Connection Configuration Guide.

洛阳烟雨空心柳 2024-10-23 04:35:59

有一种方法可以让 ActiveMQ 根据 JMS 属性过滤重复项。它涉及编写一个 Activemq 插件。将重复消息发送到死信队列的基本代理过滤器如下所示

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.activemq.broker.Broker;
import org.apache.activemq.command.Message;
import org.apache.activemq.command.ActiveMQMessage;
import org.apache.activemq.broker.BrokerFilter;
import org.apache.activemq.broker.ConnectionContext;
import org.apache.activemq.command.ConnectionInfo;
import org.apache.activemq.broker.ProducerBrokerExchange;

public class DuplicateFilterBroker extends BrokerFilter {
    String messagePropertyName;
    boolean switchValue;

    public DuplicateFilterBroker(Broker next, String messagePropertyName) {
        super(next);
        this.messagePropertyName = messagePropertyName;
    }

    public boolean hasDuplicate(String propertyValue){
        switchValue = propertyValue;
        return switchValue;
    }

    public void send(ProducerBrokerExchange producerExchange, Message msg) throws Exception { 
        ActiveMQMessage amqmsg = (ActiveMQMessage)msg; 
        Object msgObj = msg.getMessage(); 
        if (msgObj instanceof javax.jms.Message) { 
            javax.jms.Message jmsMsg = (javax.jms.Message) msgObj; 
            if (!hasDuplicate(jmsMsg.getStringProperty(messagePropertyName))) {
                super.send(producerExchange, msg);
            }
            else {
               sendToDeadLetterQueue(producerExchange.getConnectionContext(), msg);
            } 
        }
    }  
}

There is a way to make ActiveMQ to filter duplicates based on a JMS property. it involves writing an Activemq Plugin. A basic broker filter that sends duplicate messages to the deadletter queue would be like this

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.activemq.broker.Broker;
import org.apache.activemq.command.Message;
import org.apache.activemq.command.ActiveMQMessage;
import org.apache.activemq.broker.BrokerFilter;
import org.apache.activemq.broker.ConnectionContext;
import org.apache.activemq.command.ConnectionInfo;
import org.apache.activemq.broker.ProducerBrokerExchange;

public class DuplicateFilterBroker extends BrokerFilter {
    String messagePropertyName;
    boolean switchValue;

    public DuplicateFilterBroker(Broker next, String messagePropertyName) {
        super(next);
        this.messagePropertyName = messagePropertyName;
    }

    public boolean hasDuplicate(String propertyValue){
        switchValue = propertyValue;
        return switchValue;
    }

    public void send(ProducerBrokerExchange producerExchange, Message msg) throws Exception { 
        ActiveMQMessage amqmsg = (ActiveMQMessage)msg; 
        Object msgObj = msg.getMessage(); 
        if (msgObj instanceof javax.jms.Message) { 
            javax.jms.Message jmsMsg = (javax.jms.Message) msgObj; 
            if (!hasDuplicate(jmsMsg.getStringProperty(messagePropertyName))) {
                super.send(producerExchange, msg);
            }
            else {
               sendToDeadLetterQueue(producerExchange.getConnectionContext(), msg);
            } 
        }
    }  
}
无语# 2024-10-23 04:35:59

看起来问题中建议的方式也适用于 ActiveMQ(2016/12)。请参阅 activemq-artemis 指南。这需要生产者在消息中设置特定的属性。

Message jmsMessage = session.createMessage();
String myUniqueID = "This is my unique id";   // Could use a UUID for this
message.setStringProperty(HDR_DUPLICATE_DETECTION_ID.toString(), myUniqueID);

然而包含该属性的类是不同的:
org.apache.activemq.artemis.core.message.impl.HDR_DUPLICATE_DETECTION_ID,属性值为_AMQ_DUPL_ID

Seem the way that is suggested in the question, works for ActiveMQ too (2016/12). See the activemq-artemis guide. This requires the producer to set a specific property into the message.

Message jmsMessage = session.createMessage();
String myUniqueID = "This is my unique id";   // Could use a UUID for this
message.setStringProperty(HDR_DUPLICATE_DETECTION_ID.toString(), myUniqueID);

However the class containing the property is different:
org.apache.activemq.artemis.core.message.impl.HDR_DUPLICATE_DETECTION_ID and the property value is _AMQ_DUPL_ID.

你げ笑在眉眼 2024-10-23 04:35:59

您是否尝试过设置jms.checkForDuplicates=true

Have you tried setting jms.checkForDuplicates=true?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文