使用Node.js和mongodb处理超时 [英] Handling timeouts with Node.js and mongodb

查看:145
本文介绍了使用Node.js和mongodb处理超时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am currently testing how some code stands up against the following scenario:


  • 启动Node.js应用程序并成功建立连接到mongodb

  • 成功建立连接后,mongodb服务器死机,所有后续请求都失败

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

To do this I have got the following code which makes use of the official driver (found here: 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在处理请求时,服务器不再运行,我假设在我标记为## POINT 1 ##或## POINT 2 ##的点上,它将返回指示超时的错误;但是,情况并非如此。

As the mongodb server is no longer running when the request is being handled, I'd made the assumption that at either the points which I have labelled ## POINT 1 ## or ## POINT 2 ##, it would return an error indicating a timeout; this however, isn't the case.

我尝试了许多不同的设置(包括你可以在这里明确允许光标超时的设置),但是我似乎无法以任何方式启用它。在每个配置中我都尝试过Node.js会一直等待find()操作回调,而且它永远不会。

I have tried a number of different settings (including one you can see here that explicitly allows the cursor to timeout), however I cannot seem to enable it in any way. In every configuration I've tried Node.js will simply keep waiting for the find() operation to callback and it never does.

如果我启动Node.js应用程序运行mongodb之前,它会在连接回调中捕获错误,但如果连接在此之后死亡,它似乎无法以任何方式处理它。

If I start the Node.js application before running mongodb, it catches the error in the connect callback fine, but if the connection dies after that it doesn't seem to handle it in any way.

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

Is there a setting I am missing or is there no way to detect connections being terminated after they've been established?

编辑:只是要清楚的是,find方法中使用的用户名变量实际上是在我的完整代码中声明的,我在这篇文章中提到的代码是一个缩减版本,用于说明结构和错误检查。

推荐答案

UPD:

根据这篇文章,看起来他们已经部署了修复程序我们将在这里做同样的事情。不确定这是否已经在npm(15.10.13)内。 https://github.com/mongodb/node-mongodb -native / issues / 1092#ref-commit-2667d13

经过一番调查后,我已经设法理解那里发生了什么:

每次调用任何方法来处理数据库(查找,更新,插入等)时,它都会创建游标,该游标具有自己的ID并将自身注册到Db的EventEmitter,以便稍后回调。同时,它将自身注册到同一个CallBackStore中的_notReplied对象。

After some investigation I've managed to understand what is going on there:
Every time you call any method to deal with database (find, update, insert, etc.) it creates cursor, that has own ID and registers itself to EventEmitter of Db for being called back later. In meantime it registers itself to _notReplied object within same CallBackStore.

但是一旦连接关闭,我找不到任何会迭代_notReplied游标的东西,并会触发错误或任何带定时器的逻辑(它仍然可能在某处那里)。所以我设法写了一些小工作,当数据库发出关闭事件时,会强制触发游标错误:

But once connection is closed, I couldn't locate anything that would iterate through _notReplied cursors and would trigger them with errors or any logic with timers (it still might be somewhere there). So I've managed to write small work around, that does force triggers cursors with error when DB emits close event:

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则不会。

I recommend using first approach instead of MongoClient. Reasons are few: for example when you close connection and then call .find it will properly trigger error in callback, while with MongoClient it won't.

如果您使用的是MongoClient:

If you are using 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);
  }
});

这将做什么?一旦连接关闭,它将遍历所有_notReplied游标并为它们触发事件,错误连接已关闭!

What this will do? Once connection is closed, it will iterate through All _notReplied cursors and trigger events for them with error Connection Closed!.

测试用例:

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

这将强制关闭数据库连接并触发关闭你之前处理的事件,并确保光标将被关闭。

That will force close database connection and trigger close event that you handle earlier and will make sure that cursor will be closed.

UPD:
我在GitHub上添加了问题: https://github.com/mongodb/node-mongodb-native/issues/1092 我们我们会看到他们对此的看法。

UPD: I've added Issue on GitHub: https://github.com/mongodb/node-mongodb-native/issues/1092 we'll see what they say regarding this.

这篇关于使用Node.js和mongodb处理超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆