오픈소스 인사이트
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를 늦게 받을 경우 의도와는 다르게 부적절한 연결 끊김 현상이 발생할 수 있습니다.
따라서, 시스템 환경에 따라 적절한 값을 설정하여 운영을 권고합니다.

참고 자료