有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(上面),但是这只是延迟了死锁。