Connection Pool Timeout 장애 전파

3줄 요약

  • DB 커넥션은 비싼 자원이므로 웹 애플리케이션은 보통 커넥션 풀로 재사용한다.
  • 커넥션 풀은 성능 장치이면서 동시에 장애 격리 장치다. 설정을 잘못하면 느린 쿼리 하나가 전체 API 장애로 번진다.
  • Timeout은 client, gateway, application, pool, database 계층이 서로 맞물리도록 설계해야 하며, 단순히 길게 늘리는 것은 해결책이 아니다.

핵심 정리

  • 커넥션은 TCP 연결, 인증, 세션 상태, DB 프로세스 또는 스레드 자원을 사용한다. 요청마다 새로 만들면 CPU와 메모리 비용이 크다.
  • HikariCP 같은 풀은 제한된 커넥션을 빌려주고 반납받는다. 풀 크기는 애플리케이션 스레드 수가 아니라 DB가 감당할 동시 작업 수와 맞춰야 한다.
  • maximumPoolSize를 키우면 대기 요청은 줄어 보일 수 있지만 DB 동시 부하가 늘어 전체 지연이 더 커질 수 있다.
  • connectionTimeout은 풀에서 커넥션을 기다릴 최대 시간이다. 이 값이 너무 길면 요청 스레드가 오래 묶이고 장애가 늦게 드러난다.
  • DB 쿼리 timeout, transaction timeout, HTTP timeout, gateway timeout이 서로 어긋나면 이미 클라이언트는 포기했는데 DB는 계속 일하는 상황이 생긴다.
  • RDS Proxy, Cloud SQL Managed Connection Pooling 같은 관리형 풀은 연결 폭주 흡수에 도움이 되지만, 애플리케이션 풀과 DB 한계를 이해하지 못하면 또 다른 병목이 된다.
  • 커넥션 풀 장애는 단독 지표로 판단하지 않는다. Hikari active/idle/pending, acquire time, slow query, lock wait, DB active session, API p95/p99를 같은 타임라인에 놓고 본다.
  • batch, admin, API가 같은 pool을 공유하면 비핵심 작업 하나가 사용자 API를 막을 수 있다. 중요한 서비스는 workload별 pool, read replica, rate limit, job queue를 분리할지 검토한다.

헷갈리는 지점

  • 커넥션 풀이 크면 클수록 처리량이 늘어난다고 생각하기 쉽다. 대기 요청을 줄이는 것처럼 보이기 때문이다.
    • 핵심은 DB가 동시에 처리할 수 있는 쿼리 수에 한계가 있다는 점이다.
    • 풀 크기는 DB CPU, I/O, 쿼리 평균 시간, 인스턴스 수를 함께 보고 정한다.
  • Timeout 오류는 시간이 부족하니 늘리면 된다고 판단하기 쉽다. 에러 메시지가 timeout이기 때문이다.
    • 핵심은 timeout이 병목을 알려주는 보호 장치일 수 있다는 점이다.
    • 원인이 느린 쿼리, 락 대기, 풀 고갈, 네트워크인지 먼저 구분한다.
  • RDS Proxy 같은 프록시를 붙이면 애플리케이션 풀 설정을 몰라도 된다고 오해하기 쉽다.
    • 핵심은 프록시도 DB 앞의 제한된 연결 자원을 관리할 뿐이라는 점이다.
    • 앱 풀, 프록시 풀, DB max connections를 함께 맞춰야 한다.
  • connection timeout 로그만 보고 DB가 죽었다고 단정하기 쉽다. 에러 메시지가 DB 연결 실패처럼 보이기 때문이다.
    • 핵심은 풀에서 커넥션을 못 빌린 것이며 원인은 느린 쿼리, lock wait, 긴 트랜잭션, 누수, pool 과소 설정 등 다양하다는 점이다.
    • 로그에는 endpoint, trace id, pool 지표, SQL fingerprint, lock wait 여부가 함께 있어야 한다.

확인 질문

  • 커넥션 풀 고갈이 발생했을 때 가장 먼저 볼 지표는 무엇인가?
    • active/idle connection 수, pending acquire 수, connection acquire time, slow query, lock wait, DB active session, API 응답 시간이다.
  • maximumPoolSize를 무작정 늘리면 위험한 이유는 무엇인가?
    • DB로 들어가는 동시 쿼리 수가 늘어 CPU, I/O, 락 경합이 심해지고 전체 장애가 커질 수 있기 때문이다.
  • Timeout 계층을 맞춘다는 것은 무엇인가?
    • HTTP 요청, 애플리케이션 작업, 트랜잭션, 쿼리, 커넥션 대기 시간이 서로 모순되지 않도록 실패 순서와 제한 시간을 설계하는 것이다.
  • batch와 사용자 API가 같은 pool을 쓸 때 생길 수 있는 문제는 무엇인가?
    • batch가 커넥션을 오래 점유하면 사용자 API가 커넥션을 얻지 못해, 직접 관련 없는 기능까지 timeout과 p99 지연을 겪을 수 있다.