서버와 클라이언트가 TCP 통신을 하기전 서로의 상태가 reliable한지를 확인하는데, 이를 3-way handshake
라고 한다. 이 연결과정이 서버측의 장애나,응답의 지연으로 인해서, 연결을 맺지 못하고, 지정된 시간을 넘어가면, Connection Timeout
을 발생시킨후, 재전송을 하거나, 문제가 있는부분 을 해결한 수 다시 재전송한다.
연결 수립 이후 클라이언트와 서버는 여러 정보 즉 데이터를 주고 받는다. 이 때 데이터의 크기가 크기 때문에 패킷의 단위로 주고 받는다. 서버나 클라이언트가 패킷을 받고, 일정시간이 지나도 다음 패킷이 안온다면, Socket Timeout
을 일으킨다. 이를 통해서 사용자는 문제가 있음을 알게 되고 문제의 원인을 해결한 후 다시 재전송할 수 있다.
일반적으로 클라이언트가 요청을 보내고, 서버는 그것에 맞는 요청을 수행한다. 이 때 클라이언트는 요청을 보냈음에도 서버가 일정 시간이상으로 요청이 안 보낼 때,Read Timeout
을 통해서 클라이언트가 계속 기다리면서 낭비되는 시간을 줄인다.
클라이언트가 요청을 보낸후 Read Timeout
이 발생했다고 가정해보자.
그렇다면 3가지중의 하나의 case이다.
1. 요청이 실패한 case
2. timeout이 발생했지만, 요청은 성공한 case
3. 요청조차 서버에 도달하지 못한 case
그렇다면 이 상황에서 어떻게 retry하는 것이 맞을까?
클라이언트는 서버에 요청을 보내고 응답을 받는 역할을 수행하며, 응답 결과에 따라 사용자에게 성공 또는 실패를 알려줘야 한다. 그러나 요청이 timeout
으로 인해 실패했을 경우, 단순히 실패로 처리하는 것이 적절한지 고민이 필요하다.
timeout
발생 시 고려할 문제점위 두 가지 방법 모두 적절하지 않으며, 제3의 상태를 도입할 필요가 있다.
처리 중
상태 도입timeout
이 발생한 경우, 단순히 실패가 아닌 "처리 중" 상태로 응답한다.
이후 서버가 해당 요청을 재처리할 수 있도록 비동기 처리를 도입하는 것이 효과적이다.
Kafka
와 같은 메시지 큐에 저장.Kafka
를 이용하면 일정한 지연을 두고 안정적으로 재시도할 수 있다.
timeout
발생 시 메시지 큐(Kafka)에 해당 요청을 저장.graph TD;
A[클라이언트 요청] -->|Timeout 발생| B["처리 중 상태 반환"]
B --> C[Kafka 메시지 큐에 저장]
C --> D[비동기 프로세스가 메시지 소비]
D -->|재시도 성공| E[최종 성공 처리]
D -->|재시도 실패| F[최종 실패 처리]
{
"status": "processing",
"message": "요청이 처리 중입니다. 완료되면 알림을 받게 됩니다."
}
클라이언트는 추가적인 API 요청 없이 WebSocket이나 Polling을 통해 상태 변화를 감지할 수 있도록 설계할 수 있다.
이렇게 timeout발생시 여러가지를 고려하고 retry전략을 생각해보는것이 매우 중요하며, kafka에 대한 내용은 더욱 자세하게 공부해서 글로 올릴 것이다.