Programming/Node.js

Connection Pool 사용 시 release() 코드 위치의 중요성

고고마코드 2023. 9. 22. 14:17
반응형

관리하고 있는 채팅 시스템이 있는데 데이터베이스 연결 시 Connection Pool을 사용하고 있습니다.
코드는 커넥션을 얻고, 데이터베이스 결과값을 가져온 후에 다시 커넥션을 반환하는 과정으로 작성되어 있습니다.

커넥션 반환 문제

그러던 중 커넥션 풀을 사용할 때 문제가 생겼습니다.
커넥션이 계속 증가하고 있었는데, 그러다보니 커넥션 수 제한에 걸려서 서버 오류가 발생하기도 했습니다.

이 문제를 해결하기 위해 pool 생성할 때 connectionLimit을 크게 올려보기도 했지만 채팅 서버에서는 오류가 나지 않지만, DB서버 과부하로 처리가 매우 느려졌습니다.
마찬가지로 max_connections, wait_timeout 도 변경했지만 사용량이 많을 때는 속도가 상당히 떨어졌습니다.

그래서 이런 환경에 문제가 있는 것이 아니라 소스에 문제가 있다는 것을 깨닫고 코드를 다시 확인했습니다.
예시 코드입니다. nodeJS

기존 코드

exports.select = function(callback) {
    db.pool.getConnection((err, conn) => {
        if (err) callback(err);
        else {
            let sql = '';
            conn.query(sql, [], (err, rows) => {
                if (err) callback(err);
                else {
                    callback(null, rows);
                }

                conn.release();
            });
        }
    });
};
  1. 커넥션 얻기
  2. 데이터베이스 결과 처리
  3. 커넥션 반환
    보기엔 큰 문제가 없어보였습니다.

그러나 callback 함수 부분에서 오류가 발생할 경우 conn.release() 를 수행하지 않기에 커넥션이 제대로 반환이 되고 있지 않을 수 있겠다는 생각을 했죠.

그래서 try ~ finally 를 추가해 해결하려고 했습니다.

수정 코드 (try ~ finally)

exports.select = function(callback) {
    db.pool.getConnection((err, conn) => {
        if (err) callback(err);
        else {
            try {
                let sql = '';
                conn.query(sql, [], (err, rows) => {
                    if (err) callback(err);
                    else {
                        callback(null, rows);
                    }
                });
            } finally {
                conn.release();
            }
        }
    });
};

생각해보니 Connection.query는 비동기 함수라서 쿼리 수행시간이 길면 쿼리가 완료되기 전에 커넥션이 반환될 위험이 있었습니다.
그래서 conn.query 내부에서 반환을 해야 되고, 공식문서를 보니 conn.query 내부 첫 줄에서 반환을 하고 있더라구요.

수정 코드 (결론)

exports.select = function(callback) {
    db.pool.getConnection((err, conn) => {
        if (err) callback(err);
        else {
            let sql = '';
            conn.query(sql, [], (err, rows) => {
                conn.release();

                if (err) callback(err);
                else {
                    callback(null, rows);
                }
            });
        }
    });
};

이렇게 수정했더니 과하게 생성되었던 커넥션은 깔끔하게 해결되었습니다.

단순히 반환 부분을 아래에서 위로 올렸을 뿐인데 골치 아팠던 문제를 해결했습니다.
코드 한 줄도 꼼꼼하게 작성하는 것이 중요하다는 것을 느꼈습니다.

반응형