express中使用mysql ,运行长时间之后报read ECONNRESET
在每个api中使用connect和end就会导致只有第一次请求有返回,后面的请求都会报Cannot enqueue Handshake after invoking quit
exports.login = async (req, res, next) => {
try {
const username = req.body.reqdata.username;
const password = req.body.reqdata.password;
db.connect()
const sql = `select * from user where loginid='${username}' and password ='${password}'`;
//console.log(sql)
db.query(sql, (err, results, fields) => {
console.log(results);
console.log(err);
if (err) {
res.send({
err: err.message,
});
}
if (results.length > 0) {
//生成token,并且在返回数据中返回,设置了60S失效的token
const token = jwt.sign(req.body, "dsj", { expiresIn: 36000 });
res.send({
message: 0,
data: results,
token: token,
});
} else {
res.send({
message: 1,
data: results,
});
}
});
db.end()
} catch (err) {
next(err);
}
};
如果不使用connect和end,程序可以正常运行一段时间,但是时间长了之后就会导致报Error: read ECONNRESET
百度了很多都没有解决方案,复制粘贴的答案就不要了,只求解决办法,让程序能稳定运行
首先,在应用程序的入口(例如app.js)中配置连接池,使用mysql2模块创建连接池,代码示例如下:
const mysql = require('mysql2');
const pool = mysql.createPool({
host: 'your_host',
user: 'your_username',
password: 'your_password',
database: 'your_database',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
然后,在应用程序的其他部分中使用连接池而不是直接创建连接。例如,在你的API中,可以这样使用连接池:
exports.login = async (req, res, next) => {
try {
const username = req.body.reqdata.username;
const password = req.body.reqdata.password;
const sql = `select * from user where loginid='${username}' and password ='${password}'`;
pool.query(sql, (err, results, fields) => {
if (err) {
res.send({
err: err.message,
});
}
if (results.length > 0) {
const token = jwt.sign(req.body, "dsj", { expiresIn: 36000 });
res.send({
message: 0,
data: results,
token: token,
});
} else {
res.send({
message: 1,
data: results,
});
}
});
} catch (err) {
next(err);
}
};
这样,你就可以通过使用连接池来避免“Cannot enqueue Handshake after invoking quit”错误。
注意:不需要使用db.end()关闭连接了,因为连接池会自动管理连接。
有用请采纳!
根据您描述的问题,请尝试如下解决办法:
将db server的wait_timeout修改成900s以下,让服务器主动close掉连接会比较好,一般我们建议设置为600s
nodejs需要主动设置connection的timeout比较好,最好比server端的值还要低,Java类的项目设置为585s
我们的Java类的项目都是通过hikara来管理连接池,均是设置的585s超时,同时他们访问的数据库均是设置为600s超时,所以没有出现过类似问题。
我猜测可能是由于每次请求都新建了一个连接,而不是重用已有的连接。在连接被重用之前,它会被断开,导致"read ECONNRESET"错误。
解决方法之一是使用连接池,在连接池中维护可用连接,每次请求时从连接池中获取连接,并在请求结束后释放连接。这样能够有效地避免频繁新建连接和断开连接带来的性能损失。
另一种方法是使用单例模式维护一个全局连接,在程序启动时连接数据库,在程序结束时断开连接。这样能够保证程序中始终只有一个连接在使用,并且能够在程序结束时断开连接。
需要注意是,在使用连接池或单例模式时,需要确保每次使用完数据库连接后释放连接,避免连接泄漏。
推荐下面的写法
**dbutil.js导出模块为createConnection函数:**
var mysql = require('mysql');
function createConnection() {
var connection = mysql.createConnection({
host: '127.0.0.1',
database: 'school',
user: 'root',
password: '123456'
});
return connection;
}
module.exports.createConnection = createConnection;
**Dao文件中每次dbutil.createConnection();即可**
var dbutil = require('./dbutil');
var connection = null;
function queryStudentBysNoAndSex(sNo, sex) {
connection = dbutil.createConnection();
connection.connect();
var queryStudent = "select * from student where sNo = ? and sex = ?";
var params = [sNo, sex];
connection.query(queryStudent, params, function (error, result) {
if (error == null) {
console.log(result);
} else {
console.log(error);
}
connection.end();
});
}
不知道你这个问题是否已经解决, 如果还没有解决的话: