有没有被node-mongodb-native驱动坑过的

事情是这样的,我们的系统经常出现莫名其妙的卡顿现象.一个正常情况下40ms就完成的请求,有时候会出现短则几秒钟,长则几十秒的延时.经过排查,排除了mongodb慢查询,道理上讲同一个请求,同样的参数数据库查询不可能一会儿快一会儿慢.然后在mongo驱动里打日志分析,确定不是发生了数据库重连.那进一步推断只能是mongo驱动回调机制出现了问题.经过N个小时的问题排查,手段包括加连接数,加服务器,升级mongo驱动到最新版本.这其中只有加连接数奏效了.

还有一个奇怪的现象.在压力测试的时候,查询同一个接口,压到1000qps也不会出现卡顿的,然而放到生产环境后,就会有卡顿.综合这几个分析结果,我猜测是有慢查询影响了快的查询,于是进行了测试.

在测试中,我把连接数限制到2.同时启动两个查询,一块一慢,两个都是每隔一秒查询一次,这个时候能发现快的那个查询存在明显的卡顿现象,一会儿几十毫秒,一会儿就飙到几秒十几秒去了.然而单独执行快查询,时间就很平均且都是几十毫秒就执行完了.更夸张的是,如果连接数调成1,这俩查询是一起回调的,都是十几秒才完成.而如果把这两种查询任务分配独立的连接池,它们之间就没有影响了.

这样就基本得出了结论.node-mongodb-native这个驱动每个连接上的查询是会排队的,并不像熟悉nodejs的人想象的那样基于事件驱动,IO完成就回调,是坑爹的排队执行的,同一个连接前面有慢查询的话,慢查询结束之前后面的查询必须等待!!!

这也解释了为什么加连接数会有效果,因为连接数多了以后,同一个连接数上排队的查询就会少一点,那队列前面存在慢查询的几率也小了.然而连接数优化只能缓解问题,不能从根本上解决问题,当我们把每个进程的连接数从10加到50后,卡顿现象少了一半.从50加到100,没有变化.

解决办法还没有定下来,我测试了java驱动,不存在快慢查询排队现象.先把问题分享出来,看看大家有遇到过这个问题没有.实在不行,打算把数据库查询功能用java写成一个代理服务,不用node这个驱动了.

贴一下测试代码,find1是快查询,find2是慢查询.

var Then = require('thenjs');
var mongodb = require('mongodb3');
var MongoClient = mongodb.MongoClient;

function DB(url,cb) {
    MongoClient.connect(url,function(err, client) {
        if(err){
            console.log('connect db failed!'+err);
        }else{
            console.log("connect db success!");
            cb(null,client);
        }
    });
}

Then(function(cont){
    DB('mongodb://USER:PWD@IP:PORT/bill?authSource=admin&maxPoolSize=1',cont);
})
.then(function(cont,client){
    var find1 = function(){
        console.time("access_ip.find");
        client.collection("access_ip").find().toArray(function(err,res){
            //console.log("access_ip.find res length: " + res.length);
            console.timeEnd("access_ip.find");
            setTimeout(find1,1000);
        });
    };
    find1();

    var db = client.db('test');
    var find2 = function(){
        console.time("app_customer_repeat.find");
        db.collection('app_customer_repeat').findOne({name:"XXX"},function(err,res){
            //console.log("app_customer_repeat.find res: " + res);
            console.timeEnd("app_customer_repeat.find");
            setTimeout(find2,1000);
        });
    };
    find2();
});
阅读 3k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题