몇 일 전, 개발환경에 구축되어있는 백엔드 시스템의 커넥션풀을 변경해야하는 일이 생겨 기존 Tomcat 커넥션풀 (tomcat-dbcp)에서 HikariCP로 변경하였습니다. 변경하면서 기존 설정되어있던 수치들을 HikariCP에서 제공하는 옵션에 맞추어 마이그레이션 했는데요. 완료 후 특별한 문제점은 보이지 않았습니다. 하지만 다음 날 출근 후…. 해당 시스템의 API를 호출하자 갑자기 아래와 같은 오류 메시지가 나오며 시스템이 정상적으로 동작하지 않는 상태인 것이 확인되었습니다.
1 |
|
원인
리서치를 해본 결과 핵심은 기존 사용하던 tomcat-dbcp와 HikariCP의 철학이 달라서 생긴 문제였습니다. 현재 백엔드 시스템은 MySQL을 사용중인데요. MySQL은 맺어진 커넥션이 장시간 사용되지 않으면 해당 커넥션을 해제하도록 설계되어있습니다. (기본 8시간)
tomcat-jdbc
test-while-idle
설정이 true
로 되어있으면 IDLE 상태의 커넥션들을 대상으로 DB서버에 SELECT 1을 주기적으로 보냅니다.
이를 통해 커넥션이 지속적으로 갱신되고 서버로부터 disconnect되지 않습니다.
1 |
|
HikariCP
공식 문서: https://github.com/brettwooldridge/HikariCP
참고로 Spring Boot 2.0을 기점으로 기본 DBCP가 Tomcat DBCP에서 HikariCP로 바뀌었습니다.
HikariCP는 tomcat-dbcp와 달리 사용하지 않는 Connection을 회수하도록 설계되었습니다.
maxLifeTime
으로 설정된 시간이 지나면 풀에서 제거되고, 다시 생성되는 방이며 connectionTestQuery
는 커넥션을 최초 맺을때, 풀에서 가져올 때 사용되는 옵션이라고 합니다.
또한 JDBC4를 지원하는 환경에서는 connectionTestQuery
를 명시하지 않는것을 권고하고 있습니다.
1 |
|
HikariCP 내부 JDBC 구현체에서는 아래와 같이 JDBC4에 대한 구현을 하고 있습니다.
1 |
|
대처
우선은 maxLifeTime
값을 설정하고, connectionTestQuery
설정을 제거한 후 모니터링을 해보고자 합니다.
실제 운영환경에서는 발생하지 않았을 오류이지만, 오히려 개발환경인 덕에 발생하고, HikariCP에 대해 상세하게 리서치해 볼 수 있는 기회였습니다. 문제가 해결되면 해결된 글로 다시 작성해야겠습니다.