2011-02-08 51 views
17

¿Hay alguna manera de suprimir los mensajes duplicados en una cola definida en el servidor ActiveMQ?Evitar mensajes duplicados en JMS/ActiveMQ

Traté de definir manualmente JMSMessageID, (message.setJMSMessageID ("uniqueid")), pero el servidor ignora esta modificación y entrega un mensaje con el identificador JMSMessage generado incorporado.

Por especificación, no encontré una referencia sobre cómo deduplicar mensajes.

En HornetQ, para resolver este problema, debemos declarar la propiedad específica HQ org.hornetq.core.message.impl.HDR_DUPLICATE_DETECTION_ID en la definición del mensaje.

es decir .:

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

Alguien sabe si hay una solución similar para ActiveMQ?

Respuesta

7

Usted debe mirar Apache Camel, que proporciona un componente de consumo idempotente que funcionaría con cualquier proveedor de JMS, consulte: http://camel.apache.org/idempotent-consumer.html

El uso que, en combinación con los ActiveMQ componente hace que el uso de JMS bastante simples, ver: http://camel.apache.org/activemq.html

+1

Estoy en duda si este método resolverá mi problema. Necesito mantener solo una instancia de mensaje con el mismo JMSMessageID solo durante esta instancia está en cola. Lo necesito trabajando como un conjunto. Quiero ser capaz de poner otro mensaje con el mismo JMSMessageID después de eliminar el último elemento idem de la cola. Necesito implementarlo y probarlo. Pero, basado en Idempotent descrito en el libro de EAI, creo que el concepto no coincide con mi necesidad. BU, la solución propuesta es buena. Estudiaré más sobre él y comentaré aquí mis resultados. Gracias – apast

4

Dudo si ActiveMQ lo admite de forma nativa, pero debería ser fácil implementar un consumidor idempotente. Una forma de hacerlo sería agregar un identificador único a cada mensaje en el extremo del productor, ahora en el extremo consumidor usando una tienda (db, caché, etc.), se puede verificar si el mensaje se ha recibido antes y continuar procesando basado en ese cheque.

Veo una pregunta sobre el stackoverflow anterior en la misma línea - Apache ActiveMQ 5.3 - How to configure a queue to reject duplicate messages?, que también puede ayudar.

3

Hay una manera de hacer ActiveMQ para filtrar duplicados basados ​​en una propiedad JMS. implica escribir un Activemq Plugin. Un filtro agente básico que envía mensajes duplicados a la cola deadletter sería así

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

definitivamente una muy buena manera de resolver este problema. – user1052080

3

En la actualidad existe la posibilidad de quitar los mensajes duplicados horno en ActiveMQ transporta. Consulte los valores de configuración auditDepth y auditMaximumProducerNumber en el Connection Configuration Guide.

+3

¿cómo se configuran esos parámetros para evitar duplicados? – Thomas

+0

@Thomas No estoy seguro de lo que estás preguntando. ¿Cómo, en general, aplicar la configuración en ActiveMQ? ¿O qué valores usar para estos campos específicos? –

+0

Es solo que por la descripción de los parámetros no me parece tan claro. El 'auditDepth' por ejemplo, ¿el valor allí significa el Nb de mensajes o el nb de bytes que serán seleccionados para duplicaciones? Con respecto al 'auditMaximumProducerNumber', ¿eso significa que hay una cantidad limitada de productores que se proyectarán? Por cierto, si un mensaje con el mismo contenido es publicado por 2 suscriptores diferentes, ¿el mensaje por casualidad se considera duplicado? – Thomas

0

Parece la forma en que se sugiere en la pregunta, también funciona para ActiveMQ (2016/12). Consulte la guía activemq-artemis. Esto requiere que el productor establezca una propiedad específica en el mensaje.

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

Sin embargo la clase que contiene la propiedad es diferente: org.apache.activemq.artemis.core.message.impl.HDR_DUPLICATE_DETECTION_ID y el valor de la propiedad es _AMQ_DUPL_ID.

Cuestiones relacionadas