有Node.js的MongoDB在Docker中运行,但在Windows上不运行

问题

我遇到了类似于死锁的行为,我们的Node.js服务器应用程序对MongoDB实例运行了集成testing。 我们的testing代码和服务器代码都使用Mongoose和node.js驱动程序来访问MongoDB。

testing框架将删除数据库,并在每个testing套件开始时重新创build每个集合的索引(有时也可以是单个testing)。 这在testing过程中会发生很多次。

类似死锁的行为似乎在对db.collection.ensureIndex的一系列调用中发生。 一旦发生这种情况,所有执行都会停止,直到testing超时过期,这会中止testing。 如果我没有超时运行testing,挂起似乎是永远。

在这一点上,我觉得自己正在fla and,很想听到关于debugging方法或寻找线索方向的build议。 非常感谢。

细节

根据MongoDB并发常见问题解答 , ensureIndex在调用时不需要background:true选项ensureIndex需要一个独占的数据库写锁('W')。 不过,我已经通过Mongoosedebugging日志validation了background:true在这些调用中使用了background:true ,例如:

 mails.ensureIndex({ expires: 1, mailType: 1, readOn: 1 }) { background: true } 

但是,MongoDB日志出现(至less对我来说)表明一个独占锁试图:

 command: createIndexes { createIndexes: "mails", indexes: [ { name: "expires_1_mailType_1_readOn_1", key: { expires: 1, mailType: 1, readOn: 1 }, background: true } ], writeConcern: { w: 1 } } numYields:0 reslen:113 locks:{ Global: { acquireCount: { r: 1, w: 1 } }, Database: { acquireCount: { w: 1, W: 2 }, acquireWaitCount: { w: 1, W: 2 }, timeAcquiringMicros: { w: 1027663, W: 193312 } }, Collection: { acquireCount: { w: 1 } } } protocol:op_query 1289ms 

同时,当系统处于这种状态时,我无法使用任何客户端连接到数据库,包括mongo CLI,mongotop,mongostat或node.js驱动程序。 因此,我无法运行db.currentOp()db.serverStatus()来收集有关数据库状态的信息。 一旦我杀了testing,客户端可以连接,数据库恢复正常状态。 我不知道这是否是由全球排他性locking造成的,但它确实似乎是全球性的。

当node.js客户端代码在Docker容器(运行Linux)中执行时,此问题出现的时间为100%。 但是,在Windows上针对完全相同的MongoDB实例运行相同的客户端代码时,它绝不会发生。

这让我想知道这个问题是否会出现在MongoDB的node.js驱动程序的Linux版本中。 我在某种程度上研究了这个,但还没有发现任何结论。 我正在设置一个容器之外的另一个Linux环境,以查看是否可以在那里重现这个行为。

(编辑)我一直无法重现我的Linux机器上的问题,直接通过shell或在docker的容器中运行。 所以,我已经更新了这个问题的标题来反映这一点。 此外,我已经遇到了另一个Windows 10 Pro机器上的问题。

丢弃数据库

 mongoose.connection.db.dropDatabase(callback); 

重build索引

 // (inside a larger async.waterfall block) // Loop through all schemas and recreate all indexes. _.each(mongoose.connection.base.modelSchemas, function (schema, key) { asyncFunctions.push(function (cb) { mongoose.model(key, schema).ensureIndexes(err => { return cb(err); }); }); }); async.parallel(asyncFunctions, function (err) { return callback(err); }); 

上下文

  • mongoose@4.4.20(mongodb@2.1.18)
  • connect-mongodb-session@1.3.0(mongodb@2.2.24)< – 不同的mongodb版本
  • node –version => v6.9.1
  • mongod –version => v3.2.12(来自https://hub.docker.com/_/mongo/ )
  • 主机操作系统:Windows 10 Pro版本1607(操作系统版本14393.693)
  • 客户操作系统:Linux 4.9.12-moby
  • Docker v。17.03.0-ce

其他

我并不是说这是一个真正的DB僵局。 我无法确定。 这只是一个僵局。

我也尝试过使用* mongoose@4.9.0(mongodb@2.2.24)* mongod –version => v3.4.2这增加了驱动程序级别的超时,但是当我将它们设置为高时,类似死锁的行为仍然存在。

我尝试更换调用删除数据库调用collection.remove()为每个集合,但花了这么长时间,在该阶段的操作造成超时。

我也尝试用collection.drop()replace每个集合的DB drop,但是这会将死锁移到操作的这个阶段(而不是ensureIndex)。

最后,我尝试用async.series()replaceasync.parallel()调用ensureIndexes(上面),但是这只是延迟了死锁。