서버에 부하 테스트를 진행하면서 pm2의 cluster모드를 통해 여러개의 코어를 사용하게 해놓았는데 그 과정에서 DB와 통신하는 과정에서 PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR
오류가 계속 발생하였다.
에러 로그를 분석해보면 쿼리를 실행하기 전에 FATAL한 에러가 발생하여 작업을 할 수 없다는 것이었다.
인터넷 검색을 해보았더니 여러 글이 나왔지만 모두 정확한 이유를 알고 있지 않았고 해결 방법도 되는 경우가 있고 없는 경우가 있었다.
필자와 같은 경우는 평소에는 이상이 없다가 많은 요청이 들어올 때 오류가 발생하는 특징이 있었다.
내가 생각했던 이유는 connection
을 받아오는 과정에서 요청을 수행한 후 release
가 되지 않던가 동시에 요청을 보내 동시에 connection
을 받아올 수 없는 이유인가로 줄이고 생각해보았다.
그 과정에서 DB와의 통신과정을 알게 되었고 pool과 connection의 차이에 대해 알게 되었다.
mysql.createConnection() -> connection.connect() -> connection.query() -> connection.end()
클라이언트측에서 데이터베이스에 접속해서 질의를 수행한 후, 결과를 받고 접속을 종료하는 일련의 과정이 Connection
으로 데이터베이스에 연결되는 과정이다.
사용자의 요청에 따라 Connection
을 생성하다 보면 많은 수의 연결이 발생했을 때 서버에 과부하가 걸리게 된다.
이러한 상황을 방지하기 위해 미리 일정수의 Connection
을 만들어 Pool
에 담아뒀다가 사용자의 요청이 발생하면 연결을 해주고 연결 종료 시 Pool
에 다시 반환하여 보관하는 것이 바로 Connection Pool
이다.
이러한 Connection Pool
은 Connection
을 미리 생성해두고 관리함으로써 데이터베이스에 과부하를 방지하고 유동적으로 Connection
을 관리할 수 있다는 장점이 있다.
나한테 발생했던 이유는 MySQL과 같은 무료 RDBMS에서는 connection
을 자동으로 release
해주지 않아 문제가 발생한 것이다.
이 문제를 해결하기 위해 앞으로 MySQL을 사용할때는 pool
에서 connection
을 받아와서 사용하고 release
해줘야 할 것이다.
아래와 같이 query
함수를 만들면 기존에 쓰던 코드를 수정할 필요 없이 바로 사용할 수 있다.
var pool = mysql.createPool({ // createConnection이 아닌 createPool
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
port: process.env.DB_PORT,
});
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]; // 마지막 인자로 callback을 받아온다.
pool.getConnection(function(err, connection) { // pool에서 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(); // 마지막 쿼리를 진행한 후에 connection을 release해준다.
if(err){
console.log(err);
return callback(err);
}
callback(null, results);
});
});
}
};
출처:
https://cotak.tistory.com/105 [TaxFree:티스토리]
https://stackoverflow.com/questions/17015590/node-js-mysql-needing-persistent-connection