Node.js,请求,MySQL和连接池是否会导致无限阻止/冻结行为? [英] Node.js, Request, MySQL and Connection Pooling leads to Infinite Blocking/Freezing Behavior?

查看:112
本文介绍了Node.js,请求,MySQL和连接池是否会导致无限阻止/冻结行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm working on a service that connects to a REST service, gets a response, transforms it and writes it to a database. I was originally using a flat file in my proof of concept, and everything worked fine. Now, after 10-15 requests, the script would just hang. I was getting all 30 requests to work on the flat file, and only a third to half as many on the database.

我着手编写一个测试案例,以隔离正在发生的事情,并且发现在剥离了所有实际的应用程序逻辑,数据库模式和请求信息之后,我得出了类似这样的内容:

I set out to write a test case that would isolate what was going on, and found that after I had stripped out all of my actual application logic, database schema, and request information, I got down to something like this:

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 {}块,它会按预期运行一次,然后退出.

As far as I can imagine, this is the minimal amount of code to do something using a connection pool. When run, nothing is ever logged to the command line. Remove the while {} block, and it runs once as expected and then exits.

我的期望是,池大小将提供约束,并且尽管它可以非常快速地查询mysql,但是它永远不会超过一定的大小.相反,它似乎从未尝试建立连接.

My expectation was that the pool size would provide the constraint, and while it would be querying mysql quite quickly, it wouldn't ever grow over a certain size. Instead, it seems to never attempt to make a connection.

根据Daniel关于异步库以及何时调用connection.end()的评论进行编辑.我遵循异步库在这里实现的功能背后的逻辑,即您应该尽早释放资源,但是仍然有一些障碍.将查询结果打印到控制台一次,然后挂起".

Edits based on Daniel's comment about the async library and when to call connection.end(). I follow the logic behind what the async library is achieving here, and that you should release the resource as early as possible, but something is still blocking. The prints the result of the query to the console once, and then "hangs".

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都违反了异步的承诺...有什么想法吗?

I'm not comfortable being stuck this way - it seems like either async or mysql is breaking the promise of being asynchronous... any thoughts?

推荐答案

由于这篇关于异步库实际使用的出色文章,我发现async.forever在做错什么:

I found what I was doing wrong with async.forever , thanks to this excellent article about the practical use of the async library: http://www.sebastianseilund.com/nodejs-async-in-practice

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

The key is understanding how async uses its special callback functions. It needs to be passed to the inner-most nested asynchronous function as it's callback parameter, so that function can pass control back to async. Here's the script I revised based on Daniel's feedback from above, corrected to use the library properly (and it functions as expected):

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

这篇关于Node.js,请求,MySQL和连接池是否会导致无限阻止/冻结行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆