오픈소스 인사이트
home
오픈소스 기술 동향
home
🚀

네트워크 안정성 및 성능 향상을 위한 리눅스 TCP RTO 및 tcp_retries2 파라미터의 작동 원리

7 more properties
※ 해당 문서는 RHEL8(kernel 4.18) 기준으로 작성되었음.

👋🏻 들어가며

에스코어에서 RHEL 기술지원을 수행하고 있는 정세혁입니다.
최근 WAS 서버에서 DB 서버로의 트랜잭션 요청 시, TCP 세션은 ESTABLISHED 상태로 유지되지만 실제 데이터 전송이 이루어지지 않아 애플리케이션 Timeout 이슈가 발생하였습니다.
tcp_retries2 값 조정을 통해 TCP 연결종료시간을 줄여 이슈를 해소하였는데 그 과정을 자세히 소개하고자 합니다.
서버 간 TCP 통신 중 네트워크 정책, 타겟 서버의 문제 등으로 데이터 전송이 실패하는 경우가 있습니다.
이러한 경우 클라이언트에서는 ESTABLISH되어있던 연결을 즉시 종료하지 않고 Retransmission을 전송하여 연결을 유지하려고 노력합니다.
데이터 전송 중 ACK를 전달 받지 못해 연결이 종료되는 과정에 대해 그림을 통해 알아보겠습니다.

↔️ Data Retransmission

1.
클라이언트가 서버로 Data를 보냄.
2.
서버로부터 일정 시간(RTO)내에 ACK를 받지 못함.
3.
첫 번째 재전송을 시도하고, RTO 값을 2배로 늘려 다시 ACK를 기다림. (Exponential Backoff)
4.
이 과정을 tcp_retries2에 설정된 횟수만큼 반복
5.
최종 시도까지 ACK를 받지 못하면 (RTO x 2n+12^{n+1}) 값만큼 대기 후 연결을 강제 종료함.
이때, n은 tcp_retries2
데이터를 전송했지만 상대방으로부터 응답(ACK)를 받지 못할 때, TCP는 재전송을 시도합니다.
이 때, tcp_retries2는 재전송 시도 횟수를 결정합니다.

❔ RTO란?

TCP 전송 과정에서 타겟 서버에 데이터를 전송할 때 ACK 수신을 기다리는 시간이며, ACK를 전달받지 못했을 때의 Retransmission TimeOut 값입니다.
해당 시간이 초과하도록 타겟 서버로부터 ACK를 받지 못하면 DATA 재전송을 수행합니다.
커널에서 기본적으로 동작하는 RTO_MIN 값은 200ms이며, RTO_MAX 값은 120s입니다.
net/tcp.h #define TCP_RTO_MAX ((unsigned)(120*HZ)) #define TCP_RTO_MIN ((unsigned)(HZ/5)) HZ는 일반적으로 1000ms(1s)
C
복사
RTO 값은 라우터나 타겟 서버에서 응답을 주는 속도에 따라 결정되나 200ms 이하로 설정되지 않습니다.
RTO_MIN 값은 수동으로 지정할 수 있으며 200ms 미만 값으로도 설정이 가능하나, 너무 낮게 설정될 경우 재전송이 빈번하게 발생하는 오버헤드가 발생할 수 있습니다.

🤝 RTO 결정과정

1.
RTT 측정 TCP 연결에서 데이터 세그먼트를 보내고 해당 세그먼트에 대한 ACK를 수신할 때까지의 시간을 측정하여 RTT 샘플을 수집
2.
SRTT 및 RTTVAR 계산 RTT 측정 및 통계 데이터 세그먼트에 대한 ACK가 도착하면, 커널은 net/ipv4/tcp_input.c 파일의 tcp_rtt_estimator() 함수를 호출하여 계산 수행 srtt_us : RTT의 평균 값, 네트워크의 평균 응답 시간 mdev_us : RTT의 변화량을 나타내는 값
3.
RTO 결정 srtt_us 와 mdev_us 값을 조합하여 최종 RTO가 계산됨. 커널 소스내 tcp_rtt_estimator() 함수와 tcp_set_rto() 함수가 이 계산을 수행하며, 계산식은 다음과 같음.
RTO = SRTT + (4 × RTTVAR) SRTT = srtt_us RTTVAR = mdev_us
C
복사

🔎 RTO 값 확인 방법

# ss -ti ESTAB 0 0 192.168.1.100:ssh 192.168.1.101:41738 cubic wscale:7,7 rto:201 rtt:0.982/1.315
Bash
복사
해당 명령어를 통해 ESTABLISH된 TCP session의 RTO 값을 확인할 수 있습니다.
rto:201 : 현재 이 TCP연결의 RTO 값이 201ms임을 의미함
rtt:0.982/1.315 : RTT의 평균값(avg)이 0.982이며, 평균 편차(mdev)가 1.315ms임을 의미함
cubic : 사용중인 TCP 혼잡 제어 알고리즘

🌐 FAQ

tcp_retries2에 따라 timeout값이 어떻게 변하나요?

tcp_retries2는 기본 값은 15 입니다.
만약 재전송이 실패하게 되면, 커널은 tcp_retransmit_timer() 함수를 통해 RTO 값을 2배로 증가시킵니다. (Exponential Backoff)
커널 기본 값인 RTO_MIN 200ms / RTO_MAX 120s 기준
tcp_retries2=15일 경우 ACK를 받지 못한 시점으로부터 약 16분 후 connection이 종료됩니다.
tcp_retries2=8일 경우 ACK를 받지 못한 시점으로부터 약 100초 후 connection이 종료됩니다.

RTO_MIN값을 임의로 변경할 수 있나요?

rto_min 값은 다음과 같이 변경할 수 있습니다.
# ip route change <dst> dev <dev> rto_min value - 특정 라우팅에 대한 rto_min 값 변경 # ip route show ex) # ip route change 192.168.1.0/24 dev bond0 rto_min 300ms # ip route show 192.168.1.0/24 dev bond0 scope link rto_min lock 300ms # ss -ti ESTAB 0 0 192.168.1.101:55780 192.168.1.100:ssh cubic wscale:7,7 rto:310 rtt:9.326/13.294
Bash
복사
※ RHEL 10에서는 net.ipv4.tcp_rto_min_us 파라미터가 추가되었습니다.
해당 값은 microseconds 단위로 입력 가능하며 기본 값은 200000입니다.
rto_min / tcp_bpf_rto_min / net.ipv4.tcp_rto_min_us 값 순으로 인식되기 때문에 rto_min이 설정되어있다면 우선 적용됩니다.
# sysctl -w net.ipv4.tcp_rto_min_us=100000 tcp_rto_min_us - INTEGER Minimal TCP retransmission timeout (in microseconds). Note that the rto_min route option has the highest precedence for configuring this setting, followed by the TCP_BPF_RTO_MIN socket option, followed by this tcp_rto_min_us sysctl. The recommended practice is to use a value less or equal to 200000 microseconds. Possible Values: 1 - INT_MAX Default: 200000
Plain Text
복사

📌 마무리

tcp_retries2 값을 조정함으로써 서버나 네트워크에 이상이 발생하였을 때 세션을 더욱 빠르게 종료시킬 수 있습니다.
다만, 해당 값을 과도하게 줄이게 된다면 순간적인 단절이나 네트워크 지연 등으로 인한 ACK를 늦게 받을 경우 의도와는 다르게 부적절한 연결 끊김 현상이 발생할 수 있습니다.
따라서, 시스템 환경에 따라 적절한 값을 설정하여 운영을 권고합니다.

📎 참고 자료