Node.js 调用quit后无法将握手排队

Node.js 调用quit后无法将握手排队,node.js,express,Node.js,Express,我已经实现了以下代码: module.exports = { getDataFromUserGps: function(callback) { connection.connect(); connection.query("SELECT * FROM usergps", function(err, results, fields) { if (err) return ca

我已经实现了以下代码:

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();
    }
}
一切都只是第一次很好。如果我想第二次“使用”查询,我会得到以下错误:

Cannot enqueue Handshake after invoking quit
我尝试不使用
.end()
连接,但没有帮助


如何解决此问题?

如果使用节点mysql模块,只需删除.connect和.end即可。我自己解决了这个问题。很明显,他们在上一次迭代中引入了不必要的代码,而这些代码也有缺陷。如果您已根据以下要求运行createConnection调用,则无需连接:

  • 正在修复节点Mysql“错误:调用quit后无法将握手排队。”:

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

注意:如果您正在为web请求提供服务,那么您不应该在每个请求上都结束连接。只需在服务器上创建一个连接 启动并始终使用connection/client对象进行查询。 您可以侦听错误事件以处理服务器断开连接和 用于重新连接目的。完整代码


发件人:

  • Readme.md-服务器断开连接:

它说:

服务器断开连接 由于网络问题,您可能会失去与MySQL服务器的连接, 服务器超时,或者服务器崩溃。所有这些事件 被视为致命错误,并且将具有
err.code=
“协议连接丢失”
。看到错误了吗 有关更多信息,请参阅“处理”部分

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

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);
正如您在上面的示例中所看到的,重新连接连接是非常困难的 通过建立新的连接来完成。一旦终止,现有的 无法通过设计重新连接连接对象

对于池,断开的连接将从池中删除 释放空间以便在下一个服务器上创建新连接 获取连接呼叫


我对函数进行了调整,使得每次需要连接时,初始化器函数都会自动添加处理程序:

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

出现致命错误后,无法将查询排队


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

我也有同样的问题,谷歌把我带到了这里。我同意@Ata的观点,即仅仅删除
end()
是不对的。在进一步的谷歌搜索之后,我认为使用
pooling
是一种更好的方法

是这样的:

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

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

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

  • 连接到MySQL
  • 结束MySQL服务(不应退出节点脚本)
  • 启动MySQL服务,节点重新连接到MySQL
  • 查询数据库->失败(致命错误后无法将查询排队。)
  • 我通过使用承诺(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);
        });
    };
    
    我希望这有帮助。

    不要在函数中连接()和结束()。这将导致重复调用函数时出现问题。只进行连接

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

    解决方案:为防止此错误(适用于AWS LAMBDA):

    为了退出“Nodejs事件循环”,您必须结束连接,然后重新连接。添加下一段代码以调用回调:

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

    代替
    connection.connect()使用-

    if(!connection._connectCalled ) 
    {
    connection.connect();
    }
    
    如果已调用,则连接。_connectCalled=true

    &它不会执行
    connection.connect()


    注意-不要使用
    connection.end()

    如果您试图获取lambda,我发现用
    context.done()
    结束处理程序可以完成lambda。在添加这1行之前,它将一直运行,直到超时。

    AWS Lambda函数 将mysql.createPool()与connection.destroy()一起使用

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

    关于
    连接.end()

    这可能会导致后续调用抛出错误。调用仍将稍后重试并工作,但会有延迟

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

    Lambda函数将一直运行,直到计划的超时,因为仍然存在打开的连接

    代码示例 你可以用 调试:错误

    例如: //mysql连接

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

    你能至少结束这个问题吗?对我来说
    var dbcon1 = mysql.createConnection({
          host: "localhost",
          user: "root",
          password: "",
          database: "node5",
          debug: false,
        });