피드로 돌아가기
Dev.toBackend
원문 읽기
Context leak 해결로 메모리 47GB에서 400MB로 급감 및 p99 80ms 복구
50,000 Goroutines Took Down Prod at 3 AM. The Fix Is One Line
AI 요약
Context
WebSocket 기반 알림 서비스에서 클라이언트 연결 종료 시 Context Cancel 함수가 호출되지 않는 구조적 결함 존재. 이로 인해 종료되지 않은 Goroutine과 연관 리소스가 메모리에 누적되는 Memory Leak 발생.
Technical Solution
context.WithCancel로 생성한 cancel 함수를Subscription구조체에 캡처하여 관리하는 설계 채택WSHandler내 WebSocket 연결 종료 시defer를 통해Unsubscribe함수를 강제 호출하는 로직 추가Unsubscribe과정에서cancel()실행을 통한pumpEventsGoroutine의ctx.Done()시그널 트리거 및 종료 유도- 서비스 레벨 Map에서 구독 정보를 제거하여 GC가 도달 불가능한 상태로 만들어 메모리 회수 가능 구조 확보
- Goroutine 자체의 경량성보다 해당 루틴이 점유한 buffered channel, user state 등 Closure 리소스의 누적 방지에 집중
실천 포인트
- Prometheus 대시보드에 `go_goroutines` 메트릭을 추가하여 추세선이 평탄하거나 톱니 모양인지 상시 모니터링 - `context.WithCancel` 사용 시 생성 직후 동일 라인에서 `defer cancel()` 호출 습관화 - `goleak` 라이브러리를 CI 파이프라인에 통합하여 동시성 패키지의 리소스 누수 자동 검증 - PR 리뷰 시 "해당 Goroutine을 종료시키는 트리거가 무엇이며, 반드시 실행되는가?"를 핵심 검토 항목으로 설정