web-dev-qa-db-ja.com

mongoDBには再接続の問題がありますか、それとも間違っていますか?

NodejsとmongoDBを使用していますが、接続に問題があります。

さて、実際には「ウェイク」問題!それは完全にうまく接続します-超高速であり、私は一般的に結果に満足しています。

私の問題:接続をしばらく使用しないと(時間枠が5分以上変化するため、しばらくの間)、停止しているようです。切断イベントは発生しません-ハングするだけです。

最終的に私はエラーのような応答を受け取ります:[* .mongolab.comへの接続に失敗しました:*]* =マスクされた値)

アプリをすばやく再起動すると、接続が再び良好になります。場合によっては、アプリを再起動しないと、更新して問題なく再接続できます。

これが、「ウェイク」問題だと思う理由です。

---(コードの大まかな概要:

私はコードを含めていません-私はそれが必要だとは思いません。動作します(接続ドロップアウトは除く)

注意事項:「接続」は1つだけです-決して閉じません。再開しません。

私はマングース、socketioを使用しています。

/* constants */

var mongoConnect = 'myworkingconnectionstring-includingDBname';


/* includes */

/* settings */

/* Schema */

var db = mongoose.connect(mongoConnect);

    /* Socketio */

io.configure(function (){
    io.set('authorization', function (handshakeData, callback) {

    });
});

io.sockets.on('connection', function (socket) {

});//sockets

io.sockets.on('disconnect', function(socket) {
    console.log('socket disconnection')
});

/* The Routing */

app.post('/login', function(req, res){  

});

app.get('/invited', function(req, res){

});

app.get('/', function(req, res){

});

app.get('/logout', function(req, res){

});

app.get('/error', function(req, res){

});

server.listen(port);
console.log('Listening on port '+port);

db.connection.on('error', function(err) {
    console.log("DB connection Error: "+err);
});
db.connection.on('open', function() {
    console.log("DB connected");
});
db.connection.on('close', function(str) {
    console.log("DB disconnected: "+str);
});

私はここでさまざまな構成を試しました。たとえば、常に開いたり閉じたりすることですが、一般的なコンセンサスは、1つのオープンをたくさんラップして行うことです。 ??

私は接続テスターを試してみましたが、接続のステータスをチェックし続けます...これは何も問題がないように見えますが、問題はまだ発生しています。

この問題は初日から発生しています。私は常にMongoLabでMongoDBをホストしてきました。この問題は、localhostでは悪化しているようです。しかし、私はまだAzureに問題があり、現在はnodejit.suです。

それはどこでも起こります-それは私、MongoDB、またはmongolabでなければなりません。

ちなみに、私もphpドライバーで同様の経験をしました。 (これがnodejsにあることを確認するため)

助けになると助かります-誰かが「これは普通だ」と言っても

前もって感謝します

ロブ

27
rob_james

助けてくれてありがとう-ローカルホストとライブサーバーの両方でこの問題を解決することができました。

これが私の現在機能している接続コードです:

var MONGO = {
    username: "username",
    password: "pa55W0rd!",
    server: '******.mongolab.com',
    port: '*****',
    db: 'dbname',
    connectionString: function(){
        return 'mongodb://'+this.username+':'+this.password+'@'+this.server+':'+this.port+'/'+this.db;
    },
    options: {
        server:{
            auto_reconnect: true,
            socketOptions:{
                connectTimeoutMS:3600000,
                keepAlive:3600000,
                socketTimeoutMS:3600000
            }
        }
    }
};

var db = mongoose.createConnection(MONGO.connectionString(), MONGO.options);

db.on('error', function(err) {
    console.log("DB connection Error: "+err);
});
db.on('open', function() {
    console.log("DB connected");
});
db.on('close', function(str) {
    console.log("DB disconnected: "+str);
});

最大の変更は、「connect」ではなく「createConnection」を使用することだったと思います。以前はこれを使用していましたが、おそらくオプションが役立つでしょう。この記事は大いに役立ちました http://journal.michaelahlers.org/2012/12/building-with-nodejs-persistence.html

正直なところ、なぜこれらのオプションを追加したのかはっきりしていません-@jareedが述べたように、「MaxConnectionIdleTime」で成功している人もいます-しかし、私が見る限り、javascriptドライバーはそうではありませんこのオプションがあります。これは、動作を再現しようとする私の試みでした。

これまでのところ、これが誰かを助けることを願っています。

更新:2013年4月18日注、これは設定が異なる2番目のアプリです

今、私はこれを解決したと思ったが、問題は再び立ち上がった最近別のアプリ-同じ接続コードで再び醜い頭になっている。混乱しました!!!

しかし、セットアップは少し異なりました…

この新しいアプリは、IISNodeを使用してWindowsボックスで実行されていました。最初はこれが重要であるとは思いませんでした。

Azure(@jareed)のmongoで問題が発生した可能性があるため、DBをAWSに移動しましたが、問題は解決しませんでした。

それで私はそのオプションオブジェクトで再び遊んで、かなりそれを読みました。この結論に達しました:

options: {
    server:{
        auto_reconnect: true,
        poolSize: 10,
        socketOptions:{
            keepAlive: 1
        }
    },
    db: {
        numberOfRetries: 10,
        retryMiliSeconds: 1000
    }
}

それは私の元のオプションオブジェクトが私が述べるよりも少し教育されていました。しかし、それはまだ良くありません。

さて、何らかの理由で、私はそのWindowsボックス(モジュールがコンパイルされていないことと関係がある)を外さなければなりませんでした-動作させるためにもう1週間費やすよりも移動の方が簡単でした。

そこで、アプリをnodejitsuに移動しました。 低く、私の接続が生き続けているのを見よ!ウー!

そう…。これはどういう意味ですか…わかりません。私が知っているのは、これらのオプションがNodejitsuで動作するように見えることです..。私のために。

IISNodeは、アプリを存続させるために、ある種の「永久に」のスクリプトを使用していると思います。これで公平に言えば、アプリがクラッシュしないため、アプリはクラッシュしませんが、絶えず更新される「アプリサイクル」のようなものがあるに違いないと思います。これにより、継続的な展開を行うことができます(ftpコードアップ、必要なし)アプリを再起動します)-多分これは要因です;しかし、私は今推測しています。

もちろん、これは今すべてを意味します、これは解決されていませんか?それはまだ解決されていません。それは私のセットアップで私のために解決されています。

18
rob_james

[〜#〜] update [〜#〜]:このトピックのサポート記事(基本的にはこの投稿のコピー)が 接続トラブルシューティングdoc

Azure IaaSネットワークが約13分のアイドルタイムアウトを強制するという既知の問題があります(経験的に到達した)。私たちはAzureと協力して、よりユーザーフレンドリーなものにできないかどうかを確認していますが、それまでの間、問題を回避するためのドライバーオプションを構成することで成功した人もいます。

最大接続アイドル時間

Azureとお客様との連携で見つかった最も効果的な回避策は、最大接続アイドル時間を4分未満に設定することです。ファイアウォールが問題を強制する前に、ドライバーにアイドル接続をリサイクルさせるという考え方です。たとえば、C#ドライバーを使用している1人の顧客がMongoDefaults.MaxConnectionIdleTimeを1分にすると、問題が解決しました。

MongoDefaults.MaxConnectionIdleTime = TimeSpan.FromMinutes(1);

アプリケーションコード自体は変更されませんでしたが、ドライバーは舞台裏でアイドル接続を積極的にリサイクルします。結果はサーバーログでも確認できます。アプリのアイドル期間中に多数の接続がチャーンします。

このアプローチの詳細については、関連するmongo-userスレッドの AzureのC#ドライバーを使用した[////] SocketException を参照してください。

キープアライブ

また、ある種の keepalive を使用して接続をアイドル状態にしないことで、問題を回避することもできます。通常、 TCPキープアライブ を利用して、ドライバがそのままでサポートしない限り、これは実装が少し難しいです。独自にロールする必要がある場合は、数分ごとにプールからアイドル状態の各接続を取得し、おそらく ping のような簡単で安価なコマンドを発行してください。

切断の処理

積極的なファイアウォールの設定がなくても、切断が発生することがあります。本番環境に入る前に、それらを正しく処理する必要があります。

まず、必ず自動再接続を有効にしてください。その方法はドライバーによって異なりますが、接続が不良であったためにドライバーが操作の失敗を検出した場合、自動再接続をオンにすると、ドライバーに再接続を試行するように指示されます。

しかし、これで問題が完全に解決するわけではありません。再接続をトリガーした失敗した操作をどうするかという問題がまだ残っています。自動再接続は、失敗した操作を自動的に再試行しません。これは、特に書き込みの場合は危険です。そのため、通常は例外がスローされ、アプリはそれを処理するように求められます。多くの場合、読み取りの再試行は簡単です。ただし、書き込みの再試行は慎重に検討する必要があります。

以下のmongo Shellセッションはこの問題を示しています。 mongoシェルはデフォルトで自動再接続が有効になっています。 stuffという名前のコレクションにドキュメントを挿入し、そのコレクション内のすべてのドキュメントを検索します。次に、タイマーを30分に設定し、同じ検索を再試行しました。失敗しましたが、シェルは自動的に再接続しました。すぐに検索を再試行したところ、期待どおりに機能しました。

% mongo ds012345.mongolab.com:12345/mydatabase -u *** -p *** 
MongoDB Shell version: 2.2.2 
connecting to: ds012345.mongolab.com:12345/mydatabase 
> db.stuff.insert({}) 
> db.stuff.find() 
{ "_id" : ObjectId("50f9b77c27b2e67041fd2245") } 
> db.stuff.find() 
Fri Jan 18 13:29:28 Socket recv() errno:60 Operation timed out 192.168.1.111:12345 
Fri Jan 18 13:29:28 SocketException: remote: 192.168.1.111:12345 error: 9001 socket exception [1] server [192.168.1.111:12345] 
Fri Jan 18 13:29:28 DBClientCursor::init call() failed 
Fri Jan 18 13:29:28 query failed : mydatabase.stuff {} to: ds012345.mongolab.com:12345 
Error: error doing query: failed 
Fri Jan 18 13:29:28 trying reconnect to ds012345.mongolab.com:12345 
Fri Jan 18 13:29:28 reconnect ds012345.mongolab.com:12345 ok 
> db.stuff.find() 
{ "_id" : ObjectId("50f9b77c27b2e67041fd2245") }

私たちはあなたを助けるためにここにいます

もちろん、ご不明な点がございましたら、support @ mongolab.comまでお気軽にお問い合わせください。私たちがお手伝いします。

28
jared

まだこの問題が発生している人のためのいくつかの推奨事項:

  1. Node.jsに最新のmongodbクライアントを使用していることを確認してください。 v1.2.xからv1.3.10(今日の最新)に移行すると、この領域に大幅な改善が見られました

  2. オプションオブジェクトをMongoClient.connectに渡すことができます。 AzureからMongoLabに接続するときに、次のオプションが機能しました。

    オプション= {db:{}、サーバー:{auto_reconnect:true、socketOptions:{keepAlive:1}}、replSet:{}、mongos:{}};

    MongoClient.connect(dbUrl、options、function(err、dbConn){//コード});

  3. より信頼できると思われる「閉じる」イベントを処理する方法を説明するこの他の回答を参照してください。 https://stackoverflow.com/a/20690008/446681

6
Hector Correa

auto_reconnectServer このようなオプション:

var db = mongoose.connect(mongoConnect, {server: {auto_reconnect: true}});

ここで開いている接続は実際には5つの接続のプール(デフォルト)であるため、接続して開いたままにしておくのが適切です。私の推測では、mongolabとの接続が断続的に失われ、それが発生すると接続が切断されます。うまくいけば、auto_reconnectはそれを解決します。

1
JohnnyHK

タイムアウトを増やすと役立つ場合があります。

  • "socketTimeoutMS":ソケットでの送信または受信がタイムアウトになるまでにかかる時間。
  • "wTimeoutMS":書き込みに関する問題が解決されるまでサーバーが待機するミリ秒数を制御します。
  • "connectTimeoutMS":タイムアウトまでに接続が開かれるまでにかかる時間(ミリ秒単位)。

    $ m = new MongoClient( "mongodb://127.0.0.1:27017"、array( "connect" => TRUE、 "connectTimeoutMS" => 10、 "socketTimeoutMS" => 10、 "wTimeoutMS" => 10));

        $db= $m->mydb;
        $coll = $db->testData;
        $coll->insert($paramArr);
    
1
djebel

同様の問題が MongoDBから定期的に切断されました でした。 2つのことを行うことで修正されました。

  1. コンピューターがスリープ状態にならないようにしてください(ネットワーク接続が切断されます)。
  2. ルーター/ファイアウォールをバイパスします(または、適切に構成しますが、まだ方法がわかりません)。
0
Mike M. Lin