connection pool 고갈 문제를 layered defence를 이용해 해결할 수 있다.
·수정 2026.05.26·수정 6회
요약
- 단순히 connection pool을 늘리는 것만으로 성능이 쉽게 해결되지 않음
- 아래 layered defence들을 통해 해결 가능함
본문
- connection pool 고갈 문제는 [다양한 시나리오](느린 connection pool circulation으로 인한 3가지 실패 시나리오)를 통해 어플리케이션 성능을 악화시킬 수 있음
- 아래 layered 된 defence들을 통해 해결 가능함
1. pool_size
- 일반적인 팀들은 pool을 너무 작게 관리함
- db를 위한 pool 사이즈의 a rule of thumb은 아래와 같음
pool_size = (core_count * 2) + effective_spindle_count
- effective_spindle_count가 뭐지?
2. Connection Timouts
- acquire과 use 모두에 connection timeout을 더 공격적으로 잡아라
- 만약 쿼리가 예상보다 10배 길게 사용한다면 빠르게 실패하게 해서 release connection 하는게 낫다
3. Bounded Queues
- 요청들이 불명확하게 connection을 기다리게 하지마세요
- maximum queue depth를 설정해서 가득 차면 새로운 요청을 거절하도록 구현하세요
- 이건 cacading retries를 막을 겁니다.
4. Circuit Braker
- 만약 connection acquisitiion 실패가 증가한다면 서킷브레이커를 활성화 시켜 새 요청 전체를 막으세요
- 이건 시스템이 이미 부서졌을때 더 부하가 높아지는 것을 막습니다.
5. Observability
- 모든 커넥션 life cycle event를 기록하세요
- acquire, releae, timeout, error
- exhaustion이 도달 하면 forensic 데이터가 필요할 겁니다.
6. Bulkhead (격리)
-
pool을 하나로 공유하지 말고 의존 대상별로 쪼개라 — 한 의존 대상의 stall이 다른 호출을 굶기는 head-of-line blocking을 막는다
-
HTTP 클라이언트에서는 origin별 connection pool로 자연스럽게 구현됨 → origin별 connection pool은 HTTP 클라이언트의 Bulkhead 패턴 구현이다
-
trade-off: 격리된 pool은 다른 origin이 비어 있어도 빌려쓸 수 없어 자원 활용률이 떨어짐
-
구현 팁
- 항상 try-finally 또는 언어 친화적으로 connection을 반환할 수 있도록 보장해라
- single exception finally block을 지나지 않는 요청들이 permanent limbo를 만듦
- explicitly하게 반환하는 로직 없이 async 경계를 지나면서 connection을 hold하지마라
- end to end까지 요청의 deadline을 지정해라
- 추측하지말고 모니터링 해라
- Exhaustion은 nomal looking metric 뒤에 있다.
참고
- HTTP fan-out 동시성 캡은 TCP 연결 풀로 걸어야 ephemeral port가 안 터진다 — pool_size 캡을 in-flight Promise로 흉내내면 TIME_WAIT으로 ephemeral port 고갈이 누적되는 fan-out 관점