5

私たちのアプリケーションは、mongodb レプリカ セットに基づいて構築されています。レプリカ セットが自動フェールオーバーの処理中の時間枠内でスローされたすべての例外をキャッチしたいと考えています。アプリケーションを再試行するか、フェイルオーバーが完了するまで待ちます。フェイルオーバーがユーザーに影響を与えないように。ここで Java ドライバーの動作を説明するドキュメントを見つけました: https://jira.mongodb.org/browse/DOCS-581

考えられるすべての例外を見つけるテスト プログラムを作成します。それらはすべて MongoException ですが、メッセージが異なります。

  1. MongoException.Network: "サーバー /10.11.0.121:27017 への読み取り操作がデータベース テストで失敗しました"
  2. MongoException: 「マスターが見つかりません」
  3. MongoException: 「マスターと通信せず、再試行が使い果たされました」
  4. MongoException: "{ "mode" : "primary"} の [ここにレプリカ セットのステータスがあります] で使用できるレプリカ セット メンバーはありません"
  5. おそらくもっとある...

混乱しており、エラー メッセージで判断しても安全かどうかわかりません。また、すべての MongoException をキャッチしたくありません。なにか提案を?

ありがとう

4

3 に答える 3

2

私は今、Mongo in Java はこの点で特に弱いと考えています。エラーコードを解釈するあなたの戦略がうまくスケーリングされたり、ドライバーの進化に耐えられたりするとは思いません。もちろん、これは意見です。

良いニュースは、Mongo ドライバーが ReplicaSet のステータスを取得する方法を提供することです: http://api.mongodb.org/java/2.11.1/com/mongodb/ReplicaSetStatus.html。これを直接使用して、アプリケーションに表示されるマスターがあるかどうかを確認できます。これだけ知りたい場合は、http://api.mongodb.org/java/2.11.1/com/mongodb/Mongo.html#getReplicaSetStatus()で十分です。その子供をつかんで、null でないマスターをチェックしてください。

ReplicaSetStatus rss = mongo.getReplicaSetStatus();
boolean driverInFailover = rss.getMaster() == null;

ReplSet が死んでいるか、読み取り専用か、読み書き可能かを判断することが本当に必要な場合、これはさらに困難になります。これは、私にとってはうまくいくコードです。私はそれが嫌いです。

@Override
public ReplSetStatus getReplSetStatus() {
    ReplSetStatus rss = ReplSetStatus.DOWN;
    MongoClient freshClient = null;
    try {
        if ( mongo != null ) {
            ReplicaSetStatus replicaSetStatus = mongo.getReplicaSetStatus();
            if ( replicaSetStatus != null ) {
                if ( replicaSetStatus.getMaster() != null ) {
                    rss = ReplSetStatus.ReadWrite;
                } else {
                    /*
                     * When mongo.getReplicaSetStatus().getMaster() returns null, it takes a a
                     * fresh client to assert whether the ReplSet is read-only or completely
                     * down. I freaking hate this, but take it up with 10gen.
                     */
                    freshClient = new MongoClient( mongo.getAllAddress(), mongo.getMongoClientOptions() );
                    replicaSetStatus = freshClient.getReplicaSetStatus();
                    if ( replicaSetStatus != null ) {
                        rss = replicaSetStatus.getMaster() != null ? ReplSetStatus.ReadWrite : ReplSetStatus.ReadOnly;
                    } else {
                        log.warn( "freshClient.getReplicaSetStatus() is null" );
                    }
                }
            } else {
                log.warn( "mongo.getReplicaSetStatus() returned null" );
            }
        } else {
            throw new IllegalStateException( "mongo is null?!?" );
        }
    } catch ( Throwable t ) {
        log.error( "Ingore unexpected error", t );
    } finally {
        if ( freshClient != null ) {
            freshClient.close();
        }
    }
    log.debug( "getReplSetStatus(): {}", rss );
    return rss;
}

アプリケーションのMongo Java Driver規則に従わないため、単一のMongoのみが必要であり、このシングルトンを介して残りのMongoデータ構造(DB、コレクションなど)に接続するため、嫌いです。「ReplSet-DOWN」と「読み取り専用」を区別するために ReplicaSetStatus null チェックに依存できるように、チェック中に 2 番目の Mongo を新しくすることによってのみ、この動作を観察できました。

このドライバーで本当に必要なのは、Mongo に直接質問して、現時点で ReplSet が WriteConcerns または ReadPreferences のそれぞれをサポートできるかどうかを確認する方法です。何かのようなもの...

/**
 * @return true if current state of Client can support readPreference, false otherwise
 */
boolean mongo.canDoRead( ReadPreference readPreference )

/**
 * @return true if current state of Client can support writeConcern; false otherwise
 */
boolean mongo.canDoWrite( WriteConcern writeConcern ) 

これは、Mongo が作成されたときに ReplSet が優れていた可能性があるという事実を認めているため、私には理にかなっていますが、現在の条件は、条件の変化により特定のタイプの読み取りまたは書き込み操作が失敗する可能性があることを意味します。

いずれにせよ、おそらくhttp://api.mongodb.org/java/2.11.1/com/mongodb/ReplicaSetStatus.htmlで必要なものが得られます。

于 2013-10-01T23:28:57.363 に答える
0

Java ドライバーの実装自体はわかりませんが、すべてMongoExceptionの s をキャッチしてから、それらに基づいてフィルター処理しgetCode()ます。エラー コードがレプリカ セットの失敗に当てはまらない場合は、MongoException.

問題は、私の知る限り、ドキュメントにエラー コードの参照がないことです。ここにスタブがありますが、これはかなり不完全です。唯一の方法は、Java ドライバーのコードを読んで、それが使用するコードを知ることです…</p>

于 2013-08-05T10:09:30.087 に答える