Повторная доставка Spring Boot JMS ActiveMQ при аварийном переключении

У меня есть потребительское приложение, которое использует Spring Boot JMS для прослушивания сообщения из очереди. Это приложение подключено к кластеру ActiveMQ с аварийным переключением для обеспечения высокой доступности. Но у меня возникает следующая проблема: когда я выключаю один из брокеров, и приложение обрабатывает одно сообщение, это сообщение не удаляется из очереди, а когда приложение подключается к другому брокеру, сообщение доставляется повторно. Проблема в том, что сообщение было обработано в первый раз, и мне не нужно его обрабатывать повторно.

Я искал режимы подтверждения и пытался использовать клиентский режим для принудительного подтверждения перед обработкой сообщения. Но я не работал. Любая идея??

Я объявил следующие бобы:

@Bean
    public ActiveMQConnectionFactory jmsConnectionFactory() {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerUrl);
        connectionFactory.setUserName(brokerName);
        connectionFactory.setPassword(brokerPassword);
        connectionFactory.setTrustAllPackages(true);
        return connectionFactory;
    }

    @Bean
    public JmsTemplate jmsTemplate() {
        JmsTemplate jmsTemplate = new JmsTemplate();
        jmsTemplate.setConnectionFactory(jmsConnectionFactory());
        jmsTemplate.setSessionTransacted(false);
        jmsTemplate.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
        jmsTemplate.setDefaultDestinationName(REMOTE_T);
        return jmsTemplate;
    }


    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerFactory(
            @Qualifier("jmsConnectionFactory") ConnectionFactory connectionFactory,
            DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setSessionTransacted(false);
        factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
        configurer.configure(factory, connectionFactory);
        return factory;
    }

Код моего слушателя:

@JmsListener(destination = "Consumer.consumer1.VirtualTopic.TopicPrueba", containerFactory = "jmsListenerContainerFactory")
    public void receiveMessageFromContacts(Message message) {
        try {
            message.acknowledge();
            TextMessage txtMessage = (TextMessage)message;
            mensajesConsumer1++;
            System.out.println("First Consumer:"+ txtMessage.getText()+ " received:"+mensajesConsumer1);    
        }catch(JMSException e) {
            e.printStackTrace();
        }
    }

Не уверен, правильно ли я понял режим подтверждения клиента.

Пожалуйста помоги! :)

Заранее спасибо!

как вы думаете, почему сообщение было обработано? Нет ли исключения, когда вы закрываете одного брокера?

Simon Martinelli 20.11.2018 12:25

Когда я выключил брокера, у меня возникло исключение JMSException, которое, как я предполагал, выдается, когда я пытаюсь отправить подтверждение, потому что сообщение повторно доставляется от второго брокера. Более того, у слушателя есть счетчик входящих сообщений, и этот счетчик увеличивает свое значение, даже когда генерируется исключение.

Pedro Ramírez Pérez 20.11.2018 12:40

но в этом случае все работает как надо. Это не подтверждается из-за отключения брокера. Или я что-то упускаю?

Simon Martinelli 20.11.2018 14:28

Если вы просмотрите код слушателя, я представил вызов message.acknowledge (); Я предполагал, что это немедленно отправит подтверждение.

Pedro Ramírez Pérez 20.11.2018 14:33

Я предполагаю, что когда генерируется исключение JMSException, оно не знает.

Simon Martinelli 20.11.2018 15:11

Вам следует рассмотреть возможность использования Transaction с JmsListener, чтобы иметь транзакционную семантику.

Simon Martinelli 20.11.2018 15:12

Извини, Саймон, возможно, я неправильно объяснил свою ситуацию. Я отлаживаю свое приложение и уверен, что получаю сообщение, но когда я вызываю метод подтверждения, сообщение не удаляется из очереди. Я думаю, что в режиме подтверждения клиента так и должно быть.

Pedro Ramírez Pérez 20.11.2018 15:45

JmsListener использует AUTO_ACKNOWLEDGE, поэтому он должен быть подтвержден, НО если выдается исключение JMSException, оно не будет подтверждено.

Simon Martinelli 20.11.2018 15:49

Спасибо! Это имеет смысл в моей ситуации. Я попробую без JmsListener.

Pedro Ramírez Pérez 20.11.2018 15:51

Можно ли изменить настройку режима подтверждения объекта factroy слушателя ?? Я попробовал ввести свой код, но это не сработало.

Pedro Ramírez Pérez 20.11.2018 16:05

Если вы используете транзакцию, вам не нужно устанавливать режим подтверждения. Прочтите API Doc docs.spring.io/spring-framework/docs/current/javadoc-api/org‌ /…

Simon Martinelli 20.11.2018 16:49

Мне нужно установить режим подтверждения и отсутствие транзакции, потому что я не хочу обрабатывать сообщение, если я не могу отправить acknoledege из-за ошибки подключения.

Pedro Ramírez Pérez 20.11.2018 20:43

И для этого нужны транзакции ...

Simon Martinelli 21.11.2018 07:28
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
13
998
0

Другие вопросы по теме