Возможно ли добиться гарантированного транзакционного поведения с одновременными JmsListeners в весенней загрузке

#spring-boot #listener #ibm-mq #spring-transactions #spring-jms

Вопрос:

Я использую JmsListener Spring boot для удаления сообщений из очереди IBM MQ в сеансе транзакций.

Проблема возникла ,когда его пропускная способность была ограничена примерно 50 транзакциями в секунду(удаление из очереди MQ, обработка и сохранение в базе данных).

ЧТОБЫ повысить пропускную способность, мы увеличили его параллелизм, и это действительно помогло. Но теперь мы видим, что во время перезапуска приложения одно и то же сообщение используется несколькими одновременными слушателями.(К этому я пришел, зарегистрировав имена потоков).

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

Существует ли какой-либо другой способ достижения высокой пропускной способности при сохранении максимальной скорости полного потребления с помощью транзакционного JsmListener?

     @Bean
public PlatformTransactionManager transactionManager() {
    JmsTransactionManager transactionManager = new JmsTransactionManager();
    transactionManager.setConnectionFactory(jmsConnectionFactory());
    return transactionManager;
}
    @Bean
public ConnectionFactory jmsConnectionFactory(){
    MQConnectionFactory cf = new MQConnectionFactory();
    try {
        cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, host);
        cf.setIntProperty(WMQConstants.WMQ_PORT, Integer.parseInt(port));
        cf.setStringProperty(WMQConstants.WMQ_CHANNEL, channel);
        cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
        cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, queueManager);
        cf.setStringProperty(WMQConstants.WMQ_APPLICATIONNAME, "JmsGet (JMS)");
        cf.setBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP, true);
        cf.setStringProperty(WMQConstants.USERID, user);
        cf.setStringProperty(WMQConstants.PASSWORD, password);
        cf.setStringProperty(WMQConstants.WMQ_SSL_CIPHER_SUITE, null);
    } catch (JMSException jmsException) {
        log.error(jmsException.toString());
    }
    return cf;
}
    @Bean
public JmsListenerContainerFactory<?> listenerContainerFactory(ConnectionFactory connectionFactory,
                                                                        DefaultJmsListenerContainerFactoryConfigurer configurer) {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setConcurrency("2");//Added to increase throughput
    factory.setTransactionManager(transactionManager());
    factory.setSessionTransacted(true);
    configurer.configure(factory, connectionFactory);
    return factory;
}
@JmsListener(containerFactory = "listenerContainerFactory", destination = "${input_qname}")
public void onMessage(String message) throws Exception{
//if exception -> throw e; 
}
 

Комментарии:

1. Ваша регистрация, которая завершила это, не могли бы вы показать нам несколько примеров? Если вы используете транзакции, невозможно, чтобы два потребителя получали одно и то же сообщение. Если это действительно то, что вы видите, это было бы недостатком. В ответ на ваш главный вопрос, однако, параллелизм-это именно то, что нужно делать для увеличения пропускной способности обработки.

2. @Moraghugson спасибо за ответ, проблему нелегко смоделировать, поэтому сейчас нет журналов. Но если слушатель потребляет msgs из очереди (в данном случае IBM MQ), как именно возможно одновременное прослушивание? Разве это не должно быть так: 1: MQ отправляет сообщение слушателю, но не делает этого 2: Только одно из приведенных ниже у слушателя: 2a: Успешный процесс и сохранение сообщения и предоставление некоторого подтверждения. 2b: Выбрасывает исключение 3 : Исходя из вышеизложенного, MQ либо отправит сообщение DQ, либо обнаружит откат и снова предоставит ту же msg из-за поведения транзакции. Как возможен вышеуказанный процесс с одновременными потребителями ?

3. Одновременное получение (не просмотр) из очереди возможно, потому что менеджер очередей передает только отдельное сообщение одному получателю. Приложению (слушателю, как вы его называете) не будет передано сообщение, которое было передано кому-то другому, ему будет передано следующее. Если сообщение передается приложению, у которого позже возникнет исключение, то эта транзакция будет откатана, и только тогда то же самое сообщение может быть передано другому приложению. Менеджер очередей управляет транзакциями для обеспечения целостности.