TCP 재전송 (Retransmission)
1. RTO (Retransmission Timeout)
종류
| 구분 | 설명 |
|---|---|
| initRTO | 연결 초기, RTT 샘플이 없을 때 사용하는 초기값 (기본 1초) |
| RTO | RTT 샘플 기반으로 동적 계산되는 재전송 타임아웃 |
RTO 계산 (RFC 6298)
RTO = SRTT + 4 × RTTVAR
SRTT : Smoothed RTT (평활 왕복 시간)
RTTVAR : RTT 분산 (변동폭)
- ACK가 돌아올 때마다 SRTT, RTTVAR 갱신 → RTO 재계산
- 최솟값: 200ms (Linux 기본)
- 최댓값: 120초
2. Exponential Backoff (지수적 백오프)
재전송 후에도 ACK가 없으면 RTO를 2배씩 증가시킴
재전송 0회: RTO = 200ms
재전송 1회: RTO = 400ms
재전송 2회: RTO = 800ms
재전송 3회: RTO = 1600ms
...
상한: 120초
이유
네트워크 혼잡이 원인일 가능성이 높기 때문에, 재전송 간격을 지수적으로 늘려 혼잡 악화를 방지
3. 재전송 관련 커널 파라미터
net.ipv4.tcp_syn_retries = 6 # SYN 재전송 횟수 (연결 시도 측, initRTO부터 시작)
net.ipv4.tcp_synack_retries = 5 # SYN-ACK 재전송 횟수 (서버 측)
net.ipv4.tcp_retries1 = 3 # 초과 시 IP 레이어에 경로 재탐색 힌트 (연결 유지)
net.ipv4.tcp_retries2 = 15 # 초과 시 연결 강제 종료
net.ipv4.tcp_orphan_retries = 0 # orphan 소켓 재전송 횟수 (0 = tcp_retries2 기준 자동)
주의사항
tcp_retries2는 횟수가 아닌 시간 기반으로 동작- 15회에 상응하는 누적 시간(약 13~30분)이 지나면 종료
tcp_orphan_retries = 0은 0회가 아니라 기본값 위임 의미
4. Keepalive vs 재전송 비교
| Keepalive Probe | 데이터 재전송 | |
|---|---|---|
| 목적 | 연결 생존 확인 | 유실된 데이터 복구 |
| 트리거 | idle 상태 지속 | ACK 미수신 (RTO 만료) |
| 관련 파라미터 | tcp_keepalive_probes |
tcp_retries2 |
| 실패 시 | 연결 강제 종료 | 연결 강제 종료 |
| 2배 backoff | ❌ 일정 간격 | ✅ |
Keepalive probe 횟수는 데이터 재전송과 무관
5. tcp_orphan_retries와 TIME_WAIT
orphan 소켓이란?
close() 호출 후 FIN을 보냈지만 아직 완전히 닫히지 않은 소켓
FIN_WAIT 상태별 동작
FIN 전송
│
├─ ACK 못 받음 (FIN_WAIT1)
│ └─ tcp_orphan_retries 초과 → 강제 종료 ❌ TIME_WAIT 진입 불가
│
└─ ACK 받음 (FIN_WAIT2) → 상대방 FIN 대기
├─ 상대 FIN 수신 → TIME_WAIT 진입 ✅
└─ tcp_fin_timeout(60초) 초과 → 강제 종료 ❌ TIME_WAIT 진입 불가
결론
tcp_orphan_retries 값이 너무 작으면 FIN_WAIT1 단계에서 4-way handshake가 완료되지 않은 채 연결이 강제 종료되어 TIME_WAIT 상태로 진입하지 못함
6. 진단 명령어
# 현재 소켓의 RTO, RTT 확인
ss -ti dst <target_ip>
# 출력 예: rto:200 rtt:0.5/0.25
# 커널 파라미터 확인
sysctl net.ipv4.tcp_retries2
sysctl net.ipv4.tcp_orphan_retries