连接处于关闭状态时无法添加新命令

时间:2017-11-29 08:43:40

标签: node.js amazon-ec2 pm2

我正在使用Amazon EC2和Ubuntu。

我正在使用PM2运行服务器,如

pm2 start bin/www --log-date-format "YYYY-MM-DD HH:mm" --watch

它工作正常,但是当我试图在1或2天后访问API时。我会收到错误:

0|www      | 2017-11-29 08:30: name error  { Error: Can't add new command when connection is in closed state
0|www      |     at Connection._addCommandClosedState (/var/www/html/perb_nodejs/node_modules/mysql2/lib/connection.js:158:13)
0|www      |     at Connection.query (/var/www/html/perb_nodejs/node_modules/mysql2/lib/connection.js:621:15)
0|www      |     at Object.loginTrainer (/var/www/html/perb_nodejs/models/trainer.js:49:29)
0|www      |     at /var/www/html/perb_nodejs/routes/v1/trainer.js:50:16
0|www      |     at Layer.handle [as handle_request] (/var/www/html/perb_nodejs/node_modules/express/lib/router/layer.js:95:5)
0|www      |     at next (/var/www/html/perb_nodejs/node_modules/express/lib/router/route.js:137:13)
0|www      |     at Route.dispatch (/var/www/html/perb_nodejs/node_modules/express/lib/router/route.js:112:3)
0|www      |     at Layer.handle [as handle_request] (/var/www/html/perb_nodejs/node_modules/express/lib/router/layer.js:95:5)
0|www      |     at /var/www/html/perb_nodejs/node_modules/express/lib/router/index.js:281:22
0|www      |     at Function.process_params (/var/www/html/perb_nodejs/node_modules/express/lib/router/index.js:335:12) fatal: true }

然后我必须重新启动PM2实例。

据我所知,由于关闭连接,我正面临这个问题。但是为什么当我使用PM2时会发生这种情况。我认为PM2应该做同样的工作。

的package.json

{
  "name": "",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "body-parser": "~1.18.2",
    "cookie-parser": "~1.4.3",
    "cors": "2.8.4",
    "debug": "~2.6.9",
    "express": "~4.15.5",
    "jade": "~1.11.0",
    "morgan": "~1.9.0",
    "multer": "1.3.0",
    "mysql2": "1.5.0",
    "path": "0.12.7",
    "request": "2.83.0",
    "serve-favicon": "~2.4.5"
  }
}

编辑: 我认为这不是因为服务器而是数据库连接已关闭。

任何帮助将不胜感激。

6 个答案:

答案 0 :(得分:0)

我通过在10秒不活动后关闭连接,然后创建新连接来解决我的问题。真正的问题是没有办法知道连接是否畅通。

答案 1 :(得分:0)

10秒后如何关闭连接

答案 2 :(得分:0)

您需要监听连接上的error事件,然后在发生新连接后打开它。这是整个程序的外观:

for (;;) {
  try {
    const conn = await pool.getConnection();
    conn.on('error', err => {
      console.log(`Error on connection: ${err.message}`);
      // stop doing stuff with conn
    });
    try {
      // do stuff with conn
    } catch (err) {
      console.log(`Error doing stuff: ${err.message}`);
    } finally {
      conn.destroy();
    }
  } catch (err) {
    console.log(`Unable to acquire connection: ${err.message}`);
  }
  // delay before trying to reacquire connection
}

答案 3 :(得分:0)

我有同样的问题。在研究源代码时,我意识到在某些地方我们保持了 pool 数据库连接。因此,我更改了代码,以使我们始终在每次调用后释放连接,而不是将连接从一个函数传递给另一个函数。

let connection = await pool.getConnection();
try {
    // Run one query 
} finally {
    connection.release();
}

通过这种方式,池将始终返回有效的打开的连接。

当然,这仅适用于请求。在执行事务时,您仍然需要保持连接,但是仅在这种情况下才需要。

答案 4 :(得分:0)

池连接和8.0.15服务器存在相同的问题,更糟糕的是,我也有长时间运行的连接。目前,我对这个问题已经解决感到谨慎乐观。必须在您的逻辑中进行一些更改:

  1. 如果您需要长时间运行的连接,请首先检查MySQL服务器参数 wait_timeout -以秒为单位,一段时间后它会杀死静默连接,可能对您来说足够了这个值
  2. 如果 wait_timeout 不够用,您可以间隔一段时间使用 connection.ping 方法-它将使连接保持活动状态
  3. 在操作后分析错误对象:如果错误对象具有 fatal = true ,则连接变得无用(可能是由于某种原因关闭了或丢失了连接)-您必须调用 connection.destroy( -它将从池中删除此中毒的连接,否则池可以再次提供此连接-可能应在池逻辑中进行一些更改。

答案 5 :(得分:0)

我最终要做的是将连接请求放入它自己的.js文件中- connectionRequest.js

module.exports = function () {

    let mysql = require('mysql2')
    let connCreds = require('./connectionsConfig.json');

    //Establish Connection to the DB
    let connection = mysql.createConnection({
        host: connCreds["host"],
        user: connCreds['username'],
        password: connCreds['password'],
        database: connCreds['database'],
        port: 3306
    });

    //Instantiate the connection
    connection.connect(function (err) {
        if (err) {
            console.log(`connectionRequest Failed ${err.stack}`)
        } else {
            console.log(`DB connectionRequest Successful ${connection.threadId}`)
        }
    });

    //return connection object
    return connection
}

一旦完成,便可以将其导入控制器文件中的查询中,

let connectionRequest = require('../config/connectionRequest')

controllerMethod: (req, res, next) => {
    //Establish the connection on this request
    connection = connectionRequest()

    //Run the query
    connection.query("SELECT * FROM table", function (err, result, fields) {
        if (err) {
            // If an error occurred, send a generic server failure
            console.log(`not successful! ${err}`)
            connection.destroy();

        } else {
            //If successful, inform as such
            console.log(`Query was successful, ${result}`)

            //send json file to end user if using an API
            res.json(result)

            //destroy the connection thread
            connection.destroy();
        }
    });
},