MongoDB JavaドライバーMongoOptionsを本番用に構成するにはどうすればよいですか?


100

私はWebを検索して、MongoDB JavaドライバーのMongoOptionsを構成するためのベストプラクティスを探していましたが、API以外は思いつきませんでした。この検索は、「com.mongodb.DBPortPool $ SemaphoresOut:Out of semaphores to get db connection」エラーが発生し、接続数/乗数を増やすことで問題を解決できた後に開始されました。本番用にこれらのオプションを構成する際のリンクまたはベストプラクティスを探しています。

2.4ドライバーのオプションは次のとおりです。http//api.mongodb.org/java/2.4/com/mongodb/MongoOptions.html

  • autoConnectRetry
  • connectionsPerHost
  • connectTimeout
  • maxWaitTime
  • socketTimeout
  • threadsAllowedToBlockForConnectionMultiplier

新しいドライバーにはより多くのオプションがあり、それらについても聞きたいです。

回答:


160

2.9に更新:

  • autoConnectRetryは、予期しない切断の後にドライバーがサーバーへの再接続を自動的に試行することを意味します。本番環境では、通常、これをtrueに設定します。

  • connectionsPerHostは、単一のMongoインスタンス(シングルトンなので、通常、アプリケーションごとに1つある)がmongod / mongosプロセスに対して確立できる物理接続の量です。執筆時点では、実際のクエリスループットが低くても、最終的にこの量の接続が確立されます(つまり、アプリケーションサーバーごとにこの数に達するまで、mongostatの「conn」統計が上昇します)。

    ほとんどの場合、これを100より大きく設定する必要はありませんが、この設定は「テストして確認する」ことの1つです。サーバーへの接続の合計量が超えないように、この値を十分低く設定する必要があることに注意してください。

    db.serverStatus().connections.available

    生産では、現在40です。

  • connectTimeout。名前が示すように、接続試行が中止される前にドライバーは待機するミリ秒数を示します。タイムアウトを何か長い時間(15から30秒)に設定します。そうしないと、接続試行が成功するのを妨げる可能性があるため、現実的で予期される可能性があります。通常、接続の試行に数秒以上かかる場合、ネットワークインフラストラクチャは高スループットに対応できません。

  • maxWaitTime。接続プールで接続が使用可能になるのをスレッドが待機するミリ秒数。これが間に合わない場合は例外が発生します。デフォルトのままにします。

  • socketTimeout。標準ソケットタイムアウト値。60秒(60000)に設定します。

  • threadsAllowedToBlockForConnectionMultiplier。プールが現在使い果たされている場合に接続が使用可能になるのを待機できるスレッドの数を示すconnectionsPerHostの乗数。これは、「com.mongodb.DBPortPool $ SemaphoresOut:Out of semaphores to get db connection」例外が発生する設定です。このスレッドキューがthreadsAllowedToBlockForConnectionMultiplier値を超えると、この例外がスローされます。たとえば、connectionsPerHostが10で、この値が5の場合、前述の例外がスローされる前に最大50のスレッドがブロックされる可能性があります。

    大きなキューが発生する可能性があるスループットの大きなピークが予想される場合は、この値を一時的に増やします。まさにその理由で、現時点では1500にあります。クエリの負荷が常にサーバーを上回っている場合は、それに応じてハードウェア/スケーリングの状況を改善する必要があります。

  • readPreference(更新、2.8以降)デフォルトの読み取り設定を決定するために使用され、「slaveOk」を置き換えます。クラスファクトリメソッドの1つを使用してReadPreferenceを設定します。最も一般的な設定の完全な説明は、この投稿の最後にあります

  • w(更新、2.6 +)この値は、書き込みの「安全性」を決定します。この値が-1の場合、ネットワークまたはデータベースのエラーに関係なく、書き込みはエラーを報告しません。WriteConcern.NONEは、これに適した事前定義されたWriteConcernです。wが0の場合、ネットワークエラーは書き込みを失敗させますが、mongoエラーはそうではありません。これは通常「ファイアアンドフォーゲット」書き込みと呼ばれ、一貫性と耐久性よりもパフォーマンスが重要な場合に使用する必要があります。このモードではWriteConcern.NORMALを使用します。

    wを1以上に設定すると、書き込みは安全と見なされます。安全な書き込みは書き込みを実行し、サーバーへの要求によってそれをフォローアップして、書き込みが成功したことを確認するか、失敗した場合はエラー値を取得します(つまり、書き込み後にgetLastError()コマンドを送信します)。このgetLastError()コマンドが完了するまで、接続は予約されることに注意してください。これと追加のコマンドの結果として、スループットはw <= 0の書き込みよりも大幅に低くなります。w値が正確に1の場合、MongoDBは、書き込みを送信したインスタンスで書き込みが成功した(または検証可能に失敗した)ことを保証します。

    レプリカセットの場合、MongoDBに書き込みを送信する前に、レプリカセットの少なくとも "w"メンバーに書き込む前に、より高い値を使用できます(より正確には、 "w"メンバーへの書き込みのレプリケーションを待ちます) )。wを文字列 "majority"に設定して、MongoDBにレプリカセットメンバーの大部分(WriteConcern.MAJORITY)への書き込みを実行するように指示することもできます。通常、生のパフォーマンス(-1または0)または複製された書き込み(> 1)が必要でない限り、これを1に設定する必要があります。1より大きい値は、書き込みスループットに大きな影響を与えます。

  • fsync。有効にすると、書き込みごとにmongoを強制的にディスクにフラッシュする耐久性オプション。書き込みバックログに関連する耐久性の問題は一度もないので、本番環境ではこれをfalse(デフォルト)にしています。

  • j * (新規2.7以降) *。trueに設定されている場合、MongoDBが戻る前にジャーナルグループのコミットが成功するまで待機することをブール値。ジャーナリングを有効にしている場合は、これを有効にして耐久性を高めることができます。http://www.mongodb.org/display/DOCS/Journalingを参照して、どのジャーナリングで取得できるか(したがって、このフラグを有効にする理由)を確認してください

ReadPreference ReadPreferenceクラスを使用すると、レプリカセットを使用している場合に、クエリをルーティングするmongodインスタンスを設定できます。次のオプションを使用できます。

  • ReadPreference.primary():すべての読み取りは、repsetプライマリメンバーのみに送信されます。すべてのクエリで一貫性のある(最後に書き込まれた)データを返す必要がある場合は、これを使用します。これがデフォルトです。

  • ReadPreference.primaryPreferred():すべての読み取りは、可能な場合はrepsetプライマリメンバーに送信されますが、プライマリノードが利用できない場合はセカンダリメンバーにクエリを実行できます。そのため、プライマリが使用できなくなった場合、読み取りは最終的に整合性が取られますが、プライマリが使用できない場合のみです。

  • ReadPreference.secondary():すべての読み取りはセカンダリrepsetメンバーに送信され、プライマリメンバーは書き込みのみに使用されます。最終的に一貫した読み取りで対応できる場合にのみ、これを使用してください。追加のrepsetメンバーを使用して読み取りパフォーマンスをスケールアップできますが、repsetが持つことができる(投票)メンバーの数には制限があります。

  • ReadPreference.secondaryPreferred():読み取りが可能な場合、すべての読み取りはセカンダリrepsetメンバーに送られます。すべてのセカンダリメンバーが使用不可にならない限り、プライマリメンバーは書き込み専用に使用されます。読み取り用のプライマリメンバーへのフォールバック以外は、ReadPreference.secondary()と同じです。

  • ReadPreference.nearest():読み取りは、データベースクライアントが使用できる最も近いrepsetメンバーに送信されます。最終的に一貫した読み取りが許容される場合にのみ使用してください。最も近いメンバーは、クライアントとさまざまなrepsetメンバーの間のレイテンシが最も低いメンバーです。忙しいメンバーは最終的にレイテンシが高くなるため、これも読み取り負荷のバランスを自動的にとるはずですが、私の経験では、セカンダリ(優先)は、メンバーのレイテンシが比較的一貫している場合は、より良いようです。

注:上記のすべてに同じメソッドのタグ対応バージョンがあり、代わりにTaggableReadPreferenceインスタンスを返します。レプリカセットタグの詳細については、こちらをご覧ください。レプリカセットタグ


6
socketTimeoutとconnectTimeoutをデフォルト(無限)のままにしておくのは危険ではありませんか?なんらかの理由で接続がハングすると、アプリ(または少なくともそのスレッド)が永久に動かなくなります。これらを非常に高い値に設定するべきではありませんか(接続に30秒、ソケットに2分など)。
Idris Mokhtarzada 2011

イドリス、本当です。私の投稿では、誤ってMongoOptionsにデフォルトが設定されていると思いました。私たちのMongo ORMレイヤーには、それぞれ15秒と1分でこれらがあり、執筆中、私はこれらがデフォルトであると想定しました。無限のタイムアウトは間違いなく悪い考えです。頭を上げてくれてありがとう、私はポストでそれを修正しました
Remon van Vliet

「slaveOk」オプションは非推奨になりました。これと同等のものをtrueにしたい場合は、次のようにしてください。mongoOptions.readPreference = ReadPreference.secondaryPreferred();
Gubatron 2012年

良い答えですが、threadsAllowedToBlockForConnectionMultiplierの定義が間違っています(キーワード乗数)。ドキュメントによると、「connectionsPerHostが10で、threadsAllowedToBlockForConnectionMultiplierが5の場合にブロックできるスレッドの数に対するconnectionsPerHostの乗数は、50スレッドがそれ以上ブロックでき、例外がスローされます」
Tyler Zale

3
かなり人気のある答えのようです。最新のドライバーの変更を反映するためにこれを更新することに興味がある人がいたら、知らせてください
Remon van Vliet
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.