错误: 拓扑被破坏

我有一个包含 Restify 和 Mongoose 的 node.js 内置的 REST 服务,以及一个包含约30.000个常规大小文档的 mongoDB 集合。 我的节点服务在 pmx 和 pm2之间运行。

昨天,节点突然开始排除错误消息“ MongoError: 拓扑已被破坏”,仅此而已。 我不知道这是什么意思也不知道是什么触发了这一切。在谷歌上搜索这个也没有什么发现。所以我想在这里问问。

今天重新启动节点服务后,错误就不再出现了。 我也有一个这样的运行在生产中,它让我害怕,这可能会发生在任何给定的时间,一个相当关键的部分设置运行在那里..。

我使用以下版本的软件包:

  • 猫鼬: 4.0
  • 重新调整: 3.0.3
  • 节点: 0.10.25
164564 次浏览

这似乎意味着您的节点服务器与 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);

我希望这个回答可以帮助其他人有“拓扑被摧毁”的错误。

我也犯了同样的错误。最后,我发现我的代码有一些错误。我对两个 nodejs 服务器使用负载均衡,但只更新了一个服务器的代码。

我更改了蒙古服务器 from standalone to replication,但是我忘记对连接字符串进行相应的更新,所以我遇到了这个错误。

独立连接字符串: Mongodb://server-1:27017/mydb 复制连接字符串: Mongodb://server-1:27017,server-2:27017,server-3:27017/mydb? plicaSet = myReplSet

详情请浏览这里: [连接字符串的 mongo doc ]

此错误是由于 mongo 驱动程序由于任何原因(例如服务器关闭)而中断连接造成的。

默认情况下,猫鼬会尝试重新连接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
}
}
);

连接选项文档

这只是加法尔回答的一个小小的补充,它给了我一个反对警告。而不是在服务器对象上,如下所示:

MongoClient.connect(MONGO_URL, {
server: {
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 1000
}
});

它可以放在顶层物体上。基本上,只要把它从服务器对象中取出来,放到 options 对象中,如下所示:

MongoClient.connect(MONGO_URL, {
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 1000
});

当我在 MongoDb Compass 社区上创建一个新数据库时,出现了这个错误。问题是我的蒙神,它没有运行。因此,作为一个修复,我必须像前面那样运行 MonGod 命令。

C:\Program Files\MongoDB\Server\3.6\bin>mongod

在运行了这个命令之后,我创建了一个数据库。

希望能有帮助。

我通过以下方式解决了这个问题:

  1. 确保蒙戈跑起来
  2. 重启我的服务器

根据 此评论,在创建 mongo 文档索引之前,“拓扑被破坏”可能是由于猫鼬断开连接造成的

为了确保所有模型在断开连接之前都建立了索引,您可以:

await Promise.all(mongoose.modelNames().map(model => mongoose.model(model).ensureIndexes()));


await mongoose.disconnect();

我是在 kubernette/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 和类似的站点上任意找到)

在我的例子中,这个错误是由于“异步”中“等待”部分的 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
});

在我的示例中,此错误是由已经运行后台的相同服务器实例引起的。

奇怪的是,当我在没有通知的情况下启动服务器时,已经有一个正在运行,控制台没有显示任何类似“ something is using port xxx”的内容。我甚至可以上传一些东西到服务器。我花了很长时间才找到这个问题。

而且,在关闭了所有我能想到的应用程序之后,我仍然找不到在我 Mac 的活动监视器中使用这个端口的进程。我必须用 lsof来追踪。罪魁祸首并不令人惊讶——它是一个节点进程。但是,通过终端中显示的 PID,我发现监视器中的端口号与服务器使用的端口号不同。

总之,杀死所有节点进程可以直接解决这个问题。

塞巴斯蒂安对阿德里安的回答的评论需要更多的关注,它帮助了我,但它是一个评论可能会被忽略的某个时候 所以我有个办法:

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);
}
});

我在这个问题上挣扎了一段时间——正如你从其他答案中看到的,这个问题可以是非常不同的。

找出原因的最简单的方法是在选项中打开 loggerLevel: '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");
}


});

您需要重新启动 mongo 来解决拓扑错误,然后只需更改猫鼬或 mongoclient 的一些选项来解决这个问题:

var mongoOptions = {
useMongoClient: true,
keepAlive: 1,
connectTimeoutMS: 30000,
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 5000,
useNewUrlParser: true
}


mongoose.connect(mongoDevString,mongoOptions);

在这里使用猫鼬,但你可以做一个类似的检查没有它

export async function clearDatabase() {
if (mongoose.connection.readyState === mongoose.connection.states.disconnected) {
return Promise.resolve()
}
return mongoose.connection.db.dropDatabase()
}

我的用例只是测试抛出错误,所以如果我们断开连接,我就不运行操作。

我最近遇到了这个问题,我是这么做的:

  1. 重新启动 MongoDb: sudo service mongod restart
  2. 重新启动我的 NodeJS 应用程序。我使用 pm2来处理这个 pm2 restart [your-app-id]。使用 pm2 list来获得 ID

Var mongoOptions = { UseNewUrlParser: true, UseUnifiedTopology: true, }

Connect (mongoDevString,mongoOptions) ;