避免在JMS / ActiveMQ上重复的消息

时间:2011-02-08 14:41:34

标签: java duplicates jms activemq mom

有一种方法可以抑制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是否有类似的解决方案?

5 个答案:

答案 0 :(得分:7)

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

将它与ActiveMQ组件结合使用可以非常简单地使用JMS,请参阅: http://camel.apache.org/activemq.html

答案 1 :(得分:4)

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

我在同一行看到了之前的stackoverflow问题 - Apache ActiveMQ 5.3 - How to configure a queue to reject duplicate messages?,这也可能会有所帮助。

答案 2 :(得分:4)

现在支持删除烘焙到ActiveMQ传输中的重复邮件。请参阅Connection Configuration Guide中的配置值auditDepthauditMaximumProducerNumber

答案 3 :(得分:3)

有一种方法可以让ActiveMQ根据JMS属性过滤重复项。它涉及写一个Activemq Plugin。将重复消息发送到deadletter队列的基本代理过滤器就像这样

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);
            } 
        }
    }  
}

答案 4 :(得分:0)

似乎问题中提出的方式,也适用于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