Connection Timeout과 Read Timeout은 어떻게 설정하는게 좋을까?

정은영·2025년 5월 25일
1

CS

목록 보기
23/24

Connection Timeout과 Read Timeout

Connection Timeout은 클라이언트와 서버 간 TCP 3 way handshake를 통해 TCP 연결 생성을 할 때, 클라이언트가 연결 요청(SYN)을 보냈지만 서버가 응답하지 않으면 발생합니다.

Read Timeout은 클라이언트와 서버 간 연결은 성공했지만 응답 데이터가 지정된 시간에 오지 않으면 발생합니다.

Connection Timeout은 언제 발생할 수 있을까?

TCP 3 way handshake 과정에서 패킷 유실이 발생할 할 수 있는 경우는 다음과 같이 3가지가 있습니다.

  • Case 1. SYN 패킷이 유실 되었을 때
  • Case 2. SYN + ACK 패킷이 유실 되었을 때
  • Case 3. ACK 패킷이 유실 되었을 때

Case 1. SYN 패킷 유실

클라이언트가 서버와 연결을 맺기 위해 SYN 패킷을 보냈지만, 이 SYN 패킷이 유실되는 경우입니다.
클라이언트는 SYN+ACK 패킷을 받지 못하여 패킷이 유실되었다고 판단 후 SYN 패킷을 다시 보냅니다.

이 때, 재전송에 소요되는 시간을 InitRTO라고 부르며 부릅니다. 이 값은 리눅스 상에서는 1초로 하드코딩 되어 있습니다. 따라서 SYN 패킷이 한번 유실된다면 최소한 연결을 맺는데 1초 이상이 소요됩니다.

RTO
RTO란 패킷 유실 여부를 판단하는 시간입니다. 서버와 클라이언트간 통신을 위해 필요한 물리적인 시간 RTT (Rount Trip Time)를 기반으로 RTO를 계산합니다. 예를 들어, 클라이언트에서 서버로 패킷을 보낼 때 100ms가 소요되고 서버에서 클라이언트로 패킷을 보낼 때 100ms가 소요된다고 하면 RTT는 100ms+100ms = 200ms가 됩니다. RTO는 RTT보다는 크게 설정됩니다.
하지만 Case 1처럼 최초로 연결을 맺는 경우에는 이 RTT를 측정할 수 없으므로 RTO를 초기값으로 설정하는데요. 이 값이 initRTO입니다.

Case 2. SYN + ACK 패킷이 유실 되었을 때


이 경우도 원인은 다르지만 결과는 Case 1과 똑같이 동작하게 됩니다.
서버가 보낸 SYN+ACK 패킷이 유실되었을 때, 클라이언트는 패킷 유실로 판단하여 SYN을 다시 보냅니다.

Case 3. ACK 패킷이 유실 되었을 때

Case 3의 경우에는 SYC, SYNC+ACK 패킷을 주고 받으면서 RTT를 알게 되었기 때문에 더이상 initRTO를 쓰지 않고 RTT를 기반으로 계산된 RTO를 쓰게 됩니다.
따라서 ACK 패킷은 initRTO 1초가 아닌 RTO 200ms 이후 패킷을 재전송하게 됩니다.

Connection Timeout을 몇으로 설정해야 하는가?

외부 API와 통신을 할 때 지연이 발생하는 경우를 생각해봅시다. 이 지연된 외부 API 요청에 대해 connection timeout을 너무 길게 잡으면, 요청이 쌓이고 리소스 고갈로 전체 서비스 장애로 이어질 수 있습니다. 이런 경우에는 timeout을 너무 길지 않게 설정해서 장애를 빠르게 감지하고 대처할 수 있어야 합니다.

다만, 네트워크는 항상 100%로 동작하지 않기 때문에 한번의 패킷유실은 재전송을 통해 해결할 수 있도록 Connection Timeout을 설정해야 합니다.

이러한 기준으로 Connection Timeout을 몇으로 설정할 것인가? 생각해보면...
initRTO는 지수 backoff로 증가하여 2의 제곱으로 커지기 때문에 한번의 패킷 유실을 허용한다고 하면 3초정도가 적당합니다.

이 값이 정답은 아니고 통신 환경에 따라서 다르게 설정해야 합니다. 인터넷 환경에서는 3초 정도가 적당하고, 사설망 또는 VPC 내에서 내부 통신할 경우에는 안정적이고 RTT가 짧기 때문에 3초보다 짧아야 합니다.

Read Timeout을 몇으로 설정해야 하는가?


Read Timeout가 발생하는 단계에서 RTO는 RTT 기준으로 계산되어 initRTO(=1초)보다는 작게 계산됩니다.
Read Timeout을 고려할 때는 RTT와 RTO, 서버에서 요청을 받아 처리하는 시간까지 고려해야합니다.


RTT가 10ms, RTO가 200ms, 서버에서 요청을 처리하는 데 소요되는 시간을 300ms라고 가정합시다.

한번의 패킷 유실은 허용한다는 기준하에
서버와 클라이언트가 통신하는데 걸리는 시간 10ms + 서버에서 요청을 처리하는 데 소요되는 시간 300ms + 패킷 유실을 인지하고 재전송에 소요된 시간(RTO) 200ms = 510ms 가 걸립니다.

따라서, 약간의 버퍼를 두고 Read Timeout은 650ms~1초로 설정하는게 좋습니다.

Reference

0개의 댓글