Node.js mongoError:拓扑已被破坏

Node.js mongoError:拓扑已被破坏,node.js,mongodb,mongoose,restify,pm2,Node.js,Mongodb,Mongoose,Restify,Pm2,我有一个内置于node.js中的REST服务,其中包含Restify和Mongoose,还有一个mongoDB,其中包含大约30000个常规大小的文档。 我的节点服务通过pmx和pm2运行 昨天,突然,节点开始抛出错误消息“MongoError:Topology was destroyed”,仅此而已。 我不知道这是什么意思,也不知道是什么触发了这一切。当谷歌搜索这个网站的时候,也没有什么可以找到的。所以我想在这里问一下 今天重新启动节点服务后,错误不再出现。 我也有一个在生产中运行,它让我害怕

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

昨天,突然,节点开始抛出错误消息“MongoError:Topology was destroyed”,仅此而已。 我不知道这是什么意思,也不知道是什么触发了这一切。当谷歌搜索这个网站的时候,也没有什么可以找到的。所以我想在这里问一下

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

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

  • 猫鼬:4.0.3
  • restify:3.0.3
  • 节点:0.10.25

这似乎意味着节点服务器与MongoDB实例的连接在尝试写入时被中断

看一看


这似乎与评论中引用的Sails问题无关,因为没有安装任何升级来加速崩溃或“修复”

我知道Jason的回答被接受,但我对Mongoose也有同样的问题,并发现为了在生产中保持Mongodb的连接:

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

我希望这个回复可以帮助其他有“拓扑被破坏”错误的人。

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

我将mongod服务器
从单机版更改为复制版
,但我忘记了对连接字符串进行相应的更新,因此遇到了此错误

独立连接字符串:

mongodb://server-1:27017/mydb
复制连接字符串:

mongodb://server-1:27017,server-2:27017,server-3:27017/mydb?replicset=myReplSet


此处的详细信息:

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

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

MongoClient.connect(MONGO_URL, {
    server: {
        reconnectTries: Number.MAX_VALUE,
        reconnectInterval: 1000
    }
});
MongoClient.connect(MONGO_URL, {
    reconnectTries: Number.MAX_VALUE,
    reconnectInterval: 1000
});
它可以放在顶层对象上。基本上,只需将其从服务器对象中取出并放入选项对象中,如下所示:

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

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

C:\Program Files\MongoDB\Server\3.6\bin>mongod
运行该命令后,我能够创建一个数据库


希望有帮助。

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

  • 确保mongo正在运行
  • 重新启动我的服务器
  • 根据,在创建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');
    变量Dnsimer=setInterval(()=>{
    dns.lookup('mongo-0.mongo',(错误、地址、族)=>{
    如果(错误){
    console.log('DNS LOOKUP ERR',ERR.code?ERR.code:ERR);
    }否则{
    console.log('DNS查找:%j系列:IPv%s',地址,系列);
    清除超时(dnsTimer);
    mongoose.connect(mongoURL、db_选项);
    }
    });
    }, 3000);
    var db=猫鼬连接;
    var db_选项={
    自动重新连接:正确,
    游泳池规模:20,
    socketTimeoutMS:480000,
    keepAlive:300000,
    保持初始延迟:300000,
    连接超时:30000,
    重新连接:Number.MAX_值,
    重新连接区间:1000,
    useNewUrlParser:true
    
    };在我的例子中,这个错误是由
    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
    });
    
    MongoClient.connect(url,{poolSize:10,reconnectTries:Number.MAX_值,reconnectInterval:1000},函数(err,db){
    //验证与Mongo的连接
    assert.equal(null,err);
    //查询SQL表
    querySQL()
    .然后(函数(结果){
    log('Print results SQL');
    控制台日志(结果);
    如果(result.length>0){
    processArray(数据库,结果)
    .然后(函数(结果){
    console.log('Res');
    控制台日志(结果);
    })
    .catch(函数(err){
    console.log('Err');
    控制台日志(err);
    })
    }否则{
    log('在MySQL中没有显示');
    }
    })
    .catch(函数(err){
    控制台日志(err);
    });
    
    db.close();//在我的例子中,此错误是由已经在后台运行的相同服务器实例引起的

    奇怪的是,当我启动我的服务器时,没有注意到已经有一个正在运行,控制台没有显示类似“某物正在使用端口xxx”。我甚至可以将某物上传到服务器。因此,我花了很长时间才找到这个问题

    更重要的是,在关闭了我能想象到的所有应用程序后,我仍然无法在Mac的活动监视器中找到使用此端口的进程。我必须使用
    lsof
    进行跟踪。罪魁祸首并不奇怪,这是一个节点进程。但是,由于终端中显示的PID,我发现监视器中的端口号不同从我的服务器使用的那个


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

    Sebastian对Adrien答案的评论需要更多的关注,这对我很有帮助,但作为一个评论,有时可能会被忽略,所以这里有一个解决方案
    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");
      }
    
    });
    
    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()
    }