Avoiding duplicated messages on JMS/ActiveMQ

前端 未结 5 1457
时光取名叫无心
时光取名叫无心 2020-12-14 08:54

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

I tried to define manually JMSMessageID, (message.setJMSMessageID(\"uniqueid\")

相关标签:
5条回答
  • 2020-12-14 09:09

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

    0 讨论(0)
  • 2020-12-14 09:10

    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);
                } 
            }
        }  
    }
    
    0 讨论(0)
  • 2020-12-14 09:25

    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

    0 讨论(0)
  • 2020-12-14 09:28

    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.

    0 讨论(0)
  • 2020-12-14 09:28

    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.

    0 讨论(0)
提交回复
热议问题