한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

게임 렉 백서 › TCP 재전송의 근본 원인

MTU 블랙홀 (큰 패킷만 반복 손실) PMTU black hole

원인 ID rt-mtu · 주 담당 인프라팀·네트워크 인프라 · 함께 인프라팀·서버 인프라, 게임개발팀·서버 개발

그림과 실험이 있는 원본 카드로 열기 →

중간 구간이 받을 수 있는 크기가 작아졌는데 “너무 크다”는 알림(ICMP)이 막히면, 큰 패킷은 몇 번을 다시 보내도 계속 사라집니다.

왜 VPN·터널 구간에서 최대 크기가 줄고 크기 초과 알림은 방화벽에 막힘 → 그러면 보내는 쪽은 이유를 모른 채 같은 큰 패킷을 계속 재전송, RTO는 두 배씩 증가 → 화면에서는 평소엔 멀쩡하다가 인벤토리·사람 많은 곳·입장 로딩처럼 큰 데이터가 오가는 순간 뒤따르는 작은 패킷까지 전부 멈춤, 결국 접속 끊김이나 무한 로딩

증상
멈춤, 접속 끊김, 접속 불가·무한 로딩
요인
손실
누가 겪나
특정 지역·통신사, 나만
언제
특정 행동을 할 때, 접속·점검 직후
담당
주 담당 인프라팀·네트워크 인프라 · 함께 인프라팀·서버 인프라, 게임개발팀·서버 개발
게임개발팀 할 일
서버 쪽에서 직접 낮추려면 소켓의 최대 세그먼트 크기(TCP_MAXSEG) 설정, 게임 코드에서 메시지를 잘게 쪼개는 것만으로는 안 막힘(TCP가 보낼 데이터를 MSS 크기로 다시 묶음).
인프라팀 할 일
네트워크: 경계 장비에서 MSS 조정(clamping), 방화벽·클라우드 네트워크 ACL에서 크기 초과 ICMP(유형 3 코드 4, fragmentation needed) 허용. 서버 장비·OS: 경로 MTU 설정, 서버 방화벽·클라우드 보안 그룹에서도 크기 초과 ICMP가 막히지 않는지 확인, 마지막 안전망으로 리눅스 tcp_mtu_probing=1.
수치 감각
보통 1,500바이트, 터널을 지나면 1,400 안팎. 같은 패킷이 5~6번 재전송되면 멈춤이 10초를 넘습니다.
그래프에서는
일부만 높음 · 연결별 RTO·backoff, 지역·통신사별 끊김 수
확인할 곳
문제 연결의 재전송을 서버 쪽 패킷 캡처나 bcc tcpretrans -s(시퀀스 번호 표시)로 보고, ss -ti로 그 연결의 mss·pmtu·backoff를 봄. 서버에서 그 유저 주소로 작은 ping과 DF를 켠 1,500바이트 ping(ping -M do -s 1472)을 보내 비교함
이러면 맞음
MSS만큼 꽉 찬 패킷이 같은 시퀀스 번호로 간격을 두 배씩 늘리며 계속 재전송되고, 그보다 작은 패킷은 오감. 크기 초과 ICMP(Wireshark 필터 icmp.type == 3 and icmp.code == 4)는 오지 않고, 작은 ping은 응답하는데 큰 DF ping만 응답 없이 사라짐
이러면 아님
작은 패킷도 함께 사라지면 크기와 상관없는 손실(“병목 대기열 넘침”, “경로 변경·ECMP 불량 경로”). 크기 초과 ICMP가 도착하고 ss -ti의 pmtu가 줄어들면 경로 MTU 탐색이 제대로 동작하는 것
확인 수단
인프라 도구로 확인(게임 코드 불필요)
더 알아보기
tcp_mtu_probing=1은 재전송 타임아웃이 몇 초(tcp_retries1=3에 해당) 이어진 뒤에야 블랙홀로 판단하고 MSS를 1,024바이트로 낮춥니다. 그 사이는 멈춤이므로 마지막 안전망으로 두고 미리 막는 MSS 조정이 먼저입니다.

출처

  1. RFC 1191: Path MTU discovery IETF
    경로 MTU 탐색: 너무 큰 패킷은 ICMP “fragmentation needed and DF set”(유형 3 코드 4)로 알림
  2. RFC 2923: TCP Problems with Path MTU Discovery IETF
    ICMP가 막혀 큰 패킷만 계속 사라지는 PMTU 블랙홀 문제
  3. RFC 4821: Packetization Layer Path MTU Discovery IETF
    ICMP 없이 전송 계층이 패킷 크기를 탐색하는 방법(리눅스 tcp_mtu_probing의 바탕)
  4. IP Sysctl Linux kernel
    tcp_mtu_probing: 0 꺼짐, 1 블랙홀이 감지될 때만, 2 항상(시작 MSS는 tcp_base_mss). tcp_retries1 기본 3
  5. net/ipv4/tcp_timer.c Linux kernel
    RTO 재전송이 tcp_retries1만큼 이어지면 블랙홀 감지로 보고 MTU 탐색을 켜 MSS를 낮춤
  6. include/net/tcp.h Linux kernel
    TCP_BASE_MSS = 1,024바이트
  7. RFC 6298: Computing TCP's Retransmission Timer IETF
    재전송 타이머가 만료될 때마다 RTO를 두 배로 늘림
  8. iptables-extensions(8) — Linux manual page netfilter
    TCPMSS --clamp-mss-to-pmtu: ICMP를 막는 구간 때문에 큰 패킷이 멈추는 문제를 SYN의 MSS 조정으로 우회
  9. tcp(7) — Linux manual page Linux man-pages
    TCP_MAXSEG: 나가는 패킷의 최대 세그먼트 크기, 연결 전에 설정하면 상대에게 알리는 MSS도 바뀜
  10. Network maximum transmission unit (MTU) for your EC2 instance AWS
    인터넷 게이트웨이·VPN은 MTU 1,500, PMTUD에는 ICMP 유형 3 코드 4가 필요하고 보안 그룹·네트워크 ACL이 막으면 받지 못함
  11. MTU considerations | Cloud VPN Google Cloud
    Cloud VPN 게이트웨이 MTU 1,460바이트, IPv4 터널의 페이로드 MTU 1,406바이트(터널을 지나면 1,400 안팎)
  12. Demonstrations of tcpretrans, the Linux eBPF/bcc version IO Visor
    재전송마다 한 줄씩 보여 주고 -s는 재전송한 패킷의 시퀀스 번호를 함께 표시
  13. ss(8) — Linux manual page iproute2
    ss -i의 mss, pmtu(경로 MTU), backoff(RTO가 두 배로 늘어난 횟수)
  14. ping(8) — Linux manual page iputils
    -M do는 DF를 켜고 커널이 아는 경로 MTU보다 큰 패킷은 보내지 않음, -s는 데이터 크기(ICMP 헤더 8바이트 별도)
  15. Display Filter Reference: Internet Control Message Protocol Wireshark
    icmp.type·icmp.code 표시 필터

함께 보면 좋은 원인

같은 층: TCP 재전송의 근본 원인

같은 증상(멈춤)의 다른 층 원인

그림과 실험이 있는 원본 카드 보기