5

Hibernate と PostgreSQL を使用する Spring アプリケーションがあります。また、Spring AMQP (RabbitMQ) も使用します。

次のように構成された Hibernate Transaction Manager を使用しています。

<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager"
    p:sessionFactory-ref="sessionFactory" p:dataSource-ref="dataSource" />

次のように構成された非同期メッセージ受信に SimpleMessageListenerContainer を使用しています。

@Resource(name="transactionManager")
private PlatformTransactionManager txManager;

@Autowired
private MyListener messageListener;

@Bean
public SimpleMessageListenerContainer mySMLC()
{
    final SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(rabbitConnectionFactory);
    container.setQueueNames("myQueue");

    final MessageListenerAdapter adapter = new MessageListenerAdapter(messageListener);
    adapter.setMessageConverter(converter);
    container.setMessageListener(adapter);
    container.setChannelTransacted(true);
    container.setTransactionManager(txManager);
    return container;
}

したがって、基本的に、メッセージの受信はトランザクションである必要があると指定しました。メッセージ リスナーは、@Transactional でアノテーションを付けたメソッドを持つことができるサービスを呼び出し、場合によっては DB で CRUD 操作を実行します。

私の質問は、HibernateTransactionManager を使用して SimpleMessageListenerContainer レベルでトランザクションを管理することに問題はありますか? DB トランザクション マネージャーを使用して、RabbitMQ からのメッセージの受信をラップする問題はありますか?

私はここで XA を期待していません。サービスによる DB での操作が失敗した場合に、メッセージが RabbitMQ ブローカーに ack されないようにしたいだけです。

4

1 に答える 1

1

Spring のソースによると、MessageListenerContainer の transactionManager プロパティの主な目的は、リスナー呼び出しの前に受信したメッセージでトランザクションを開始し、リスナーが例外を返すかスローした後にトランザクションをコミットまたはロールバックすることです。したがって、リスナーメソッドが呼び出される前にトランザクションがすでに開始されているため、リスナーメソッドを @Transactional にする必要はありません。

リスナーでエラーが発生した場合、例外がスローされ、DB トランザクションがロールバックされ、メッセージ ブローカーに ack が送信されません (jms トランザクション ロールバック)。ただし、XA がないと、メッセージが重複する可能性があります。たとえば、DB トランザクションが正常にコミットされた後、メッセージ ブローカーへの接続がリセットされ、ack をブローカーに送信できませんでした。再接続後、ブローカーは重複したメッセージを配信する可能性があります。これを認めれば、XA を扱う必要はありません。

于 2014-09-15T20:34:07.000 に答える