我为我正在开发的多人游戏编写了一个后端节点服务器,大多数时候每个请求需要大约20-100毫秒来解决。但是,有时候(也许50个请求中有1个)我会做同样的请求,需要2000 + ms才能解决。
服务器完全用node.js编写,并托管在heroku上。我正在使用mongoose来调用数据库。
以下是日志的屏幕截图,在顶部您可以看到查询通常如何运作。请求发布于19:03:03.68,响应发送时间为19:03:03.73,保存所有数据完成时间为19:03:03.74。 Heroku将请求记录为58ms,这是期望和期望的结果。
下面是问题发生时。您可以看到来自两个独立客户端的多个请求(每个客户端每秒发送~1个请求,这是正确的)但是请求建立起来并且在大约2000-5000ms之后它们将一个接一个地快速解决。我试图在没有太多运气的情况下缩小问题范围,但我认为这与我查询数据库的时间有关,因为您可以看到多个请求进入但数据库的第一个查询直到大约2300ms后才真正解决。据我所知,这些请求与在20-100ms内解决的请求完全相同。
实际代码在服务器上类似于此(为了这个问题而简化):
console.log (“request received”);
Game.findOne({‘id’: gameID}, function(err, theGame){
console.log("First Query");
我还打开了数据库的mongo shell,用这段代码查找花费了大量时间(> 2000ms)的查询:
db.system.profile.find( {millis: {$gt : 2000} } ).sort( { ts: 1} );
以下是略微修改的结果,其中应包括所有相关内容:
{ "op" : "update", "ns" : "theDb.players", "query" :
{ "_id" : ObjectId("572b8eb242d70903005df0df")
}, "updateobj" :
{ "$set" :
{ "lastSeen" : ISODate("2016-05-05T18:19:30.761Z"), "timeElapsed" : 16
}
}, "nscanned" : 1, "nscannedObjects" : 1, "nMatched" : 1, "nModified" : 1, "fastmod" : true, "keyUpdates" : 0, "writeConflicts" : 0, "numYield" : 0, "locks" :
{ "Global" :
{ "acquireCount":
{ "r" : NumberLong(2), "w" : NumberLong(2) }
}, "MMAPV1Journal" :
{ "acquireCount" :
{ "w" : NumberLong(2) }, "acquireWaitCount" :
{ "w" : NumberLong(1) }, "timeAcquiringMicros" :
{ "w" : NumberLong(7294179) }
}, "Database" :
{ "acquireCount" :
{ "w" : NumberLong(2) }
}, "Collection" :
{ "acquireCount" :
{ "W" : NumberLong(1) }
}, "oplog" :
{ "acquireCount" :
{ "w" : NumberLong(1) }
}
}, "milli" : 2298, "execStats" : {}, "ts" : ISODate("2016-05-05T18:19:33.060Z")
第二个结果:
{ "op" : "update", "ns" : "theDb.connections", "query" :
{ "_id" : ObjectId("572b8eaf42d70903005df0dd")
}, "updateobj" :
{ "$set" :
{ "internalCounter" : 3, "lastCount" : 3, "lastSeen" : ISODate("2016-05-05T18:19:30.761Z"), "playerID" : 128863276517, "sinceLast" : 0
}
}, "nscanned" : 1, "nscannedObjects" : 1, "nMatched" : 1, "nModified" : 1, "keyUpdates" : 0, "writeConflicts" : 0, "numYield" : 0, "locks" :
{ "Global" :
{ "acquireCount" :
{ "r" : NumberLong(2), "w" : NumberLong(2)
}
}, "MMAPV1Journal" :
{ "acquireCount" :
{ "w" : NumberLong(2) }, "acquireWaitCount" :
{ "w" : NumberLong(1) }, "timeAcquiringMicros" :
{ "w" :NumberLong(7294149) }
}, "Database" :
{ "acquireCount" :
{ "w" : NumberLong(2) }
}, "Collection" :
{ "acquireCount" :
{ "W" : NumberLong(1) }
}, "oplog" :
{ "acquireCount" :
{ "w" : NumberLong(1) }
}
}, "millis" : 2299, "execStats" : {},"ts" : ISODate("2016-05-05T18:19:33.061Z")
我确实需要确保任何请求的延迟从不超过500毫秒,否则它在游戏本身非常恼人。我真的对可能造成这种情况的原因感到茫然,以及如何找到更多。
我认为问题的原因是timeAcquiringMicros太长了。我不确定导致这种情况的原因。
*注意,客户端只使用标准的http请求请求数据,我目前没有使用任何套接字。
答案 0 :(得分:2)
好吧,我终于解决了这个问题。这个问题实际上与我所做过的事情无关。我正在使用mlab提供的与heroku相关的沙箱计划,我的应用程序与其他人一起使用沙箱计划竞争处理时间。他们的查询减慢了数据库的速度,导致响应时间出现峰值。
解决方案:我必须升级到他们的共享群集计划。自升级以来,查询时间没有任何不正常之处。