programing

Node.js MySQL 영구 연결 필요

iphone6s 2023. 10. 24. 20:14
반응형

Node.js MySQL 영구 연결 필요

노드 웹 앱을 위한 지속적인 MySQL 연결이 필요합니다.문제는 이런 일이 하루에 몇 번씩 일어난다는 것입니다.

Error: Connection lost: The server closed the connection.
at Protocol.end (/var/www/n/node_modules/mysql/lib/protocol/Protocol.js:73:13)
at Socket.onend (stream.js:79:10)
at Socket.EventEmitter.emit (events.js:117:20)
at _stream_readable.js:895:16
at process._tickCallback (node.js:415:13)
error: Forever detected script exited with code: 8
error: Forever restarting script for 2 time
info: socket.io started

내 연결 코드는 다음과 같습니다.

// Yes I know multipleStatements can be dangerous in the wrong hands.
var sql = mysql.createConnection({
    host: 'localhost',
    user: 'my_username',
    password: 'my_password',
    database: 'my_database',
    multipleStatements: true
});

sql.connect();

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);
        sql = mysql.createConnection(connection.config);
        handleDisconnect(sql);
        sql.connect();
    });
}

handleDisconnect(sql);

보시다시피 핸들 Disconnect 코드가 작동하지 않습니다.

mysql 연결 풀을 사용합니다.연결이 끊어지면 다시 연결되며 동시에 여러 sql 쿼리를 만들 수 있는 추가적인 이점을 얻을 수 있습니다.데이터베이스 풀을 사용하지 않으면 현재 실행 중인 데이터베이스 요청이 완료되기를 기다리는 동안 앱이 데이터베이스 요청을 차단합니다.

저는 보통 질의를 경로와 분리하여 보관하는 데이터베이스 모듈을 정의합니다.이렇게 생겼네요...

var mysql = require('mysql');
var pool  = mysql.createPool({
  host     : 'example.org',
  user     : 'bob',
  password : 'secret'
});

exports.getUsers = function(callback) {
  pool.getConnection(function(err, connection) {
    if(err) { 
      console.log(err); 
      callback(true); 
      return; 
    }
    var sql = "SELECT id,name FROM users";
    connection.query(sql, [], function(err, results) {
      connection.release(); // always put connection back in pool after last query
      if(err) { 
        console.log(err); 
        callback(true); 
        return; 
      }
      callback(false, results);
    });
  });
});

이것이 엄청나게 지연되는 것은 알지만, 좀 더 일반적이고 사용하기 쉬운 해결책을 써 보았습니다.나는 완전히 의존하는 앱을 작성했습니다.connection.query()수영장으로 갈아타면 그런 전화들이 끊겼습니다

제 해결책은 이렇습니다.

var mysql = require('mysql');

var pool = mysql.createPool({
    host     : 'localhost',
    user     : 'user',
    password : 'secret',
    database : 'test',
    port     : 3306
});

module.exports = {
    query: function(){
        var sql_args = [];
        var args = [];
        for(var i=0; i<arguments.length; i++){
            args.push(arguments[i]);
        }
        var callback = args[args.length-1]; //last arg is callback
        pool.getConnection(function(err, connection) {
        if(err) {
                console.log(err);
                return callback(err);
            }
            if(args.length > 2){
                sql_args = args[1];
            }
        connection.query(args[0], sql_args, function(err, results) {
          connection.release(); // always put connection back in pool after last query
          if(err){
                    console.log(err);
                    return callback(err);
                }
          callback(null, results);
        });
      });
    }
};

풀을 한 번 인스턴스화한 다음 이름이 지정된 메서드를 내보냅니다.query. 지금, 언제connection.query()는 아무 곳에서나 호출되며, 이 메서드는 먼저 풀에서 연결을 잡은 다음 인수를 연결로 전달합니다.콜백을 먼저 잡는 부가적인 효과가 있어 풀에서 연결을 잡을 때 발생하는 오류를 콜백할 수 있습니다.

이것을 사용하기 위해서는 mysql 대신 모듈로 필요합니다.예:

var connection = require('../middleware/db');

function get_active_sessions(){
  connection.query('Select * from `sessions` where `Active`=1 and Expires>?;', [~~(new Date()/1000)], function(err, results){
    if(err){
      console.log(err);
    }
    else{
      console.log(results);
    }
  });
}

이것은 일반 쿼리와 똑같이 보이지만 실제로는 풀을 열고 백그라운드의 풀에서 연결을 가져옵니다.

@gladsocc 질문에 대한 답변:

모든 것을 리팩토링하지 않고 수영장을 사용할 수 있는 방법이 있습니까?저는 앱에 수십 개의 SQL 쿼리가 있습니다.

이것이 바로 제가 만든 것입니다.쿼리 기능을 위한 포장지입니다.연결을 잡고 쿼리를 수행한 다음 연결을 해제합니다.

var pool = mysql.createPool(config.db);

exports.connection = {
    query: function () {
        var queryArgs = Array.prototype.slice.call(arguments),
            events = [],
            eventNameIndex = {};

        pool.getConnection(function (err, conn) {
            if (err) {
                if (eventNameIndex.error) {
                    eventNameIndex.error();
                }
            }
            if (conn) { 
                var q = conn.query.apply(conn, queryArgs);
                q.on('end', function () {
                    conn.release();
                });

                events.forEach(function (args) {
                    q.on.apply(q, args);
                });
            }
        });

        return {
            on: function (eventName, callback) {
                events.push(Array.prototype.slice.call(arguments));
                eventNameIndex[eventName] = callback;
                return this;
            }
        };
    }
};

그리고 평소처럼 사용합니다.

db.connection.query("SELECT * FROM `table` WHERE `id` = ? ", row_id)
          .on('result', function (row) {
            setData(row);
          })
          .on('error', function (err) {
            callback({error: true, err: err});
          });

언급URL : https://stackoverflow.com/questions/17015590/node-js-mysql-needing-persistent-connection

반응형