왜 TCP 재전송이 지연의 주범이 되는가

애플리케이션 로그상 정상인데 특정 요청만 수백 ms에서 수 초까지 튀는 경우, 상당수는 TCP 재전송에서 비롯된다. 패킷이 유실되면 송신 측은 ACK를 기다리다 RTO(Retransmission Timeout)가 만료된 뒤 다시 보낸다. 리눅스의 최소 RTO는 200ms로 고정되어 있어, 단 한 번의 유실만으로도 요청 지연이 최소 200ms 늘어난다. 빠른 재전송(fast retransmit)은 중복 ACK 3개로 트리거되므로 상대적으로 저렴하지만, RTO 기반 재전송은 혼잡 윈도우를 1로 되돌려 이후 처리량까지 떨어뜨린다.

먼저 재전송이 실제로 일어나는지 확인

추측하지 말고 커널 카운터부터 본다. nstat은 마지막 조회 이후 증분을 보여줘 특정 부하 구간을 격리하기 좋다.

nstat -az | grep -E 'TcpRetransSegs|TcpExtTCPLostRetransmit|TcpExtTCPTimeouts|TcpExtTCPSlowStartRetrans'

# 재전송 비율 개략 계산
awk '/TcpOutSegs/{o=$2} /TcpRetransSegs/{r=$2} END{printf "retrans %.3f%%\n", r/o*100}' /proc/net/snmp

재전송 비율이 0.1%를 넘고 TCPTimeouts가 함께 증가한다면 RTO 재전송이 지연에 직접 기여하고 있다는 신호다.

연결 단위로 RTT와 재전송 짚어내기

전체 카운터로 방향을 잡았으면 ss로 개별 소켓을 본다. retrans, rto, rtt 필드가 핵심이다.

# 재전송이 있는 established 소켓만 추림
ss -tino state established | \
  grep -E 'retrans|rto' | \
  awk '{print}' | head -20

# 예시 출력 해석
# rtt:1.2/0.6 rto:204 retrans:0/3  ->  누적 3회 재전송, rto 204ms
# rtt:180/90  rto:600 ...          ->  RTT 자체가 높아 rto가 커진 상태

rto가 최소값(약 204ms) 근처인데 retrans가 쌓인다면 저지연 경로에서의 유실이고, rtt가 커서 rto가 늘어난 경우는 경로 지연 자체가 문제다. 둘의 처방이 다르므로 반드시 구분한다.

유실 지점을 패킷 레벨로 좁히기

어느 홉에서 유실되는지 애매하면 캡처로 확인한다. 재전송 패킷만 필터링하면 노이즈가 줄어든다.

tcpdump -ni eth0 'tcp[tcpflags] & (tcp-syn|tcp-fin) == 0' -w /tmp/cap.pcap

# tshark로 재전송/타임아웃 이벤트만 추출
tshark -r /tmp/cap.pcap -Y 'tcp.analysis.retransmission || tcp.analysis.rto' \
  -T fields -e frame.time_relative -e ip.dst -e tcp.analysis.rto

재전송이 특정 대상 IP나 특정 시간대에 몰린다면 네트워크 경로·미들박스·상대 서버 큐를 의심한다. 반대로 전 대상에 고르게 퍼져 있으면 로컬 NIC 링·큐 드롭 가능성이 크다. ethtool -S eth0 | grep -i drop로 하드웨어 드롭을 함께 확인한다.

원인별 대응과 트레이드오프

증상주 원인대응
rto 최소값 + retrans 누적경로/큐 유실큐 튜닝, ECN, 경로 점검
rtt 높고 rto 큼물리적 지연지역 배치, keepalive 조정
SlowStartRetrans 급증버퍼 부족/버스트혼잡제어(BBR) 검토

혼잡제어 알고리즘 변경은 유실 기반 CUBIC보다 지연·대역 추정 기반 BBR이 유실 많은 경로에서 유리할 수 있다. 다만 공용망에서 BBR은 공정성 논란이 있으니 폐쇄망 위주로 적용한다.

# 확인 후 적용 (재부팅 유지는 sysctl.d에 기록)
sysctl net.ipv4.tcp_available_congestion_control
sysctl -w net.ipv4.tcp_congestion_control=bbr
# 링 버퍼 드롭이 잦으면
ethtool -G eth0 rx 4096 tx 4096

주의점

재전송 비율 0%를 목표로 삼지 않는다. TCP는 적당한 유실을 전제로 혼잡을 제어하므로, 무리한 버퍼 확대는 bufferbloat로 오히려 지연을 키운다. 최소 RTO를 낮추는 ip route ... rto_min 조정은 데이터센터 내부처럼 RTT가 안정적인 환경에서만 쓴다. 인터넷 경로에 적용하면 조기 재전송으로 불필요한 트래픽만 늘어난다. 또한 카운터는 커널 부팅 이후 누적값이므로, 반드시 nstat 증분이나 시계열 수집으로 부하 구간과 상관관계를 확인한 뒤 조치한다.