关于#node.js#的问题:express中使用mysql ,运行长时间之后报read ECONNRESET(语言-javascript)

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


不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^