게임 렉 백서 › L7 서버 OS (커널)
서버 간 연결의 임시 포트 고갈 Ephemeral port exhaustion (TIME_WAIT)
원인 ID so-ports · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라
그림과 실험이 있는 원본 카드로 열기 →
게임 서버가 DB나 다른 서버에 연결을 짧게 자주 맺고 끊으면, 끊긴 연결이 한동안 포트를 점유해 새 연결을 못 엽니다.
왜 요청마다 새 연결을 열고 닫음 → 그러면 먼저 닫은 쪽이 약 60초(리눅스) 동안 포트를 점유해(TIME_WAIT) 쓸 포트가 바닥 → 화면에서는 내부 요청 실패로 저장 실패·기능 오류
- 증상
- 씹힘·롤백, 접속 불가·무한 로딩
- 요인
- 손실
- 누가 겪나
- 서버 전체, 특정 기능만
- 언제
- 사람이 몰릴 때
- 담당
- 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라
- 게임개발팀 할 일
- 연결 재사용(커넥션 풀), 요청마다 연결을 새로 열고 닫지 않게.
- 인프라팀 할 일
- 포트 범위 확장(ip_local_port_range), 나가는 연결의 TIME_WAIT 재사용(리눅스 tcp_tw_reuse) 검토, TIME_WAIT 수 감시.
- 수치 감각
- 리눅스 기본 포트 범위(32768~60999)는 약 2만 8천 개. 같은 상대 주소로 1초에 470번 넘게 새로 연결하면 바닥납니다. 윈도우는 기본 포트가 약 1만 6천 개(49152~65535)이고 TIME_WAIT도 더 길어 더 빨리 바닥납니다.
- 그래프에서는
- 한도에 닿아 평평해짐 · TIME_WAIT 소켓 수, 내부 연결 실패 수
- 확인할 곳
- ss -tan state time-wait로 TIME_WAIT 소켓을 상대 주소별로 세고, 게임 서버 로그에서 connect 실패(EADDRNOTAVAIL)를 찾음
- 이러면 맞음
- 같은 상대(DB 등)로 가는 TIME_WAIT가 임시 포트 범위(기본 약 2만 8천 개) 근처에서 평평해지고, connect가 EADDRNOTAVAIL로 실패함
- 이러면 아님
- TIME_WAIT가 적은데 외부로 나가는 연결만 실패하면 “클라우드 NAT 게이트웨이 연결·포트 한도”
- 확인 수단
- 인프라 도구로 확인(게임 코드 불필요)
- 더 알아보기
- 리눅스의 TIME_WAIT 60초는 커널에 고정된 값입니다. 이름이 비슷한 tcp_fin_timeout을 줄여도 TIME_WAIT는 짧아지지 않습니다.
출처
- IP Sysctl Linux kernel
ip_local_port_range 기본 32768~60999, tcp_tw_reuse, tcp_fin_timeout은 FIN_WAIT_2 상태 유지 시간 - include/net/tcp.h (Linux v6.12) Linux kernel
TCP_TIMEWAIT_LEN(60*HZ): TIME_WAIT 약 60초는 커널 상수 - TCP/IP port exhaustion troubleshooting Microsoft
윈도우 동적 포트 기본 49152~65535, 닫힌 연결은 기본 4분 동안 TIME_WAIT로 포트를 잡고 있음 - ss(8) — Linux manual page iproute2
상태 필터 state time-wait로 TIME_WAIT 소켓만 골라 봄 - connect(2) — Linux manual page Linux man-pages
EADDRNOTAVAIL: 임시 포트 범위의 포트가 모두 쓰이는 중이라 연결을 열지 못함
함께 보면 좋은 원인
같은 층: L7 서버 OS (커널)
같은 증상(씹힘·롤백)의 다른 층 원인
그림과 실험이 있는 원본 카드 보기