2011-02-08 17 views
17

Istnieje sposób na zduszenie zduplikowanych wiadomości w kolejce zdefiniowanej na serwerze ActiveMQ?Unikanie zduplikowanych wiadomości w JMS/ActiveMQ

Próbowałem zdefiniować ręcznie JMSMessageID, (message.setJMSMessageID ("uniqueid")), ale serwer ignoruje tę modyfikację i dostarcza komunikat z wbudowanym wygenerowanym identyfikatorem JMSMessageID.

Według specyfikacji nie znalazłem odniesienia do deduplikacji wiadomości.

W HornetQ, aby poradzić sobie z tym problemem, musimy zadeklarować specyficzną właściwość HQ org.hornetq.core.message.impl.HDR_DUPLICATE_DETECTION_ID w definicji wiadomości.

tj .:

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

Ktoś wie, czy istnieje podobne rozwiązanie dla ActiveMQ?

Odpowiedz

7

Należy spojrzeć na Apache Camel, stanowi składnik konsumentów idempotent że będzie pracować z dowolnego dostawcy JMS, patrz: http://camel.apache.org/idempotent-consumer.html

Korzystanie które w połączeniu z ActiveMQ składnik sprawia, że ​​korzystanie JMS dość proste, patrz: http://camel.apache.org/activemq.html

+1

Mam wątpliwości, czy ta metoda rozwiąże mój problem. Muszę zachować tylko jedną instancję wiadomości z tym samym identyfikatorem JMSMessageID, podczas gdy ta instancja jest w kolejce. Potrzebuję tego działając jako zestaw. Chcę móc umieścić inną wiadomość o tym samym identyfikatorze JMSMessageID po usunięciu ostatniego elementu idem z kolejki. Muszę to wdrożyć i przetestować. Ale w oparciu o Idempotent opisany w książce EAI, myślę, że koncepcja nie pasuje do mojej konieczności. BUt, proponowane rozwiązanie jest dobre. Będę uczyć się więcej o tym i komentować moje wyniki. Dzięki – apast

4

Wątpię, czy ActiveMQ obsługuje je natywnie, ale powinno być łatwe wdrożenie idempotentnego konsumenta. Można to zrobić, dodając unikalny identyfikator do każdej wiadomości po stronie producenta, teraz po stronie konsumenta, używając magazynu (db, cache itp.), Można sprawdzić, czy wiadomość została odebrana przed kontynuować proces w oparciu o tę kontrolę.

Widzę poprzednie pytanie stackoverflow wzdłuż tych samych linii - Apache ActiveMQ 5.3 - How to configure a queue to reject duplicate messages?, które mogą również pomóc.

3

Istnieje sposób, aby ActiveMQ filtrować duplikaty na podstawie właściwości JMS. wymaga napisania Activemqa Plugin. Podstawowy filtr pośrednik, który wysyła zduplikowane wiadomości do kolejki deadletter byłoby jak to

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

zdecydowanie bardzo bardzo dobry sposób na rozwiązanie tego problemu. – user1052080

3

Jest teraz obsługiwać do usuwania zduplikowanych wiadomości upieczone w ActiveMQ transportuje. Zobacz wartości konfiguracyjne auditDepth i auditMaximumProducerNumber w Connection Configuration Guide.

+3

jak właściwie skonfigurować te parametry, aby uniknąć duplikatów? – Thomas

+0

@ Thomas Nie jestem pewien, o co pytasz. Jak na ogół zastosować konfigurację w ActiveMQ? Lub jakie wartości użyć dla tych konkretnych pól? –

+0

Po prostu dlatego, że z opisu parametrów nie wydaje mi się to tak jasne. Na przykład wartość 'auditDepth' oznacza wartość Nb komunikatów lub nb bajtów, które będą wyświetlane z powrotem dla duplikacji? Jeśli chodzi o "auditMaximumProducerNumber", czy oznacza to, że istnieje ograniczona liczba producentów, którzy zostaną poddani kontroli bezpieczeństwa? Przy okazji, jeśli wiadomość o tej samej treści została opublikowana przez 2 różnych subskrybentów, wiadomość jest przypadkiem uważana za zduplikowaną? – Thomas

0

Wydaje się, że sposób sugerowany w pytaniu działa również dla ActiveMQ (2016/12). Zobacz przewodnik activemq-artemis. Wymaga to od producenta ustawienia określonej właściwości w wiadomości.

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

Jednak klasa zawierający właściwość jest inna: org.apache.activemq.artemis.core.message.impl.HDR_DUPLICATE_DETECTION_ID a wartość nieruchomości jest _AMQ_DUPL_ID.