2

JAX-RSを使用してRESTAPIを提供するGlassfish3.1.2クラスターにJavaEEアプリケーションをデプロイしています。EARを複製クラスターインスタンスにデプロイすることでアプリケーションの新しいバージョンを定期的にデプロイしてから、HTTPロードバランサーを更新して、古いインスタンスではなく更新されたインスタンスにトラフィックを送信します。

これにより、http://docs.oracle.com/cd/E18930_01/html/821-2426/abdio.html#abdipで説明されているように、可用性を失うことなくアップグレードできます。私たちは頻繁にアプリケーションに大幅な変更を加えているため、新しいバージョンは「互換性がありません」(これが2つのクラスターを使用する理由です)。

ここで、(C ++プロデューサーからの)高スループットの内部メッセージングのために、アプリケーションにメッセージキューインターフェイスを提供する必要があります。ただし、メッセージ駆動型Beanを使用すると、サービスを中断せずにアプリケーションをアップグレードする方法がわかりません。

私が調査したオプションは次のとおりです。

単一のリモートJMSキュー(openMQ)

プロデューサーはメッセージを単一のメッセージキューに送信し、メッセージはMDBによって処理されます。2番目のクラスターインスタンスを開始するとき、メッセージはアップグレードされたクラスターに負荷分散される必要がありますが、「古い」クラスターを停止すると、未処理のトランザクションが失われます。

アップグレード中にJMXを使用してそのメッセージキューへのプロデューサー/コンシューマーを無効にすることを検討しましたが、それはメッセージ配信を一時停止するだけです。古いクラスターを無効にしても、未処理のメッセージは失われます(私は思いますか?)。

また、@ MessageDrivenアノテーションを破棄し、MessageConsumerを手動で作成することも検討しました。これは機能しているように見えますが、MessageConsumerはEJBアノテーションを使用して他のEJBにアクセスできません(私が知る限り)。

// Singleton bean with start()/stop() functions that 
// enable/disable message consumption

@Singleton
@Startup
public class ServerControl {

private boolean running=false;

@Resource(lookup = "jms/TopicConnectionFactory")
private TopicConnectionFactory topicConnectionFactory;

@Resource(lookup = "jms/MyTopic")
private Topic topic;
private Connection connection;
private Session session;
private MessageConsumer consumer;    

public ServerControl()
{
    this.running = false;         
}

public void start() throws JMSException {
    if( this.running ) return;

    connection = topicConnectionFactory.createConnection();
    session = dbUpdatesConnection.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
    consumer = dbUpdatesSession.createConsumer(topic);
    consumer.setMessageListener(new MessageHandler());    


    // Start the message queue handlers
    connection.start();

    this.running = true;
}

public void stop() throws JMSException {
    if( this.running == false ) return;

    // Stop the message queue handlers

    consumer.close();

    this.running = false;
}
}

// MessageListener has to invoke functions defined in other EJB's

@Stateless
public class MessageHandler implements MessageListener {

@EJB
SomeEjb someEjb; // This is null

public MessageHandler() {
}

@Override
public void onMessage(Message message) {
    // This works but someEjb is null unless I 
    // use the @MessageDriven annotation, but then I 
    // can't gracefully disconnect from the queue
}

}

各クラスターのローカル/埋め込みJMSキュー

  • クライアントは、2つの異なるメッセージキューブローカー(クラスターごとに1つ)に接続する必要があります。
  • クラスターインスタンスがダウンしていることをクライアントに通知し、そのブローカーのキューへのメッセージの送信を停止する必要があります。
  • 一般に、既存のhttpソリューションよりもはるかに便利で整頓されていません。

代替メッセージキュープロバイダー

  • Glassfishを別のタイプのメッセージキューまたは別のベンダー(Apache OpenMQなど)に接続します。おそらく、これらの1つに、特定のコンシューマーのセットからのトラフィックのバランスをとる機能がありますか?

アプリケーションを無効にするだけで、未処理のトランザクションが「強制終了」されると思います。アプリケーションを無効にすると、既存のトランザクションを完了できる場合は、2番目のクラスターを起動した後でそれを実行できます。

どんな助けでもいただければ幸いです!前もって感謝します。

4

2 に答える 2

0

「古い」クラスターを停止すると、未処理のトランザクションが失われるというあなたの仮定が理解できません。MDB は、アプリケーションが停止する前にメッセージ処理を終了することが許可され、未確認のメッセージは「新しい」クラスターによって処理されます。

古いバージョンと新しいバージョンの間の負荷分散が問題になる場合は、MDB を別々に配置し.ear、新しい MDB がオンラインになるとすぐに古い MDB を停止します。ユース ケースで新しいバージョンがオンラインになるまでメッセージ処理の遅延が許される場合は、その前でも構いません。配備されました。

于 2012-06-20T21:50:01.943 に答える
0

高可用性を使用する場合、クラスターのすべてのメッセージは、各インスタンスのローカル データ ストアではなく、単一のデータ ストアに格納されます。その後、同じストアを使用するように両方のクラスターを構成できます。次に、古いものをシャットダウンして新しいものをスピンアップすると、すべてのメッセージにアクセスできます。

これは、glassfish の高可用性 jms を説明するのに役立つ優れたビデオです。

于 2012-06-15T16:19:47.903 に答える