[1.29] Timeout

Always·2025년 1월 30일
1

매일메일

목록 보기
29/69

Connection Timeout,Socket Timeout, Read Timeout

Connection Timeout

서버와 클라이언트가 TCP 통신을 하기전 서로의 상태가 reliable한지를 확인하는데, 이를 3-way handshake라고 한다. 이 연결과정이 서버측의 장애나,응답의 지연으로 인해서, 연결을 맺지 못하고, 지정된 시간을 넘어가면, Connection Timeout을 발생시킨후, 재전송을 하거나, 문제가 있는부분 을 해결한 수 다시 재전송한다.

Socket Timeout

연결 수립 이후 클라이언트와 서버는 여러 정보 즉 데이터를 주고 받는다. 이 때 데이터의 크기가 크기 때문에 패킷의 단위로 주고 받는다. 서버나 클라이언트가 패킷을 받고, 일정시간이 지나도 다음 패킷이 안온다면, Socket Timeout을 일으킨다. 이를 통해서 사용자는 문제가 있음을 알게 되고 문제의 원인을 해결한 후 다시 재전송할 수 있다.

Read Timeout

일반적으로 클라이언트가 요청을 보내고, 서버는 그것에 맞는 요청을 수행한다. 이 때 클라이언트는 요청을 보냈음에도 서버가 일정 시간이상으로 요청이 안 보낼 때,Read Timeout을 통해서 클라이언트가 계속 기다리면서 낭비되는 시간을 줄인다.

Timeout시 Retry 전략

클라이언트가 요청을 보낸후 Read Timeout이 발생했다고 가정해보자.
그렇다면 3가지중의 하나의 case이다.

1. 요청이 실패한 case
2. timeout이 발생했지만, 요청은 성공한 case
3. 요청조차 서버에 도달하지 못한 case

그렇다면 이 상황에서 어떻게 retry하는 것이 맞을까?

  • 요청이 실패한 case일 때 retry를 바로 한다고 생각해보자.
    만약 서버의 부하로 인해서, 요청이 실패한 경우에는 더 많은 retry은 오히려 더 큰 서버에게 부하를 주게 될 것이다. 이러한 경우에는 지수의 간격을 두고 Retry하는 전략을 사용할 수 있다.

    출처:https://hudi.blog/safely-handling-network-errors/
  • timout이 발생했지만, 요청은 성공한 case를 보자.
    이 경우에는 재전송을 하게 된다면 데이터베이스의 정합성에 문제가 생길 수 있다.
    따라서 Idenpotency Key를 활용하는 대안을 볼 수 있다.
    클라이언트가 서버에게 요청할 때 이 키를 보내고 서버는 그전에 해당 key를 받은 적이 있는지를 체크하는 것이다.

클라이언트 요청의 실패 처리 및 재시도 전략

클라이언트는 서버에 요청을 보내고 응답을 받는 역할을 수행하며, 응답 결과에 따라 사용자에게 성공 또는 실패를 알려줘야 한다. 그러나 요청이 timeout으로 인해 실패했을 경우, 단순히 실패로 처리하는 것이 적절한지 고민이 필요하다.


1. timeout 발생 시 고려할 문제점

실패로 처리하는 경우

  • 사용자는 다시 동일한 API를 요청할 가능성이 높다.
  • 데이터베이스 정합성 문제가 발생할 수 있다.
  • 서버 부하가 증가할 수 있다.

성공으로 처리하는 경우

  • 실제로 요청이 정상적으로 수행되지 않았을 가능성이 존재한다.
  • 사용자가 잘못된 정보를 받아볼 위험이 있다.

위 두 가지 방법 모두 적절하지 않으며, 제3의 상태를 도입할 필요가 있다.


2. 처리 중 상태 도입

timeout이 발생한 경우, 단순히 실패가 아닌 "처리 중" 상태로 응답한다.
이후 서버가 해당 요청을 재처리할 수 있도록 비동기 처리를 도입하는 것이 효과적이다.

처리 흐름

  1. 클라이언트가 서버에 요청을 보냄.
  2. 서버가 일정 시간 내에 응답하지 못하면 "처리 중" 상태를 반환.
  3. 요청 정보를 Kafka와 같은 메시지 큐에 저장.
  4. 서버의 비동기 프로세스가 메시지를 소비하여 재시도 수행.
  5. 최종적으로 성공 또는 실패 상태로 업데이트.

3. 메시지 큐를 활용한 재시도 로직

Kafka를 이용하면 일정한 지연을 두고 안정적으로 재시도할 수 있다.

Kafka를 이용한 재시도 방법

  • 요청이 timeout 발생 시 메시지 큐(Kafka)에 해당 요청을 저장.
  • 서버의 메시지 소비 프로세스가 이를 읽어 일정 간격으로 재시도.
  • 처리 성공 시 데이터베이스 및 클라이언트에 최종 성공 반영.
  • 실패가 지속되면 최종적으로 실패로 기록.
graph TD;
    A[클라이언트 요청] -->|Timeout 발생| B["처리 중 상태 반환"]
    B --> C[Kafka 메시지 큐에 저장]
    C --> D[비동기 프로세스가 메시지 소비]
    D -->|재시도 성공| E[최종 성공 처리]
    D -->|재시도 실패| F[최종 실패 처리]
   

4. 처리 중 상태를 위한 API 응답 예시


{
  "status": "processing",
  "message": "요청이 처리 중입니다. 완료되면 알림을 받게 됩니다."
}

클라이언트는 추가적인 API 요청 없이 WebSocket이나 Polling을 통해 상태 변화를 감지할 수 있도록 설계할 수 있다.

이렇게 timeout발생시 여러가지를 고려하고 retry전략을 생각해보는것이 매우 중요하며, kafka에 대한 내용은 더욱 자세하게 공부해서 글로 올릴 것이다.

profile
🐶개발 블로그

0개의 댓글