Connection Timeout과 Read Timeout은 어떤 값이 적절할까?

공병주(Chris)·2023년 2월 14일
3

2023 글로벌미디어학부 졸업전지 단디 프로젝트를 진행하면서 Feign Client를 적용하고 있었습니다. FeignClient에는 Connection-TimeoutRead-Timeout을 설정할 수 있습니다. 어떤 기준으로 두 값을 설정해야하는지 모르겠어서 찾아보다가 좋은 글들을 읽고 이해, 고민을 해보았습니다.

글 출처는 아래에 남겨두겠습니다.

RTT와 RTO

Timeout들을 알아보기 전에 RTT와 RTO를 알아야합니다.

RTT

Round Trip Time의 줄임말로 패킷이 목적지에 도달하고 나서 해당 패킷에 대한 응답이 출발지로 다시 돌아오기까지의 시간입니다. 물리적으로 먼거리와 통신을 하려고 한다면 RTT도 커집니다.

네트워크 성능을 측정을 위한 지표로도 사용됩니다.

RTO

Retransmission Timeout의 줄임말로, 재전송 타임아웃 시간입니다. RTO를 넘은 시간에도 응답이 오지 않으면 재전송을 하기 위해 설정하는 시간입니다.

RTO는 RTT를 기반으로 설정됩니다. 두 노드 간데 패킷이 전달되는 시간들을 보고 재전송 타임아웃을 설정하는 것입니다.

InitRTO

하지만, 첫 통신에 응답을 받지 못하면 RTT를 알 수 없기 때문에 RTO를 설정할 수 없습니다. 따라서 InitRTO라는 초기 RTO 값 존재합니다. 리눅스 기본값은 1초로 지정되어있습니다.

중요한 점은, initRTO는 실패할 때마다 값이 2의 제곱으로 증가한다는 점입니다.

Exponential Backoff

2^0 → 2^1 → 2^2 → 2^3 → 2^4

retry를 빨리 하지 않는 이유는 요청하는 측의 서버에 문제가 있을 수 있으니까, 바로 요청을 해도 똑같은 문제를 겪을 것이니 바로 보내지 않음

최소 RTO

RTO는 최소값을 가지고 있습니다. 리눅스에서 최소값은 200ms로 설정되어 있습니다. RTT를 통해서 RTO를 도출한 값이 200ms 보다 작아도 RTO는 200ms가 됩니다.

4가지 개념을 기억하시면서 글을 읽으시면 좋을 것 같습니다.

Connection Time-out

출처 : https://afteracademy.com/blog/what-is-a-tcp-3-way-handshake-process/

Connection Time-out은 3-way handshaking과 연관이 있습니다.

위 3번의 과정 중에 유실되는 패킷이 있다면 다시 패킷을 전송해야하기 때문에 연결 지연으로 이뤄집니다. 여기서 패킷 유실로 인한 어느 정도의 연결 지연까지 허용할 것인지가 Connection Time-out입니다.

3 way 중 어느 과정에서 손실이 일어났는지를 Client - Server 간의 관계로 모두 따져보고 적절한 Connection Time-out을 도출해보겠습니다.

1. SYN(Client → Server) 패킷 유실 상황

SYN를 전송하고 SYN / ACK를 응답받지 못했기 때문에, RTT를 알 수 없습니다.
따라서, InitRTO에 따라 1초 후에 재전송을 합니다.

따라서, Connection Time-out을 1초보다 짧게 지정한다면 해당 과정에서 패킷이 유실이 되면 바로 Connection Time-out이 발생합니다.

2. SYN / ACK (Server → Client) 패킷 유실 상황

SYN / ACK 패킷이 유실된 상황도 SYN 패킷이 유실된 상황과 동일합니다. Client에서 InitRTO인 1초 이내에 응답을 받지 못한다면 다시 재전송을 합니다.

3. ACK (Client → Server) 패킷 유실 상황

이제 Client에서 SYN / ACK를 응답받았기 때문에, RTT를 알 수 있습니다. 따라서, RTT를 기반으로 RTO를 도출해낼 수 있습니다. 위에 적어뒀듯이 최소 RTO는 200ms로 설정되어있습니다.

Connection-Timeout 값 도출

SYN, SYN / ACK 의 RTO는 initRTO고정되어 있고, ACK는 RTT에 따른 RTO를 기준으로 하기 때문에 SYN, SYN / ACK 위주로 값을 정해야할 것 같다는 생각이 듭니다. 또한, 실제 연결에서 긴 RTT로 Connection-Timeout이 많이 발생한다면 Connection-Timeout을 조정해야 할 것으로 보입니다.

따라서, 아래 3가지 값에 따라 유동적으로 조정해야한다고 생각합니다.

  • SYN, SYN / ACK에서의 패킷 유실 허용 횟수(initRTO과 관련)
  • ACK의 허용 횟수 (RTT에 의해 계산된 RTO 값과 관련)
  • 실제 통신을 하는 속도 (RTT)

하지만, 유동적이지 않고 절대적인 조건이 있습니다. Connection Time-out을 1초보다 작게 가져간다면, 한번의 재전송도 허용하지 않습니다. initRTO에 따라 1초를 기다리고 재전송을 하기도 전에 Connection-Timeout이 발생하기 때문입니다.

많은 패킷 유실을 허용하기 위해서 Connection-timeout을 늘리는 것은 좋지 않은 방식 같습니다. Connection-timeout을 늘릴 것이 아니라, 네트워크적 문제를 확인하고 개선을 해야 할 것 같습니다. 또한, Connection-timeout을 많이 늘리면 사용자에게 연결 지연에 대한 피드백을 바로 줄 수 없기 때문에 좋지 않은 사용자 경험을 줄 것이라 생각합니다.

사실, RTT 값이 유동적인 값이기 때문에 이론만으로 Connection-Timeout 값을 도출하는 것이 힘들다고 생각합니다. 하지만, 이런 개념을 알고 모르고는 차이가 있다고 생각합니다.

따라서, Connection-Timeout 개념에 대해 알고 실제로 패킷이 오가는 기록과 Connection-Timeout이 발생하는 빈도를 보면서 적절히 제어해야 할 것 같습니다.

Read-Timeout

출처 : https://junhyunny.github.io/information/kind-of-request-timeout/

Read-Timeout은 클라이언트가 서버와의 Connection을 마친 후, 특정 데이터를 Read(요청)했으나 서버의 응답이 늦을 경우에 발생하는 상태에서 발생합니다.

3 way - handshaking 과정에서 RTT에 의한 RTO가 도출되었기 때문에, Read-Timeout은 RTO를 기반으로 설정할 수 있습니다. 기본적으로 최소 RTO는 200ms이기 때문에, Read-Timeout을 200ms 보다 적게 가져간다면, 1번의 패킷 유실도 허용하지 않는 조건이 됩니다.

사실, Read-Timeout에서 RTO 보다 중요한 것은 Server에서 요청을 처리하는데 걸리는 시간이라고 생각합니다. RTT가 20ms이고 Server에서 요청에 대한 처리 시간이 500ms라고 가정해보겠습니다. Read-Timeout을 500ms보다 적게 두었다면 해당 요청에 대해선 무조건 Read-Timeout이 발생할 것입니다. 따라서, Server에서의 처리 시간도 고려해야 합니다.

결론

절대적으로 좋은 Connection Time-out, Read-Timeout을 제시할 수는 없다고 생각합니다. 어디와 통신을 하는지, 본인의 서비스는 어떤 성격인지, 사용자에게 어떤 경험을 줄 것인지 등을 고려해야 한다고 생각합니다. 값을 설정하는 것에 끝나는 것이 아니라, 실제 Timeout 발생 빈도와 원인을 파악하고 값을 적절히 조절하는 것이 좋다고 생각합니다.


참고자료

https://brunch.co.kr/@alden/15

https://brunch.co.kr/@dreaminz/5

https://alden-kang.tistory.com/20

1개의 댓글

comment-user-thumbnail
2023년 11월 22일

공주님 잘봤어용~

답글 달기