关闭 MySQL 后 Node.js 进程无法恢复,然后再打开

Posted

技术标签:

【中文标题】关闭 MySQL 后 Node.js 进程无法恢复,然后再打开【英文标题】:Node.js process cannot recover after MySQL turned off, then turn on 【发布时间】:2016-02-12 16:06:03 【问题描述】:

我正在将 Node.js 与 mysql 和 restify 一起使用。

我有以下作为 REST API 的一部分运行的代码。它工作正常。

server.get('/test', function (req, res, next) 
    var query_string =
        "SELECT DATE(date_transacted) AS transaction_date, " +
        " MonthReports.tb AS MonthReports__tb " +
        " FROM monthly_reports MonthReports " +
        " WHERE ( date_transacted >= \'2015-01-00\' AND date_transacted <= \'2015-09-00\' ) ";

    connection.query(
        query_string
        , function (err, rows, fields) 
            if (err) throw err;
            res.send(rows);
        );
);

如果我故意关闭 MySQL 数据库并调用 REST API 来运行查询,我会收到错误消息

致命错误后无法将查询入队。

此时,我打开了 MySQL 数据库。 node.js 进程无法恢复,并且在我进行 REST API 调用时不断出现相同的错误。 REST API 服务器已死。

如何使 Node.js REST API 服务器代码可恢复?

【问题讨论】:

【参考方案1】:

我假设您在脚本内进行全局连接。

一种简单的方法是为每个请求创建一个连接:

server.get('/test', function (req, res, next) 
    var query_string =
        "SELECT DATE(date_transacted) AS transaction_date, " +
        " MonthReports.tb AS MonthReports__tb " +
        " FROM monthly_reports MonthReports " +
        " WHERE ( date_transacted >= \'2015-01-00\' AND date_transacted <= \'2015-09-00\' ) ";



    var connection = getConnection(function connected(err) 
        if (err) 
           // error connecting  to mysql! alert user
         else 
          connection.query(
            query_string
            , function (err, rows, fields) 
              if (err) throw err;
              res.send(rows);
          );
        
    );

);

上面的代码是伪代码,因为我不熟悉 node mysql 库。这将允许每个请求查看是否能够连接到 mysql,但代价是每个 Web 请求都有一个连接。


另一种策略是在发出查询时检查err,如果出现错误,请尝试重新建立全局连接

server.get('/test', function (req, res, next) 
    var query_string =
        "SELECT DATE(date_transacted) AS transaction_date, " +
        " MonthReports.tb AS MonthReports__tb " +
        " FROM monthly_reports MonthReports " +
        " WHERE ( date_transacted >= \'2015-01-00\' AND date_transacted <= \'2015-09-00\' ) ";

    connection.query(
        query_string
        , function (err, rows, fields) 
            if (err) 
              // Try to reconnect here instead of throwing error and stopping node process, and reissue query
            
            res.send(rows);
        );
);

【讨论】:

【参考方案2】:

这个网站给出了完整的答案。归功于这篇文章的作者,而不是我。

https://www.exratione.com/2013/01/nodejs-connections-will-end-close-and-otherwise-blow-up/

/**
 * @fileOverview A simple example module that exposes a getClient function.
 *
 * The client is replaced if it is disconnected.
 */

var mysql = require("mysql");

var client = mysql.createConnection(
  host: "127.0.0.1",
  database: "mydb",
  user: "username",
  password: "password"
);

/**
 * Setup a client to automatically replace itself if it is disconnected.
 *
 * @param Connection client
 *   A MySQL connection instance.
 */
function replaceClientOnDisconnect(client) 
  client.on("error", function (err) 
    if (!err.fatal) 
      return;
    

    if (err.code !== "PROTOCOL_CONNECTION_LOST") 
      throw err;
    

    // client.config is actually a ConnectionConfig instance, not the original
    // configuration. For most situations this is fine, but if you are doing
    // something more advanced with your connection configuration, then
    // you should check carefully as to whether this is actually going to do
    // what you think it should do.
    client = mysql.createConnection(client.config);
    replaceClientOnDisconnect(client);
    client.connect(function (error) 
      if (error) 
        // Well, we tried. The database has probably fallen over.
        // That's fairly fatal for most applications, so we might as
        // call it a day and go home.
        //
        // For a real application something more sophisticated is
        // probably required here.
        process.exit(1);
      
    );
  );


// And run this on every connection as soon as it is created.
replaceClientOnDisconnect(client);

/**
 * Every operation requiring a client should call this function, and not
 * hold on to the resulting client reference.
 *
 * @return Connection
 */
exports.getClient = function () 
  return client;
;

【讨论】:

【参考方案3】:

此答案摘自另一个链接nodejs mysql Error: Connection lost The server closed the connection

提取的代码;

var db_config = 
  host: 'localhost',
    user: 'root',
    password: '',
    database: 'example'
;

var connection;

function handleDisconnect() 
  connection = mysql.createConnection(db_config); // Recreate the connection, since
                                                  // the old one cannot be reused.

  connection.connect(function(err)               // The server is either down
    if(err)                                      // or restarting (takes a while sometimes).
      console.log('error when connecting to db:', err);
      setTimeout(handleDisconnect, 2000); // We introduce a delay before attempting to reconnect,
                                         // to avoid a hot loop, and to allow our node script to
  );                                     // process asynchronous requests in the meantime.
                                          // If you're also serving http, display a 503 error.
  connection.on('error', function(err) 
    console.log('db error', err);
    if(err.code === 'PROTOCOL_CONNECTION_LOST')  // Connection to the MySQL server is usually
      handleDisconnect();                         // lost due to either server restart, or a
     else                                       // connnection idle timeout (the wait_timeout
      throw err;                                  // server variable configures this)
    
  );


handleDisconnect();

【讨论】:

以上是关于关闭 MySQL 后 Node.js 进程无法恢复,然后再打开的主要内容,如果未能解决你的问题,请参考以下文章

node.js项目通过pm2以守护进程方式运行

Web 进程在启动 node.js 后 60 秒内无法绑定到 $PORT

在node js程序中传递函数后无法获得输出? [关闭]

Node.js 和 Heroku 错误:Web 进程在启动后 60 秒内无法绑定到 $PORT

如何关闭 node.js 中子进程的 stdio 管道?

Heroku Node.js 错误 R10(启动超时)-> Web 进程在启动后 60 秒内无法绑定到 $PORT