네트워크 timeout의 종류들

네트워크 타임아웃

어느정도 규모가 있는 서비스라면 보통 외부와의 통신없이 사용하는 stand-alone 으로 사용하는 경우는 드물다고 할 수 있습니다. 서비스 특성에 따라 일반적으로 사내 API 혹은 외부 API 들을 연계해서 사용하는것이 대부분일텐데 이때 각 서비스들간에 네트워크 통신을 하게 될 것 입니다. 그리고 그 과정속에서 TimeoutException 에러를 흔하게 받아보셨을거라 생각합니다. 이번 포스팅에서는 네트워크 통신에서 발생하는 여러가지 Timeout에 대해서 정리해보려고 합니다.


RestTemplate

먼저 Timeout의 종류를 알아보기위해 Spring에서 HTTP Request를 위해 사용하는 RestTemplate를 살펴보도록 하겠습니다. RestTemplate의 생성자에는 HttpComponentsClientHttpRequestFactory라는 파라미터를 통해 다양한 연결정보 설정을 할 수 있도록 되어 있습니다.

// package org.springframework.http.client.HttpComponentsClientHttpRequestFactory

public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequestFactory, DisposableBean {

    ...

	public void setConnectTimeout(int timeout) {
        ...
	}

	public void setConnectionRequestTimeout(int connectionRequestTimeout) {
		...
	}

    public void setReadTimeout(int timeout) {
        ...
	}

    // httpClient(socketTimeout)
    public void setHttpClient(HttpClient httpClient) {
		...
	}
}

정리해보자면 다음과 같은 HTTP 통신을 위해 다음과 같은 Timeout들을 정의하고 있음을 확인 하실수 있습니다.

  • connectionTimeout
  • connectionRequestTimeout
  • readTimeout
  • socketTimeout

Timeout-s

각각의 타임아웃들이 무엇을 의미하는지 아래 그림으로 알아보도록 하겠습니다.

1

가장먼저 Connection timeout은 실제 request를 하기전, 말그대로 연결을 맺는데 걸리는 유효시간 입니다. 3-handshaking 과정을 통해 클라이언트와 서버간의 Connection을 생성하는데 걸리는 유효시간을 의미합니다. 일반적으로 네트워크 상태가 불량할경우 timeout을 초과할때가 많습니다.

일반적으로 가장 많이 custom 수정되는 Read timeout은 요청을 보내고 응답을 받는데까지 걸리는 유효시간을 의미합니다. 일반적으로 서버측에서 처리하는 시간이 길어지거나 (long-transaction) 요청/응답에 보내지는 네트워크 데이터가 큰 경우에 timeout을 초과할때가 많습니다.

다음으로 Socket timeout은 네트워크상에서 데이터는 패킷단위로 전송되어지는데, 연속된 다음 패킷을 받는데까지 걸리는 유효시간을 의미합니다. 일반적으로 패킷사이즈가 크거나 네트워크 상태가 불량할경우 timeout을 초과할때가 많습니다.

마지막으로 그림에는 connectionRequestTimeout이 존재하지 않는데, 이는 httpClient 구현상에서 connection-pool을 정의해두고 Connection을 재사용하는데 connection-pool에서 connection을 가지고 올때까지 걸리는 유효시간을 의미합니다.


timeout의 발생 상황

이제 위에서 timeout의 종류와 개념에 대해 알아보았으니 각각의 timeout이 발생하는 상황들을 유추해 볼 수 있을것같습니다.

connectionTimeout

  • 해당 네트워크 경로(호스트, 포트)에 제공되는 서비스가 정상정이지 않은경우
  • 서버가 connection을 받을수 없는 상태인 경우
  • 네트워크지연으로 인한 connection 수행이 지연되는 경우

connectionRequestTimeout

  • connection-pool의 모든 connection이 사용중인 경우
  • 새로운 connection을 만드는 과정에서 네트워크지연이 발생한경우

readTimeout

  • connection-pool의 모든 connection이 사용중인 경우
  • 새로운 connection을 만드는 과정에서 네트워크지연이 발생한경우

socketTimeout

  • connection-pool의 모든 connection이 사용중인 경우
  • 새로운 connection을 만드는 과정에서 네트워크지연이 발생한경우