Предотвращение дублирования сообщений на ОМС/в частности, ActiveMQ
есть способ подавить дублированные сообщения в очереди, определенной на сервере ActiveMQ?
Я попытался определить вручную JMSMessageID, (сообщение.setJMSMessageID ("uniqueid")), но сервер игнорирует эту модификацию и доставляет сообщение со встроенным сгенерированным JMSMessageID.
по спецификации я не нашел ссылку о том, как дедуплицировать сообщения.
в HornetQ, чтобы справиться с этой проблемой, нам нужно объявить конкретное свойство HQ орг.hornetq.ядро.сообщение.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 ответов
вы должны посмотреть на Apache Camel, он предоставляет идемпотентный потребительский компонент, который будет работать с любым поставщиком JMS, см.:http://camel.apache.org/idempotent-consumer.html
использование этого в сочетании с компонентом ActiveMQ делает использование JMS довольно простым, см.: http://camel.apache.org/activemq.html
Я сомневаюсь, что ActiveMQ поддерживает его изначально, но это должно быть легко реализовать идемпотентного потребителя. Способ сделать это-добавить уникальный идентификатор к каждому сообщению в конце производителя, теперь в конце потребителя, используя хранилище(БД, кэш и т. д.), Можно проверить, было ли сообщение получено раньше и продолжить обработку на основе этой проверки.
Я вижу предыдущий вопрос stackoverflow по тем же строкам - Apache ActiveMQ 5.3 - как настроить очередь для отклонения повторяющихся сообщений? , что также может помочь.
теперь есть поддержка удаления дубликатов сообщений, запеченных в транспортах ActiveMQ. См. значения конфигурации auditDepth
и auditMaximumProducerNumber
на Руководство По Конфигурации Подключения.
существует способ сделать ActiveMQ фильтровать дубликаты на основе свойства JMS. он включает в себя написание Activemq плагин. Базовый фильтр брокера, который отправляет повторяющиеся сообщения в очередь 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);
}
}
}
}
кажется, способ, который предлагается в вопросе, работает и для 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
.