web-dev-qa-db-fra.com

Impossible de mettre en file d'attente Handshake après avoir appelé quit

Voici ce que je fais, probablement une erreur fondamentale, En général, j'ai implémenté un tel code:

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

Et tout fonctionne très bien, mais seulement à la première fois, si je veux "utiliser" la requête à la deuxième fois, je reçois son erreur:

Impossible de mettre en file d'attente Handshake après avoir appelé quit

J'ai essayé de ne pas avoir de connexions .end () mais ça n'aide pas 
Merci d'avance
Radek

65
radek

Si vous utilisez le module node-mysql, supprimez simplement les fichiers .connect et .end. Juste résolu le problème moi-même. Apparemment, ils ont introduit du code inutile dans leur dernière itération, qui est également bogué. Vous n'avez pas besoin de vous connecter si vous avez déjà exécuté l'appel createConnection.

200
Andrew Rhyne

Selon:

TL; DR Vous devez établir une nouvelle connexion en appelant la méthode createConnection après chaque déconnexion.

et

Remarque: Si vous envoyez des demandes Web, vous ne devriez pas mettre fin aux connexions à chaque demande. Créez simplement une connexion sur le serveur démarrage et utilisez l'objet connection/client pour interroger tout le temps . Vous pouvez écouter l'événement d'erreur pour gérer la déconnexion du serveur et pour se reconnecter. Code complet ici .


De:

Ça dit:

Serveur déconnecte

Vous risquez de perdre la connexion à un serveur MySQL en raison de problèmes de réseau, le serveur vous chronométrant ou le serveur en panne. Tous ces événements sont considérées comme des erreurs fatales et auront le err.code = 'PROTOCOL_CONNECTION_LOST'. Voir l'erreur Section Manipulation pour plus d'informations.

La meilleure façon de gérer de telles déconnexions inattendues est indiquée ci-dessous:

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

Comme vous pouvez le voir dans l'exemple ci-dessus, la reconnexion d'une connexion est fait en établissant une nouvelle connexion. Une fois terminé, un .__ existant. objet de connexion ne peut pas être reconnecté par conception.

Avec Pool, les connexions déconnectées seront supprimées du pool libérer de l'espace pour qu'une nouvelle connexion soit créée sur le prochain appel getConnection.


J'ai modifié la fonction de sorte que chaque fois qu'une connexion est nécessaire, une fonction d'initialisation ajoute automatiquement les gestionnaires:

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

Initialiser une connexion:

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

Suggestion mineure: Cela peut ne pas s'appliquer à tout le monde, mais j'ai rencontré un problème mineur lié à la portée. Si le OP estime que cette modification était inutile, il peut alors le supprimer. Pour moi, je devais changer une ligne dans initializeConnection, qui était var connection = mysql.createConnection(config); pour simplement

connection = mysql.createConnection(config);

La raison en est que si connection est une variable globale dans votre programme, le problème précédent était que vous créiez une nouvelle variable connection lors du traitement d'un signal d'erreur. Mais dans mon code nodejs, j'ai continué à utiliser la même variable globale connection pour exécuter des requêtes, de sorte que la nouvelle connection serait perdue dans la portée locale de la méthode initalizeConnection. Mais lors de la modification, la variable globale connection est réinitialisée. Cela peut être utile si vous rencontrez un problème appelé

Impossible de mettre en file d'attente la requête après une erreur irrécupérable

après avoir essayé d’effectuer une requête après avoir perdu la connexion, puis avec succès, vous reconnectez. C'était peut-être une faute de frappe de la part du PO, mais je voulais juste clarifier un point.

44
XP1

J'ai eu le même problème et Google m'a conduit ici. Je suis d’accord avec @Ata pour dire qu’il n’est pas correct de supprimer simplement end(). Après avoir cherché davantage sur Google, je pense que l’utilisation de pooling est un meilleur moyen.

doc-node-mysql sur le pooling

C'est comme ça:

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

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

Ne connectez pas () et fin () dans la fonction. Cela causera des problèmes lors d'appels répétés à la fonction. Faire la connexion seulement

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

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

});

une fois et réutilisez cette connexion.

À l'intérieur de la fonction 

function insertData(name,id) {

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


}
5
ajin

Je pense que ce problème est similaire au mien:

  1. Se connecter à MySQL
  2. Fin du service MySQL (ne doit pas quitter le script de noeud)
  3. Démarrer le service MySQL, le nœud se reconnecte à MySQL
  4. Interroger la base de données -> FAIL (impossible de mettre en file d'attente l'interrogation après une erreur irrécupérable.)

J'ai résolu ce problème en recréant une nouvelle connexion avec l'utilisation de promesses (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);
    });
};

J'espère que ça aide.

1
tsuz

Vous pouvez utiliser debug: false,

Exemple: // connexion mysql

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

Si vous essayez d'obtenir un lambda, j'ai constaté que mettre fin au gestionnaire avec context.done() obligeait le lambda à terminer. Avant d’ajouter cette ligne, il devrait simplement s’exécuter, jusqu’à expiration du délai imparti.

0
JonTroncoso

Fonctions AWS Lambda

Utilisez mysql.createPool () avec connection.destroy ()

De cette façon, les nouveaux appels utilisent le pool établi, mais ne gardent pas la fonction en cours d'exécution. Même si vous ne tirez pas pleinement parti du pooling (chaque nouvelle connexion utilise une nouvelle connexion au lieu d'une connexion existante), cela permet à une seconde invocation d'établir une nouvelle connexion sans que la précédente ne soit fermée en premier.

Concernant connection.end()

Cela peut provoquer une invocation ultérieure et générer une erreur. L'invocation réessayera plus tard et fonctionnera, mais avec un retard.

Concernant mysql.createPool() avec connection.release()

La fonction Lambda continuera à s'exécuter jusqu'à la fin du délai imparti, car la connexion est toujours ouverte.

Exemple de code

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();
    });
  });
};
0
LvxOne

SOLUTION: pour éviter cette erreur (pour AWS LAMBDA):

Pour quitter "Nodejs event Loop", vous devez mettre fin à la connexion, puis vous reconnecter. Ajoutez le code suivant pour appeler le rappel:

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,

        });
    });
0
Jorge Valvert

place de connection.connect(); usage -

if(!connection._connectCalled ) 
{
connection.connect();
}

si elle s'appelle déjà connection._connectCalled =true,
& il n’exécutera pas connection.connect();

note - ne pas utiliser connection.end();

0
Kundan Thakur