Node.js,Request,MySQL和Connection Pooling会导致无限阻塞/冻结行为?

时间:2013-06-17 22:26:09

标签: mysql node.js blocking

我正在开发一项连接到REST服务,获取响应,转换并将其写入数据库的服务。我最初在我的概念证明中使用了一个平面文件,一切正常。现在,在10-15个请求之后,脚本就会挂起。我得到所有30个请求在平面文件上工作,只有三分之一到数据库的一半。

我打算编写一个测试用例来隔离正在发生的事情,并发现在我删除了所有实际的应用程序逻辑,数据库模式和请求信息之后,我得到了类似的结果:< / p>

var mysql = require('mysql');
var pool  = mysql.createPool({
  host     : 'localhost',
  user     : 'user',
  password : 'secret',
});

while (true) {
        pool.getConnection(function (err, connection) {
            if (err) throw err;
            connection.query('SELECT 1 + 1 AS solution', function(err, rows, fields) {
              if (err) throw err;
              console.log('The solution is: ', rows[0].solution);
              connection.end();
            });
        });
}

据我所知,这是使用连接池执行操作的最少量代码。运行时,没有任何内容记录到命令行。删除while {}块,它按预期运行一次然后退出。

我的期望是池大小会提供约束,虽然它会很快查询mysql,但它不会超过一定的大小。相反,它似乎永远不会尝试建立联系。


根据Daniel关于异步库的评论以及何时调用connection.end()进行编辑。我遵循异步库在这里实现的逻辑,并且您应该尽早释放资源,但仍然存在阻塞。将查询结果打印到控制台一次,然后“挂起”。

var mysql = require('mysql'),
    async = require('async');
var pool = mysql.createPool({
  host     : 'localhost',
  user     : 'user',
  password : 'secret',
});



async.forever(function() {
                        pool.getConnection(function (err, connection) {
                            if(err) throw err;
                            connection.query('SELECT 1 + 1 AS solution', 
                              function(err, rows, fields) {
                              connection.end();
                              if (err) throw err;
                              console.log('The solution is: ', rows[0].solution);
                            });

                        });
            },
            function (err) {
                console.log(err);
            });

我不习惯被这种方式困住 - 似乎asyncmysql打破了异步的承诺...任何想法?

2 个答案:

答案 0 :(得分:2)

您正在使用同步循环来部署异步资源。你不能这样做。

你的while循环填满数据库池,然后再次循环并阻塞getConnection,然后阻塞整个Node.js事件循环。

您可以使用async包来执行异步while循环。

async#forever来电会做你想要达到的目标。


此外,您的代码正在泄漏数据库连接。您应该将connection.end()置于回调中,除非您再次使用相同的连接。否则,错误将泄漏数据库连接。

pool.getConnection(function (err, connection) {
    if (err) throw err;
    connection.query('SELECT 1 + 1 AS solution', function(err, rows, fields) {
      connection.end(); // return to pool before evaluating error.
      if (err) throw err;
      console.log('The solution is: ', rows[0].solution);
    });
});

答案 1 :(得分:1)

由于这篇关于异步库的实际使用的优秀文章,我发现了async.forever我做错了什么:http://www.sebastianseilund.com/nodejs-async-in-practice

关键是要了解异步如何使用其特殊的callback函数。它需要作为回调参数传递给最内层嵌套的异步函数,以便该函数可以将控制权传递回异步。这是我根据Daniel上面的反馈修改的脚本,更正为正确使用库(并且它按预期运行):

var mysql = require('mysql'),
    async = require('async');
var pool = mysql.createPool({
    host     : 'localhost',
    user     : 'user',
    password : 'secret', 
});



async.forever(function(callback) {
    pool.getConnection(function (err, connection) {
        if(err) throw err;
            connection.query('SELECT 1 + 1 AS solution', 
                function(err, rows, fields) {
                    connection.end(callback);
                    if (err) throw err;
                    console.log('The solution is: ', rows[0].solution);
                });
        });  
    },
    function (err) {
        console.log(err);  
    });