home

Lambda의 rds 커넥션 풀 고갈 문제

Lambda로 RDS를 붙여 쓰다 보면 커넥션이 순식간에 고갈되는 상황을 마주치게 됩니다. 왜 그런지, 어떻게 해결하는지 정리해봤습니다.

왜 문제가 생기나

Lambda는 요청마다 별도 실행 환경이 뜰 수 있어서, 요청이 100개면 Lambda도 100개가 동시에 뜨고 커넥션도 100개가 생깁니다. RDS는 커넥션 수에 한계가 있으니 금방 터집니다.

해결 방법들

SQS batchSize로 Lambda 수 줄이기

SQS 없이:
요청 100개 → Lambda 100개 동시 실행 → 커넥션 100개

SQS + batchSize=10:
요청 100개 → SQS → Lambda 10개 실행 (각각 메시지 10개 처리) → 커넥션 10개

여기에 reservedConcurrency까지 걸면 더 줄일 수 있습니다.

SQS + batchSize=10 + reservedConcurrency=5:
요청 100개 → SQS → Lambda 최대 5개 실행 → 커넥션 최대 5개
나머지 메시지는 SQS에서 대기

근데 이게 완전한 해결은 아닙니다. Cold Start마다 새 커넥션이 생기고, Warm 인스턴스가 여러 개면 각각 커넥션을 들고 있습니다. 동시성을 너무 조이면 처리 지연도 생깁니다.

근본 해결은~? RDS Proxy

RDS Proxy는 커넥션 풀링 + 멀티플렉싱으로 이 문제를 제대로 해결합니다.

기존:
Lambda A → 커넥션 1 → RDS
Lambda B → 커넥션 2 → RDS
Lambda C → 커넥션 3 → RDS

RDS Proxy:
Lambda A ─┐
Lambda B ─┼→ RDS Proxy (커넥션 풀) → 커넥션 소수만 유지 → RDS
Lambda C ─┘

멀티플렉싱이 핵심인데, Lambda가 쿼리를 날리는 순간에만 커넥션을 빌려주고 쿼리가 끝나면 바로 풀에 반환합니다. 그래서 여러 Lambda가 소수의 커넥션을 시분할로 공유할 수 있습니다.

그냥 HikariCP 쓰면 안 되나요?

ECS나 EC2 같은 일반 서버는 프로세스가 계속 살아있으니 자체 커넥션 풀로 충분합니다. 근데 Lambda는 호출마다 실행 환경이 달라질 수 있어서 프로세스 간 커넥션 공유가 불가능합니다. Warm 상태라도 인스턴스마다 각자 커넥션을 들고 있을 뿐입니다. 그래서 RDS Proxy가 필요합니다.

비용은?

vCPU당 시간당 $0.015 (서울 리전 기준)

db.t3.medium 기준이면 2 × $0.015 × 24 × 30 = 약 $21.6/월 정도입니다. RDS 인스턴스 비용에 추가로 붙는 거라 작은 인스턴스면 크게 부담스럽지 않습니다.