Linux TCP TIME_WAIT 및 CLOSE_WAIT 상태 분석과 해결 방안
핵심 내용
TIME_WAIT은 커널 소스에 60초로 하드코딩되어 tcp_fin_timeout으로 변경할 수 없으며, CLOSE_WAIT은 로컬 애플리케이션의 명시적 close() 호출이 필요하다.
자세히 보기
CLOSE_WAIT 누적과 서버 행업
트래픽이 높은 웹서비스에서 CLOSE_WAIT 상태가 누적되면 서버가 행업(hang)되는 현상이 발생한다. 이는 커널 옵션이나 타임아웃 설정으로 해결할 수 없으며, 로컬 애플리케이션의 명시적인 close() 호출이 필요하다. 원인은 Passive Close 측이 close()를 호출하지 않아 Active Close 측이 FIN을 보내지 못해 CLOSE_WAIT에 머무는 것이다. 해결책으로는 상호 의존성을 제거하기 위해 별도 서버(예: nginx)로 분리하거나 애플리케이션 로직을 수정하여 정상적인 종료 프로세스를 보장해야 한다.
TIME_WAIT의 원리와 오해 바로잡기
TIME_WAIT은 Active Close 측이 최종적으로 남는 상태로, 2*MSL(최대 세그먼트 수명) 동안 유지된다. 이는 지연 패킷으로 인한 데이터 무결성 문제를 방지하고, 마지막 ACK 유실 시 연결 실패를 막기 위해 필수적이다. RFC 793 기준 2 MSL이지만, CentOS 6 등에서는 60초로 고정된다.
많은 인터넷 문서와 달리 net.ipv4.tcp_fin_timeout은 TIME_WAIT 타임아웃을 변경하지 않는다. 리눅스 커널 소스(include/net/tcp.h)에서 TCP_TIMEWAIT_LEN이 (60*HZ)로 하드코딩되어 변경이 불가능함을 확인했다.
커널 동작 및 설정 권장 사항
TIME_WAIT 상태의 소켓은 프로세스 종료 후에도 60초간 포트를 점유하여 bind() 실패를 유발할 수 있다. 하지만 64비트 시스템 등 현대 환경에서는 메모리 부담이 크지 않다. 서버-서버 접속 시 클라이언트 로컬 포트 고갈 방지를 위해 net.ipv4.tcp_tw_reuse 활용을 고려할 수 있으나, NAT 환경에서는 주의가 필요하다.
net.ipv4.tcp_fin_timeout은 FIN_WAIT2 단계의 타임아웃을 조절하는 값으로, 90 정도로 설정하는 것을 추천한다. FIN_WAIT1 상태가 지속되면 상대방의 응답 문제이므로 OS 차원의 재시도 로직을 확인해야 한다.
이 한국어 요약은 AI가 자동으로 만들었습니다. 원문의 주장과 맥락은 원문에서 확인해 주세요. 저작권은 원저작자에게 있습니다.