node.js 调用退出后无法排队握手
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14087924/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cannot enqueue Handshake after invoking quit
提问by radek
Here I am doing, propably some basic mistake, In general, I've implemented such a 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();
}
}
And everything works great, but only by first time, If I want to "use" query by the second time I've receive his error:
一切都很好,但只有第一次,如果我想第二次“使用”查询,我会收到他的错误:
Cannot enqueue Handshake after invoking quit
调用退出后无法排队握手
I've tried not to .end() connections but it does not help
Thanks in advance
Radek
我试过不 .end() 连接,但它没有帮助
提前致谢
Radek
回答by Andrew Rhyne
If you using the node-mysql module, just remove the .connect and .end. Just solved the problem myself. Apparently they pushed in unnecessary code in their last iteration that is also bugged. You don't need to connect if you have already ran the createConnection call
如果您使用 node-mysql 模块,只需删除 .connect 和 .end。刚刚自己解决了这个问题。显然,他们在最后一次迭代中插入了不必要的代码,这些代码也被窃听了。如果您已经运行了 createConnection 调用,则不需要连接
回答by XP1
According to:
根据:
Fixing Node Mysql "Error: Cannot enqueue Handshake after invoking quit.":
http://codetheory.in/fixing-node-mysql-error-cannot-enqueue-handshake-after-invoking-quit/
修复节点 Mysql“错误:调用退出后无法入队握手。”:
http://codetheory.in/fixing-node-mysql-error-cannot-enqueue-handshake-after-invoking-quit/
TL;DRYou need to establish a new connection by calling the
createConnectionmethod after every disconnection.
TL;DR您需要
createConnection在每次断开连接后通过调用该方法来建立新连接。
and
和
Note:If you're serving web requests, then you shouldn't be ending connections on every request. Just create a connection on server startup and use the connection/client object to query all the time. You can listen on the error event to handle server disconnection and for reconnecting purposes. Full code here.
注意:如果您正在处理 Web 请求,那么您不应该在每个请求上都结束连接。只需在服务器启动时创建一个连接,并始终使用连接/客户端对象进行查询。您可以侦听错误事件以处理服务器断开连接和重新连接的目的。完整代码 在这里。
From:
从:
Readme.md - Server disconnects:
Readme.md - 服务器断开连接:
It says:
它说:
Server disconnects
You may lose the connection to a MySQL server due to network problems, the server timing you out, or the server crashing. All of these events are considered fatal errors, and will have the
err.code = 'PROTOCOL_CONNECTION_LOST'. See the Error Handling section for more information.The best way to handle such unexpected disconnects is shown below:
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);As you can see in the example above, re-connecting a connection is done by establishing a new connection. Once terminated, an existing connection object cannot be re-connected by design.
With Pool, disconnected connections will be removed from the pool freeing up space for a new connection to be created on the next getConnection call.
服务器断开连接
由于网络问题、服务器超时或服务器崩溃,您可能会失去与 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 调用时创建的新连接释放空间。
I have tweaked the function such that every time a connection is needed, an initializer function adds the handlers automatically:
我已经调整了该函数,以便每次需要连接时,初始化函数都会自动添加处理程序:
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;
}
Initializing a connection:
初始化连接:
var connection = initializeConnection({
host: "localhost",
user: "user",
password: "password"
});
Minor suggestion:This may not apply to everyone but I did run into a minor issue relating to scope. If the OP feels this edit was unnecessary then he/she can choose to remove it. For me, I had to change a line in initializeConnection, which was var connection = mysql.createConnection(config);to simply just
小建议:这可能不适用于所有人,但我确实遇到了与范围有关的小问题。如果 OP 认为此编辑是不必要的,则他/她可以选择将其删除。对我来说,我必须在 中更改一行initializeConnection,这var connection = mysql.createConnection(config);只是简单地
connection = mysql.createConnection(config);
The reason being that if connectionis a global variable in your program, then the issue before was that you were making a new connectionvariable when handling an error signal. But in my nodejs code, I kept using the same global connectionvariable to run queries on, so the new connectionwould be lost in the local scope of the initalizeConnectionmethod. But in the modification, it ensures that the global connectionvariable is reset This may be relevant if you're experiencing an issue known as
原因是如果connection是程序中的全局变量,那么之前的问题是您connection在处理错误信号时创建了一个新变量。但是在我的 nodejs 代码中,我一直使用相同的全局connection变量来运行查询,因此 newconnection将在方法的本地范围内丢失initalizeConnection。但是在修改中,它确保全局connection变量被重置如果您遇到称为
Cannot enqueue Query after fatal error
致命错误后无法入队查询
after trying to perform a query after losing connection and then successfully reconnecting. This may have been a typo by the OP, but I just wanted to clarify.
在失去连接并成功重新连接后尝试执行查询后。这可能是 OP 的打字错误,但我只是想澄清一下。
回答by hbrls
I had the same problem and Google led me here. I agree with @Ata that it's not right to just remove end(). After further Googling, I think using poolingis a better way.
我遇到了同样的问题,谷歌把我带到了这里。我同意@Ata 的观点,仅仅删除end(). 经过进一步的谷歌搜索,我认为使用pooling是一个更好的方法。
It's like this:
就像这样:
var mysql = require('mysql');
var pool = mysql.createPool(...);
pool.getConnection(function(err, connection) {
connection.query( 'bla bla', function(err, rows) {
connection.release();
});
});
回答by ajin
Do not connect() and end() inside the function. This will cause problems on repeated calls to the function. Make the connection only
不要在函数内部连接()和结束()。这将导致重复调用该函数时出现问题。仅建立连接
var connection = mysql.createConnection({
host: 'localhost',
user: 'node',
password: 'node',
database: 'node_project'
})
connection.connect(function(err) {
if (err) throw err
});
once and reuse that connection.
一次并重用该连接。
Inside the function
函数内部
function insertData(name,id) {
connection.query('INSERT INTO members (name, id) VALUES (?, ?)', [name,id], function(err,result) {
if(err) throw err
});
}
回答by LvxOne
AWS Lambda functions
AWS Lambda 函数
Use mysql.createPool()with connection.destroy()
使用mysql.createPool()和connection.destroy()
This way, new invocations use the established pool, but don't keep the function running. Even though you don't get the full benefit of pooling (each new connection uses a new connection instead of an existing one), it makes it so that a second invocation can establish a new connection without the previous one having to be closed first.
这样,新调用使用已建立的池,但不保持函数运行。即使您没有获得池的全部好处(每个新连接使用一个新连接而不是现有连接),它也可以使第二次调用可以建立新连接,而不必先关闭前一个连接。
Regarding connection.end()
关于 connection.end()
This can cause a subsequent invocation to throw an error. The invocation will still retry later and work, but with a delay.
这可能会导致后续调用引发错误。调用仍将稍后重试并工作,但会延迟。
Regarding mysql.createPool()with connection.release()
关于mysql.createPool()与connection.release()
The Lambda function will keep running until the scheduled timeout, as there is still an open connection.
Lambda 函数将继续运行,直到计划的超时,因为仍有打开的连接。
Code example
代码示例
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();
});
});
};
回答by Kundan Thakur
inplace of connection.connect();use -
代替connection.connect();使用 -
if(!connection._connectCalled )
{
connection.connect();
}
if it is already called then connection._connectCalled =true,
& it will not execute connection.connect();
如果是已经叫然后connection._connectCalled =true,
和它不会执行connection.connect();
note- don't use connection.end();
注意- 不要使用connection.end();
回答by tsuz
I think this issue is similar to mine:
我认为这个问题与我的相似:
- Connect to MySQL
- End MySQL service (should not quit node script)
- Start MySQL service, Node reconnects to MySQL
- Query the DB -> FAIL (Cannot enqueue Query after fatal error.)
- 连接到 MySQL
- 结束 MySQL 服务(不应退出节点脚本)
- 启动 MySQL 服务,Node 重新连接 MySQL
- 查询数据库 -> FAIL(致命错误后无法入队查询。)
I solved this issue by recreating a new connection with the use of promises (q).
我通过使用 promise (q) 重新创建新连接解决了这个问题。
mysql-con.js
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
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);
});
};
I hope this helps.
我希望这有帮助。
回答by JonTroncoso
If you're trying to get a lambda, I found that ending the handler with context.done()got the lambda to finish. Before adding that 1 line, It would just run and run until it timed out.
如果你想得到一个 lambda,我发现结束处理程序会让context.done()lambda 完成。在添加那 1 行之前,它会一直运行直到超时。
回答by Jorge Valvert
SOLUTION:to prevent this error(for AWS LAMBDA):
解决方案:为防止此错误(对于 AWS LAMBDA):
In order to exit of "Nodejs event Loop" you must end the connection, and then reconnect. Add the next code to invoke the callback:
为了退出“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,
});
});
回答by user1476842
You can use debug: false,
您可以使用调试:假,
Example: //mysql connection
示例://mysql 连接
var dbcon1 = mysql.createConnection({
host: "localhost",
user: "root",
password: "",
database: "node5",
debug: false,
});

