3

現在 Oracle AQ を使用していますが、永続化された ActiveMQ に置き換えたいと考えています。

Oracle AQを使用した現在のセットアップは次のとおりです。

  • DB サーバー: キュー Q1 を持つ Oracle DB
  • アプリ サーバー 1: Q1 にプロデューサーと複数のリスナーがあります
  • アプリ サーバー 2: Q1 にプロデューサーと複数のリスナーがあります

現在、次の流れが続いています。

アプリサーバー 1:

  • Web サービス経由の着信メッセージ
  • DBトランザクション開始
  • メッセージを ID で DB に保存
  • メッセージの ID およびその他の情報をキュー Q1 に投稿します。
  • トランザクションをコミットする

アプリサーバー 2:

  • 同じセットアップ、水平スケーリング

要件

ActiveMQ を実装する場合、DB へのデータと同じトランザクション内のキューへの投稿が必要です。そのため、一方がロールバックを実行すると、もう一方も同様にロールバックします。

両方のアプリ サーバーで同時にキューにメッセージを生成できるようにする必要があるため、アプリ サーバーではなく DB サーバーで ActiveMQ ブローカーを実行する必要があります。それ以外の場合は、「マスター スレーブ」として機能します。

私が読んだ記事では、トランザクション リソースを共有する方法について説明しています。ただし、これは、ActiveMQ ブローカーをトランザクションが開始された場所と同じサーバーに配置することを前提としています。これを達成するためにJTAを使用する以外に方法はありますか?

私はJavaを使用しています:

  • 春 2.5.6
  • 休止状態 3.3
  • トランザクションマネージャー: org.springframework.orm.hibernate3.HibernateTransactionManager
  • データソース: oracle.jdbc.pool.OracleDataSource
4

1 に答える 1

0

私はこれをテストしませんでした。しかし、これはあなたが探しているものではありませんか?

import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.JmsException;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class SomeServiceImpl implements SomeService {

    @Autowired
    private Queue someQueue;

    private JmsTemplate jmsTemplate;
    private SomeRepository repository;

    public SomeServiceImpl() {}

    public SomeServiceImpl(ConnectionFactory activeMQConnectionFactory, SomeRepository repository) {
        this.jmsTemplate = new JmsTemplate(activeMQConnectionFactory);
        this.repository = repository;
    }

    @Transactional(rollbackFor = {JmsException.class, RepositoryException.class})
    public void sendMessage(final SomeObject object) {
        repository.save(object);
        jmsTemplate.send(       
        new MessageCreator() {          
            @Override
            public Message createMessage(Session session) throws JMSException {
                return session.createObjectMessage(object.getSpecialId());
            }
        });
    }

}

この方法では、オブジェクトの保存中にエラーが発生した場合、またはメッセージをキューに送信する際に問題が発生した場合 (JMSException)、ローカル トランザクションはロールバックされ、オブジェクトは保持されません。分散トランザクションは必要ないと思います。

于 2013-11-08T20:55:03.263 に答える