14

Java ループで大量のデータを MongoDB に書き込もうとしています。開いている接続の数に基づいてエラーが発生しています。

私の理論では、MongoDB はトランザクションに対応していないため、多数の接続を同時に開くことができるというものです。ただし、Java コードは非常に高速にループすることもできます。一定の時間が経過すると、ループの反復回数が利用可能な接続の数を追い越し始め、Mongo は壁にぶつかります。

私のコードは次のようになります。しないことをお勧めしm.close()ますが、エラーがさらに速くなります。

public static void upsert(){
    Mongo m = null;
    DB db = null;

    try {
    m = new Mongo("localhost");
    db = m.getDB("sempedia");    } catch (UnknownHostException e1) { e1.printStackTrace(); } catch (MongoException e1) { e1.printStackTrace(); }

    // create documents
    // I am doing an upsert - hence the doc, doc
    DBCollection triples;
try {
        triples = db.getCollection("triples");
        triples.update(doc,doc,true,false); 
    } catch (MongoException e) { e.printStackTrace(); }

    m.close();
}

私のJavaコンソールでは、次のエラーが表示されます:

警告: java.net.SocketException を使用して maxBSON サイズを決定する例外: 接続のリセット

そしてmongodbはこのエラーを出します:

Tue Oct 25 22:31:39 [initandlisten] 開いている接続が多すぎるため、接続が拒否されました: 204/204

この問題に対処する最もエレガントな方法は何でしょうか?

4

2 に答える 2

22

個々の操作ごとに Mongo クラスのインスタンスを作成しています。各インスタンスは少なくとも 1 つの接続 (ただし、デフォルトでは 10) を作成して保持し、Java GC が Mongo インスタンスをクリーンアップする場合、または close() を呼び出した場合にのみ、これらの接続が削除されるため、これは機能しません。

問題は、どちらの場合も、単一のスレッドを使用しても閉じられるよりも速く作成していることです。これにより、接続の最大量が急いで使い果たされます。適切な修正は、シングルトン パターンを使用して 1 つの Mongo インスタンスを維持することです (Mongo.Holder はこのための機能を提供します。Mongo.Holder.connect(..) を試してください)。簡単な「修正」は、マシンのファイル記述子の制限を増やして接続の最大量を大幅に増やすことですが、明らかに最終的に同じ制限に達する可能性があります。(シェルで)を使用して現在の最大値を確認できます:

db.serverStatus().connections

TL;DR : Mongo インスタンスをシングルトンとして扱い、それらを可能な限り長寿命にすれば、あなたは成功します。遅延して作成されたインスタンスを返す静的メソッド getInstance() を使用して MongoFactory を実装すると、うまく機能します。幸運を。

于 2011-10-25T15:40:52.020 に答える