调用退出后无法排队握手

时间:2012-12-30 02:57:30

标签: node.js express

我在这里,可能是一些基本的错误,一般来说,我已经实现了这样的代码:

module.exports = {
    getDataFromUserGps: function(callback)
    {
        connection.connect();
        connection.query("SELECT * FROM usergps", 
            function(err, results, fields) {
                if (err) return callback(err, null);
                return callback(null, results);
            }
        ); 
        connection.end();
    },
    loginUser: function(login, pass, callback)
    {
        connection.connect();
        connection.query(
            "SELECT id FROM users WHERE login = ? AND pass = ?",
            [login, pass],
            function(err, results, fields) 
            {
                if (err) return callback(err, null);
                return callback(null, results);
            }
        ); 
        connection.end();
    },
    getUserDetails: function(userid, callback)
    {
        connection.connect();
        connection.query(
            "SELECT * FROM userProfilDetails LEFT JOIN tags ON userProfilDetails.userId = tags.userId WHERE userProfilDetails.userid = ?",
            [userid],
            function(err, results, fields)
            {
                if (err) return callback(err, null);
                return callback(null, results);
            }
        );
        connection.end();
    },
    addTags: function(userId, tags)
    {
        connection.connect();
        connection.query(
            "INSERT INTO tag (userId, tag) VALUES (?, ?)",
            [userId, tags],
            function(err, results, fields)
            {
                if (err) throw err;
            }
        )
        connection.end();
    }
}

一切都很好,但只有第一次,如果我想"使用"第二次查询我收到了他的错误:

  

调用退出后无法排队握手

我已经尝试过不要.end()连接,但它没有帮助 提前谢谢你 拉狄克

10 个答案:

答案 0 :(得分:208)

如果您使用node-mysql模块,只需删除.connect和.end即可。刚刚解决了这个问题。显然,他们在最后一次迭代中推送了不必要的代码,这也是错误的。如果已经运行了createConnection调用

,则无需连接

答案 1 :(得分:46)

根据:

  

TL; DR 您需要在每次断开连接后调用createConnection方法建立新连接。

  

注意:如果您正在提供网络请求,那么您不应该在每个请求上结束连接。只需在服务器上创建一个连接   启动并使用连接/客户端对象一直查询。   您可以侦听错误事件以处理服务器断开连接   用于重新连接目的。完整代码   here


自:

它说:

  

服务器断开连接

     

由于网络问题,您可能会丢失与MySQL服务器的连接,   服务器计时你,或服务器崩溃。所有这些事件   被认为是致命错误,并且会有err.code = 'PROTOCOL_CONNECTION_LOST'。请参阅错误   处理部分了解更多信息。

     

处理此类意外断开连接的最佳方法如下所示:

function handleDisconnect(connection) {
  connection.on('error', function(err) {
    if (!err.fatal) {
      return;
    }

    if (err.code !== 'PROTOCOL_CONNECTION_LOST') {
      throw err;
    }

    console.log('Re-connecting lost connection: ' + err.stack);

    connection = mysql.createConnection(connection.config);
    handleDisconnect(connection);
    connection.connect();
  });
}

handleDisconnect(connection);
     

正如您在上面的示例中所看到的,重新连接连接是   通过建立新连接完成。一旦终止,现有的   连接对象无法通过设计重新连接。

     

使用Pool,将从池中删除断开连接的连接   释放空间以便在下一个创建新连接   getConnection调用。


我调整了函数,每次需要连接时,初始化函数会自动添加处理程序:

function initializeConnection(config) {
    function addDisconnectHandler(connection) {
        connection.on("error", function (error) {
            if (error instanceof Error) {
                if (error.code === "PROTOCOL_CONNECTION_LOST") {
                    console.error(error.stack);
                    console.log("Lost connection. Reconnecting...");

                    initializeConnection(connection.config);
                } else if (error.fatal) {
                    throw error;
                }
            }
        });
    }

    var connection = mysql.createConnection(config);

    // Add handlers.
    addDisconnectHandler(connection);

    connection.connect();
    return connection;
}

初始化连接:

var connection = initializeConnection({
    host: "localhost",
    user: "user",
    password: "password"
});

次要建议:这可能不适用于所有人,但我确实遇到了与范围有关的小问题。如果OP认为此编辑是不必要的,那么他/她可以选择将其删除。对我而言,我必须更改initializeConnection中的一行,var connection = mysql.createConnection(config);只是

connection = mysql.createConnection(config);

原因是如果connection是程序中的全局变量,那么之前的问题是您在处理错误信号时正在创建一个新的connection变量。但是在我的nodejs代码中,我一直使用相同的全局connection变量来运行查询,因此新的connection将在initalizeConnection方法的本地范围内丢失。但在修改中,它确保重置全局connection变量如果您遇到称为

的问题,这可能是相关的
  

致命错误后无法将查询排入队列

在失去连接后尝试执行查询然后成功重新连接。这可能是OP的错字,但我只想澄清一下。

答案 2 :(得分:16)

我遇到了同样的问题,谷歌把我带到了这里。我同意@Ata的意见,即删除end()是不对的。进一步谷歌搜索后,我认为使用pooling是一种更好的方式。

node-mysql doc about pooling

就是这样:

var mysql = require('mysql');
var pool  = mysql.createPool(...);

pool.getConnection(function(err, connection) {
    connection.query( 'bla bla', function(err, rows) {
        connection.release();
    });
});

答案 3 :(得分:6)

不要在函数内连接()和end()。这将导致重复调用该函数时出现问题。仅建立连接

var connection = mysql.createConnection({
      host: 'localhost',
      user: 'node',
      password: 'node',
      database: 'node_project'
    })

connection.connect(function(err) {
    if (err) throw err

});

一次并重复使用该连接。

功能内部

function insertData(name,id) {

  connection.query('INSERT INTO members (name, id) VALUES (?, ?)', [name,id], function(err,result) {
      if(err) throw err
  });


}

答案 4 :(得分:1)

我认为这个问题与我的相似:

  1. 连接MySQL
  2. 结束MySQL服务(不应该退出节点脚本)
  3. 启动MySQL服务,Node重新连接到MySQL
  4. 查询数据库 - >失败(致命错误后无法排队查询。)
  5. 我通过使用promises(q)重新创建一个新连接来解决这个问题。

    的MySQL-con.js

    'use strict';
    var config          = require('./../config.js');
    var colors          = require('colors');
    var mysql           = require('mysql');
    var q               = require('q');
    var MySQLConnection = {};
    
    MySQLConnection.connect = function(){
        var d = q.defer();
        MySQLConnection.connection = mysql.createConnection({
            host                : 'localhost',
            user                : 'root',
            password            : 'password',
            database            : 'database'
        });
    
        MySQLConnection.connection.connect(function (err) {
            if(err) {
                console.log('Not connected '.red, err.toString().red, ' RETRYING...'.blue);
                d.reject();
            } else {
                console.log('Connected to Mysql. Exporting..'.blue);
                d.resolve(MySQLConnection.connection);
            }
        });
        return d.promise;
    };
    
    module.exports = MySQLConnection;
    

    mysqlAPI.js

    var colors          = require('colors');
    var mysqlCon        = require('./mysql-con.js');
    mysqlCon.connect().then(function(con){
       console.log('connected!');
        mysql = con;
        mysql.on('error', function (err, result) {
            console.log('error occurred. Reconneting...'.purple);
            mysqlAPI.reconnect();
        });
        mysql.query('SELECT 1 + 1 AS solution', function (err, results) {
                if(err) console.log('err',err);
                console.log('Works bro ',results);
        });
    });
    
    mysqlAPI.reconnect = function(){
        mysqlCon.connect().then(function(con){
          console.log("connected. getting new reference");
            mysql = con;
            mysql.on('error', function (err, result) {
                mysqlAPI.reconnect();
            });
        }, function (error) {
          console.log("try again");
            setTimeout(mysqlAPI.reconnect, 2000);
        });
    };
    

    我希望这会有所帮助。

答案 5 :(得分:1)

AWS Lambda函数

  

mysql.createPool() connection.destroy()

一起使用

这样,新调用将使用已建立的池,但不会使函数保持运行状态。即使您没有获得共享池的全部好处(每个新连接使用一个新连接而不是一个现有连接),也可以这样做,以便第二次调用可以建立一个新连接,而不必先关闭先前的连接。

关于connection.end()

这可能导致随后的调用引发错误。调用仍会稍后重试并可以工作,但会有所延迟。

关于mysql.createPool()connection.release()

Lambda函数将一直运行直到预定的超时,因为仍然有打开的连接。

代码示例

const mysql = require('mysql');

const pool = mysql.createPool({
  connectionLimit: 100,
  host:     process.env.DATABASE_HOST,
  user:     process.env.DATABASE_USER,
  password: process.env.DATABASE_PASSWORD,
});

exports.handler = (event) => {
  pool.getConnection((error, connection) => {
    if (error) throw error;
    connection.query(`
      INSERT INTO table_name (event) VALUES ('${event}')
    `, function(error, results, fields) {
      if (error) throw error;
      connection.destroy();
    });
  });
};

答案 6 :(得分:0)

解决方案:以防止此错误(对于AWS LAMBDA):

要退出“Nodejs event Loop”,您必须结束连接,然后重新连接。添加下一个代码以调用回调:

connection.end( function(err) {
        if (err) {console.log("Error ending the connection:",err);}

       //  reconnect in order to prevent the"Cannot enqueue Handshake after invoking quit"

         connection = mysql.createConnection({
                host     : 'rds.host',
                port     :  3306,
                user     : 'user',
               password : 'password',
               database : 'target database'

               });
        callback(null, {
            statusCode: 200,
            body: response,

        });
    });

答案 7 :(得分:0)

代替appname://joinme/conference的使用-

connection.connect();

如果已被调用,则if(!connection._connectCalled ) { connection.connect(); }
并且它不会执行connection._connectCalled =true;

注释-不要使用connection.connect()

答案 8 :(得分:0)

如果您尝试获取lambda,我发现以context.done()结尾的处理程序可以使lambda完成。在添加那一行之前,它会一直运行直到超时。

答案 9 :(得分:0)

您可以使用 调试:false,

示例: // mysql连接

var dbcon1 = mysql.createConnection({
      host: "localhost",
      user: "root",
      password: "",
      database: "node5",
      debug: false,
    });