mongoError: Topology was destroyed

mongoError: Topology was destroyed

我在 node.js 中内置了一个 REST 服务,其中包含 Restify 和 Mongoose,还有一个 mongoDB 包含一个包含大约 30.000 个常规大小文档的集合。 我有我的节点服务 运行 通过 pmx 和 pm2.

昨天,突然之间,node 开始用消息 "MongoError: Topology was destroyed" 报错,仅此而已。 我不知道这是什么意思,也不知道是什么触发了它。 google-搜索此内容时也没有什么可找到的。所以我想我应该在这里问。

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

我正在使用上述软件包的以下版本:

这似乎意味着您的节点服务器与您的 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 问题无关,因为没有安装导致崩溃的升级或 "fix"

我知道 Jason 的回答被接受了,但我对 Mongoose 也有同样的问题,发现 the service hosting my database recommended to apply the following settings 为了在生产中保持 Mongodb 的连接:

var options = {
  server: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } },
  replset: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } }
};
mongoose.connect(secrets.db, options);

我希望这个回复可以帮助其他有 "Topology was destroyed" 错误的人。

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

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

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

详情在这里:[mongo doc for connection string]

此错误是由于 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 
        } 
    }
);

connection options documentation

只是对 Gaafar 回答的一个小补充,它给了我一个弃用警告。而不是在服务器对象上,像这样:

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

它可以在顶级对象上进行。基本上,只需将其从服务器对象中取出并放入选项对象中,如下所示:

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

我在 MongoDb Compass 社区上创建新数据库时遇到此错误。问题出在我的 Mongod 上,而不是 运行ning。因此,作为修复,我必须 运行 前面的 Mongod 命令。

C:\Program Files\MongoDB\Server.6\bin>mongod

我可以在 运行 执行该命令后创建数据库。

希望对您有所帮助。

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

  1. 确保 mongo 是 运行
  2. 正在重启我的服务器
根据 this comment

"Topology was destroyed" 可能是由于 mongo 在创建 mongo 文档索引之前断开连接造成的

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

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 中的数字是在 Whosebug 和类似网站上任意找到的)

在我的例子中,此错误是由 '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
});

就我而言,此错误是由已经 运行 背景的相同服务器实例引起的。

奇怪的是,当我启动我的服务器时没有注意到已经有一个 运行,控制台没有显示 'something is using port xxx' 之类的东西。我什至可以上传一些东西到服务器。所以,我花了很长时间才定位到这个问题。

而且,在关闭所有我能想到的应用程序后,我仍然无法在我的Mac的activity监视器中找到正在使用该端口的进程。我必须使用 lsof 来跟踪。罪魁祸首并不奇怪——它是一个节点进程。但是,通过终端显示的PID,我发现监视器中的端口号与我的服务器使用的端口号不同。

总而言之,杀掉所有node进程可能直接解决这个问题

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

我为此苦苦挣扎了一段时间 - 正如您从其他答案中看到的那样,问题可能非常不同。

找出原因的最简单方法是在选项

中打开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来解决拓扑错误,然后只需更改mongoose或mongoclient的一些选项即可解决此问题:

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

mongoose.connect(mongoDevString,mongoOptions);

这里使用 mongoose,但你可以在没有它的情况下进行类似的检查

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 APP。我使用 pm2 来处理这个 pm2 restart [your-app-id]。要获取 ID,请使用 pm2 list