我有一个使用Restify和Mongoose构建在node.js中的REST服务,以及一个带有大约30.000个常规文档的集合的mongoDB。 我的节点服务通过pmx和pm2运行。
昨天,突然,节点开始消除错误消息“MongoError:拓扑被破坏”,仅此而已。 我不知道这是什么意思,什么可能触发这个。谷歌搜索时也没有太多东西可以找到。所以我想我会在这里问。
今天重新启动节点服务后,错误停止了。 我也有其中一个在生产中运行,这让我感到害怕,这可能会在任何给定时间发生在运行那里的设置非常关键的部分...
我正在使用上述软件包的以下版本:
答案 0 :(得分:84)
这似乎意味着您的节点服务器与MongoDB实例的连接在尝试写入时已被中断。
查看Mongo source code that generates that error
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问题无关,因为没有安装升级来促成崩溃或“修复”
答案 1 :(得分:74)
我知道Jason的回答被接受了,但是我和Mongoose有同样的问题,为了让Mongodb的连接在生产中保持活跃,我发现the service hosting my database recommended to apply the following settings:
var options = {
server: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } },
replset: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } }
};
mongoose.connect(secrets.db, options);
我希望这个回复可以帮助其他人破坏"拓扑被破坏"错误。
答案 2 :(得分:60)
此错误是由于mongo驱动程序因任何原因丢弃了连接(例如服务器已关闭)。
默认情况下,mongoose将尝试重新连接30秒,然后停止重试并永远抛出错误,直到重新启动。
您可以通过编辑连接选项
中的这两个字段来更改此设置mongoose.connect(uri,
{ server: {
// sets how many times to try reconnecting
reconnectTries: Number.MAX_VALUE,
// sets the delay between every retry (milliseconds)
reconnectInterval: 1000
}
}
);
答案 3 :(得分:14)
就我而言,此错误是由“异步”内部“等待”部分中的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
});
答案 4 :(得分:9)
只是Gaafar答案的一小部分内容,它给了我一个弃用警告。而不是在服务器对象上,如下所示:
MongoClient.connect(MONGO_URL, {
server: {
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 1000
}
});
它可以进入顶级对象。基本上,只需将其从服务器对象中取出并将其放在options对象中,如下所示:
MongoClient.connect(MONGO_URL, {
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 1000
});
答案 5 :(得分:4)
为了确保在断开连接之前已建立所有模型的索引,您可以:
await Promise.all(mongoose.modelNames().map(model => mongoose.model(model).ensureIndexes()));
await mongoose.disconnect();
答案 6 :(得分:2)
我在kubernetes / minikube + nodejs +猫鼬环境中遇到了这个问题。 问题在于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和类似的类似站点上是任意的)
答案 7 :(得分:2)
我也有同样的错误。最后,我发现我的代码有一些错误。我为两个nodejs服务器使用负载平衡,但我只是更新一个服务器的代码。
我更改了我的mongod服务器from standalone to replication
,但我忘记对连接字符串进行相应的更新,所以我遇到了这个错误。
独立连接字符串:
mongodb://server-1:27017/mydb
复制连接字符串:
mongodb://server-1:27017,server-2:27017,server-3:27017/mydb?replicaSet=myReplSet
答案 8 :(得分:1)
我在MongoDb指南针社区创建新数据库时遇到此错误。问题出在我的Mongod上,它没有运行。所以作为修复,我必须像前面那样运行Mongod命令。
C:\Program Files\MongoDB\Server\3.6\bin>mongod
我能够在运行该命令后创建数据库。
希望它有所帮助。
答案 9 :(得分:1)
这就是我所做的,效果很好。添加以下选项后,问题消失了。
portrait
答案 10 :(得分:0)
就我而言,此错误是由已经在后台运行的相同服务器实例引起的。
奇怪的是,当我启动服务器而没有通知已经有一个正在运行时,控制台未显示“正在使用端口xxx”之类的信息。我什至可以将某些内容上传到服务器。因此,花了很长时间才找到这个问题。
此外,在关闭所有我可以想象的应用程序之后,我仍然无法在Mac的活动监视器中找到正在使用此端口的进程。我必须使用lsof
进行跟踪。罪魁祸首并不奇怪-这是一个节点过程。但是,使用终端上显示的PID,我发现监视器中的端口号与服务器使用的端口号不同。
总而言之,杀死所有节点进程可以直接解决此问题。
答案 11 :(得分:0)
塞巴斯蒂安(Sebastian)对阿德里安(Adrien)的回答的评论需要更多关注,这对我有帮助,但作为评论有时可能会被忽略所以这是一个解决方案:
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);
}
});
答案 12 :(得分:0)
我为此苦了一段时间-从其他答案中可以看出,问题可能大不相同。
找出原因的最简单方法是打开选项中的loggingLevel: info
答案 13 :(得分:0)
您需要重新启动mongo以解决拓扑错误,然后只需更改mongoose或mongoclient的某些选项即可解决此问题:
var mongoOptions = {
useMongoClient: true,
keepAlive: 1,
connectTimeoutMS: 30000,
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 5000,
useNewUrlParser: true
}
mongoose.connect(mongoDevString,mongoOptions);
答案 14 :(得分:0)
在这里使用猫鼬,但如果没有它,您也可以进行类似的检查
export async function clearDatabase() {
if (mongoose.connection.readyState === mongoose.connection.states.disconnected) {
return Promise.resolve()
}
return mongoose.connection.db.dropDatabase()
}
我的用例只是测试抛出错误,因此,如果我们断开连接,则不会运行任何操作。
答案 15 :(得分:0)
我最近遇到这个问题。这是我的工作:
<!-- Include Quill stylesheet -->
<link href="https://cdn.quilljs.com/1.0.0/quill.snow.css" rel="stylesheet">
<style>
#editor-container {
height: 375px;
}
</style>
<!-- Create the editor container -->
<div id="editor-container" >
</div>
<!-- Include the Quill library -->
<script src="https://cdn.quilljs.com/1.0.0/quill.js"></script>
<!-- Initialize Quill editor -->
<script>
var toolbarOptions = [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
[{ 'header': 1 }, { 'header': 2 }], // custom button values
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
[{ 'script': 'sub'}, { 'script': 'super' }], // superscript/subscript
[{ 'indent': '-1'}, { 'indent': '+1' }], // outdent/indent
[{ 'direction': 'rtl' }], // text direction
[{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme
[{ 'font': [] }],
[{ 'align': [] }],
['clean'] // remove formatting button
];
var quill = new Quill('#editor-container', {
modules: {
toolbar: toolbarOptions
},
placeholder: 'Compose an epic...',
theme: 'snow' // or 'bubble'
});
</script>
sudo service mongod restart
。要获取ID,请使用pm2 restart [your-app-id]
答案 16 :(得分:-2)
我通过以下方式解决了这个问题:
答案 17 :(得分:-3)
您需要转到&#34; 连接&#34;菜单并点击&#34; 连接到... &#34;子菜单。这将打开一个新的 MongoDB Compass社区窗口,您可以通过该窗口再次连接。