Подтвердить что ты не робот

Spring Синхронность транзакций JDBC и JMS

У меня есть веб-приложение spring, работающее на jboss, которое в настоящее время настроено на использование HibernateTransactionManager для транзакций db и JmsTransactionManager для jms. Для jms мы используем Camel и ActiveMQ, наша база данных - DB2. Внутри транзакции мне нужно записать несколько записей в базу данных и отправить два асинхронных сообщения jms. Сообщения jms представляют собой уведомления о событиях, и я хочу, чтобы они были отправлены, если транзакция базы данных совершается.

Я готов принять риск сообщения с брокерским сбоем после того, как транзакция jdbc уже совершена (и, следовательно, не отправлено сообщений, а db), поэтому я не думаю, что мне нужен правильный XA.

Я считаю, что мне нужно управление транзакциями "с наилучшими усилиями" с использованием транзакционной синхронизации spring.

Описание документации spring указывает на то, что spring синхронизирует две транзакции и совершает транзакцию jms только после того, как транзакция jdbc была совершена, но я не думаю, что это очень ясно. Документация spring здесь http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#tx-resource-synchronization не содержит подробных сведений о том, как она работает.

Я нашел несколько других источников, которые говорят, что spring будет делать то, что я хочу, включая некоторые javadoc ниже, и я написал некоторые интеграционные тесты, которые также показывают его.

http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/jms/support/JmsAccessor.html#setSessionTransacted%28boolean%29 javadoc on setSessionTransacted здесь звучит точно так, как я хочу.

Из того, что я видел, я думаю, что создание Camel JmsConfiguration с транзакционным множеством в true, как это достаточно:

<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
    <property name="connectionFactory" ref="pooledConnectionFactory"/>
    <property name="transacted" value="true"/>
    <property name="concurrentConsumers" value="10"/>
</bean>

Однако мне нужно убедить кого-то, с кем я работаю, с немного скептически настроенным и думает, что мой интеграционный тест работает только из-за плохо документированного побочного эффекта, а не для намеренной функции spring.

Итак, мой вопрос: я исправлю, что на spring можно полагаться на синхронизацию транзакций и всегда фиксировать транзакцию jms после транзакции jdbc или это не то, на что я должен положиться, и вы могли бы указать мне на любая официальная документация, которая гласит это четко? И я предполагаю, что в целом это хороший подход для принятия или должен управлять этими транзакциями по-другому?

4b9b3361

Ответ 3

Если вы используете локальные транзакции И usecase - это сохранить в базу данных, а затем отправить в jms

Тогда могут быть три случая:

  • Исключение сразу после получения (до DB и JMS)

Без проблем все будет откатываться

  1. После сохранения в DB у нас есть исключение

Если есть операция вставки, в результате повторных попыток будет выполняться несколько строк в БД. С каждой попыткой будет выполнена вставка. И для JMS сообщение перейдет в DeadLetterQueue

  1. После сохранения в БД и отправки в JMS у нас есть исключение

    Если есть операция вставки, в результате повторных попыток будет выполняться несколько строк в БД. С каждой попыткой будет выполнена вставка. И для JMS сообщение перейдет в DeadLetterQueue

Теперь вы не хотите использовать XA, поэтому решения могут быть

1) Проверьте If (message.getJmsRedelivered() {...}

Если нет, обработайте его

Если его переадресовано, проверьте, обработали ли вы его уже

Проверьте, находятся ли данные в базе данных на основе сведений в сообщении

Обратите внимание, что повторные поставки редки, поэтому эта проверка также редка и нет накладных расходов

2) Если ваш метод идемпотент, вам не нужна эта проверка

И что касается XA, XA гарантирует, что сообщение доставляется только один раз И синхронизировать транзакцию через несколько ресурсов.

Но с XA у вас есть служебные

Итак, если вы можете обойтись без XA, предпочтительнее