RestifyとMongooseを使ってnode.jsに組み込まれたRESTサービスと、約30,000の通常サイズのドキュメントを含むmongoDBを持っています。ノードサービスをpmxとpm2で実行しています。
昨日、突然、ノードは "MongoError:Topology is destroyed"というメッセージでエラーを作成し始めました。これが何を意味しているのか、そして何がこれを引き起こす可能性があるのかわかりません。これをグーグル検索するときに見つけることも多くありません。それで、私は私がここに尋ねたいと思った。
今日ノードサービスを再起動した後、エラーが発生するのをやめました。私はこれらのうちの1つを実稼働中で実行しています。
私は以下のバージョンのパッケージを使用しています。
MongoDBインスタンスへの書き込み中に、ノードサーバーからMongoDBインスタンスへの接続が中断されたことを意味しているようです。
そのエラーを生成する Mongoのソースコードを見てください
Mongos.prototype.insert = function(ns, ops, options, callback) {
if(typeof options == 'function') callback = options, options = {};
if(this.s.state == DESTROYED) return callback(new MongoError(f('topology was destroyed')));
// Topology is not connected, save the call in the provided store to be
// Executed at some point when the handler deems it's reconnected
if(!this.isConnected() && this.s.disconnectHandler != null) {
callback = bindToCurrentDomain(callback);
return this.s.disconnectHandler.add('insert', ns, ops, options, callback);
}
executeWriteOperation(this.s, 'insert', ns, ops, options, callback);
}
クラッシュや「修正」を早めるためのアップグレードがインストールされていないため、これはコメントで引用されているSailsの問題とは関係がないようです。
私はJasonの答えが受け入れられたことを知っていますが、私はMongooseと同じ問題を抱えていて、Mongodbの接続を本番環境で生き続けるために データベースをホストするサービスは以下の設定を適用することを推奨しました を見つけました。
var options = {
server: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } },
replset: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } }
};
mongoose.connect(secrets.db, options);
この回答が、「トポロジが破壊されました」というエラーを持つ他の人に役立つことを願っています。
このエラーは、何らかの理由でmongoドライバが接続を切断したことが原因です(たとえば、サーバーがダウンした)。
デフォルトでは、mongooseは30秒間再接続を試み、それから再試行を停止し、再起動するまでエラーを永遠にスローします。
接続オプションでこれら2つのフィールドを編集してこれを変更できます。
mongoose.connect(uri,
{ server: {
// sets how many times to try reconnecting
reconnectTries: Number.MAX_VALUE,
// sets the delay between every retry (milliseconds)
reconnectInterval: 1000
}
}
);
私の場合、このエラーは 'async'内の 'await'セクションからのdb.close();
によるものです。
MongoClient.connect(url, {poolSize: 10, reconnectTries: Number.MAX_VALUE, reconnectInterval: 1000}, function(err, db) {
// Validate the connection to Mongo
assert.equal(null, err);
// Query the SQL table
querySQL()
.then(function (result) {
console.log('Print results SQL');
console.log(result);
if(result.length > 0){
processArray(db, result)
.then(function (result) {
console.log('Res');
console.log(result);
})
.catch(function (err) {
console.log('Err');
console.log(err);
})
} else {
console.log('Nothing to show in MySQL');
}
})
.catch(function (err) {
console.log(err);
});
db.close(); // <--------------------------------THIS LINE
});
Gaafarの答えにちょっと追加しただけで、それは私に非推奨警告を与えました。次のように、サーバーオブジェクト上ではなく
MongoClient.connect(MONGO_URL, {
server: {
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 1000
}
});
それはトップレベルのオブジェクトに行くことができます。基本的には、サーバーオブジェクトから取り出して、次のようにoptionsオブジェクトに入れます。
MongoClient.connect(MONGO_URL, {
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 1000
});
「トポロジが破壊された」のは、mongoドキュメントインデックスが作成される前にmongooseが切断されたことが原因である可能性があります このコメント
切断する前にすべてのモデルのインデックスが確実に構築されていることを確認するために、次のことができます。
await Promise.all(mongoose.modelNames().map(model => mongoose.model(model).ensureIndexes()));
await mongoose.disconnect();
私はkubernetes/minikube + nodejs + mongoose環境でこれに出会いました。問題は、DNSサービスがある種の待ち時間で起動していたことです。 DNSをチェックすれば問題は解決します。
const dns = require('dns');
var dnsTimer = setInterval(() => {
dns.lookup('mongo-0.mongo', (err, address, family) => {
if (err) {
console.log('DNS LOOKUP ERR', err.code ? err.code : err);
} else {
console.log('DNS LOOKUP: %j family: IPv%s', address, family);
clearTimeout(dnsTimer);
mongoose.connect(mongoURL, db_options);
}
});
}, 3000);
var db = mongoose.connection;
var db_options = {
autoReconnect:true,
poolSize: 20,
socketTimeoutMS: 480000,
keepAlive: 300000,
keepAliveInitialDelay : 300000,
connectTimeoutMS: 30000,
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 1000,
useNewUrlParser: true
};
(db_options内の数字は、stackoverflowや類似のサイトで任意に見つかります)
私はまた同じエラーがありました。最後に、私は自分のコードにエラーがあることに気付きました。私は2つのnodejsサーバーに負荷分散を使用しますが、1つのサーバーのコードを更新するだけです。
Mongodサーバーのfrom standalone to replication
を変更しましたが、接続文字列に対応する更新をするのを忘れたので、このエラーに遭遇しました。
スタンドアロン接続文字列:mongodb://server-1:27017/mydb
レプリケーション接続文字列:mongodb://server-1:27017,server-2:27017,server-3:27017/mydb?replicaSet=myReplSet
詳細はこちら: [接続文字列のmongoドキュメント]
MongoDb Compass Communityで新しいデータベースを作成しているときに、このエラーが発生しました。問題は私のMongodにありました、それは走っていませんでした。だから修正として、私は前述のようにMongodコマンドを実行する必要がありました。
C:\Program Files\MongoDB\Server\3.6\bin>mongod
そのコマンドを実行した後、私はデータベースを作成することができました。
それが役に立てば幸い。
Adrienの回答に対するSebastianのコメントにはもっと注意が必要ですが、コメントであることはいつか無視される可能性があるため、解決策があります:
var options = { useMongoClient: true, keepAlive: 1, connectTimeoutMS: 30000, reconnectTries: 30, reconnectInterval: 5000 }
mongoose.connect(config.mongoConnectionString, options, (err) => {
if(err) {
console.error("Error while connecting", err);
}
});
私の場合、このエラーは、同一のサーバーインスタンスがすでにバックグラウンドで実行されていることが原因でした。
奇妙なことに、サーバが起動せずにサーバを起動したとき、すでに実行されているものがある場合、コンソールには「何かがポートxxxを使用しています」のように表示されませんでした。私は何かをサーバーにアップロードすることさえできました。それで、この問題を見つけるのに私はかなり時間がかかりました。
さらに、私が想像できるすべてのアプリケーションを閉じた後でも、私はこのポートを使用しているプロセスを私のMacのアクティビティモニタで見つけることができませんでした。トレースするにはlsof
を使わなければなりません。犯人は驚くべきことではなかった - それはノードプロセスです。しかし、端末に表示されているPIDで、モニターのポート番号が私のサーバーで使用されているものと異なることがわかりました。
結局のところ、すべてのノードプロセスを強制終了すると、この問題を直接解決できる可能性があります。
トポロジエラーを解決するには、mongoを再起動してから、mongooseまたはmongoclientの一部のオプションを変更して、この問題を解決する必要があります。
var mongoOptions = {
useMongoClient: true,
keepAlive: 1,
connectTimeoutMS: 30000,
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 5000,
useNewUrlParser: true
}
mongoose.connect(mongoDevString,mongoOptions);
私はしばらくこれに苦労していました - あなたが他の答えからわかることができるように、問題は非常に異なる場合があります。
原因を突き止める最も簡単な方法は、オプションでloggingLevel: info
をオンにすることです。
ここで私がやったこと、それはうまくいきます。以下のオプションを追加すると問題はなくなりました。
const dbUrl = "mongodb://localhost:27017/sampledb";
const options = { useMongoClient: true, keepAlive: 1, connectTimeoutMS: 30000, reconnectTries: 30, reconnectInterval: 5000, useNewUrlParser: true }
mongoose.connect(dbUrl,options, function(
error
) {
if (error) {
console.log("mongoerror", error);
} else {
console.log("connected");
}
});