3

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

我开始编写一个测试用例来隔离正在发生的事情,并发现在我剥离了所有实际的应用程序逻辑、数据库模式和请求信息之后,我得到了这样的结果:

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);
            });

我不习惯这样被困住——看起来要么async或者mysql正在违背异步的承诺……有什么想法吗?

4

2 回答 2

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);
    });
});
于 2013-06-17T22:33:36.070 回答
2

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

关键是理解 async 如何使用它的特殊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);  
    });
于 2013-06-19T17:45:50.083 回答