我目前正在测试一些代码如何对抗以下场景:

  • node .js应用程序启动并成功建立到mongodb的连接
  • 成功建立连接后,mongodb服务器死亡,所有后续请求失败

为了做到这一点,我得到了以下使用官方驱动程序的代码(在这里找到:https://github.com/mongodb/node-mongodb-native):

MongoClient.connect('mongodb://localhost:27017/testdb', function(err, db) {
app.get('/test', function(req, res) {
    db.collection('users', function (err, collection) {
        console.log(err);
        if (err) {
            // ## POINT 1 ##
            // Handle the error
        }
        else {
            collection.find({ 'username': username }, { timeout: true }).toArray(function(err, items) {
                console.log(err);
                if (err) {
                    // ## POINT 2 ##
                    // Handle the error
                }
                else {
                    if (items.length > 0) {
                        // Do some stuff with the document that was found
                    }
                    else {
                        // Handle not finding the document
                    }
                }
            }); 
        }
    });
});

});

由于mongodb服务器在处理请求时不再运行,我假设在我标记为##点1#或##点2#的点上,它将返回一个指示超时的错误;然而,事实并非如此.

我try 了许多不同的设置(包括你可以在这里看到的明确允许光标超时的设置),但是我似乎无法以任何方式启用它.在我try 过的每种配置中.js只会一直等待find()操作回调,但它永远不会这样做.

如果我启动 node .运行mongodb的js应用程序before会捕获连接回调中的错误,但如果连接在此之后终止,它似乎不会以任何方式处理它.

我是否缺少一个设置,或者在建立连接后无法检测到连接被终止?

Edit: just to be clear, the username variable used in the find method is actually declared in my full code, the code I've put in this post is a cut down version to illustrate the structure and error checking.

推荐答案

UPD:

经过一番调查,我终于了解了那里的情况:

但一旦连接关闭,我就找不到任何会通过_notreprested游标进行迭代,并会用错误或计时器的任何逻辑触发它们的东西(它仍然可能在那里的某个地方).所以我设法编写了一个小的变通方法,当DB发出close个事件时,它会强制触发带有错误的游标:

new mongodb.Db('testdb', new mongodb.Server('localhost', 27017, { }), { safe: true }).open(function (err, db) {
  if (!err) {
    db.on('close', function() {
      if (this._callBackStore) {
        for(var key in this._callBackStore._notReplied) {
          this._callHandler(key, null, 'Connection Closed!');
        }
      }
    });

    // ...

  } else {
    console.log(err)
  }
});

我建议使用第一种方法而不是MongoClient.原因很少:例如,当您关闭连接,然后调用.find时,它将在回调中正确触发错误,而在MongoClient中则不会.

如果您使用的是MongoClient:

MongoClient.connect('mongodb://localhost:27017/testdb', function(err, db) {
  if (!err) {
    db.on('close', function() {
      if (this._callBackStore) {
        for(var key in this._callBackStore._notReplied) {
          this._callHandler(key, null, 'Connection Closed!');
        }
      }
    });

    // ...

  } else {
    console.log(err);
  }
});

这能做什么?一旦连接关闭,它将遍历所有未回复的游标,并为它们触发事件,错误为Connection Closed!.

测试用例:

items.find({ }).toArray(function(err, data) {
  if (!err) {
    console.log('Items found successfully');
  } else {
    console.log(err);
  }
});
db.close();

这将强制关闭数据库连接并触发之前处理的close个事件,并确保游标将被关闭.

UPD:

Mongodb相关问答推荐

无法从我的NextJS 14应用程序中的Redux工具包2.0中提取数据

如何在Golang保存到MongoDB时排除空数据值的问题?

在提供的文档(_Id)之后和之前,是否有一个Mongo操作来获取已排序(和/或过滤)集合中的文档计数?

数组中字符串的Mongo查询集合和推送到新数组嵌套对象

发布到 MongoDB 时生成的附加id字段

lexik_jwt_authentication下无法识别的选项api_platform

查询有关 Go 项目中对象数组的 MongoDb 集合

MongoDB:插入重复键更新

在一个变量上运行的 Node JS 中使用正则表达式的 Mongo 查询

Mongodb:查询嵌套在数组中的json对象

Node.js 和 Passport 对象没有方法 validPassword

如何更新 mongodb 文档以向数组添加新元素?

mongo php副本连接非常慢

如何使用 c# 2.0 驱动程序将数据插入到 mongodb 集合中?

如何在 mongoDB 中聚合巨大的数组?

Mongodb KeyFile 太开放权限

无法连接到远程服务器上的 mongo

如何在 Ubuntu 10.04 中使用 --auth 选项重新启动 mongodb?

MongoError:failed to connect to server [localhost:27017] on first connect

Hadoop Map/Reduce 与内置 Map/Reduce