2016. 11. 18. 06:58
URL을  호출하는 코드를 작성할 때 Timeout 설정을 하게 됩니다.
아래 코드로 예를 들어보겠습니다.
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpParams params = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(params, 30);
HttpConnectionParams.setSoTimeout(params, 60);
* httpComponents:httpclient:4.2.3 버전 코드
setConnectionTimeout() 메서드와 setSoTimeout() 메서드를 이용하여 Timeout 설정을 하고 있습니다.
ConnectionTimeout은 서버와 클라이언트 연결시 임계값인 줄 알고 있었으나 SocketTimeout은 정확히 알지 못했던 것 같습니다.

궁금증 1. ConnectionTimeout과 SocketTimeout은 무엇일까?

먼저  URL로 HTTP 호출을 할 때 어떤 방식으로 수행되는지 이해가 필요합니다.
웹 브라우저에서 네이버에 접속한다고 가정하겠습니다.


웹 브라우저가 네이버 서버에 접속하기 위해 서버와 연결된 상태가 되어야 합니다. 연결을 구성하기 위해서 보통 TCP Connection과 동일하게 3-way Handshake 방식으로 수행하게 됩니다. 3-way Handshake를 정상적으로 수행하게 되면  웹 브라우저와 네이버 서버는 연결된 상태가 되는데요. 이 때까지 소요된 시간을 Connection에 소요된 시간이라고 할 수 있습니다. 즉, ConnectionTimeout은 Connection을 구성하는데 소요되는 시간의 임계치를 의미합니다.
SocketTimeout은 클라이언트와 서버가 연결된 상태 이 후 보통 서버는 데이터를 클라이언트로 전송하게 되는데요. 이 때 하나의 패킷이 아니라 여러 개의 패킷으로 나눠서 전송하게 됩니다. 각 패킷이 전송될 때 시간 Gap이 생길 수 있는데, 이 시간의 임계치를 SocketTimeout이라고 합니다.



ConnectionTimeout과 SocketTimeout을 그림으로 보면 위와 같습니다.

결론적으로 URL을 호출할 때에는 Co nnectionTimeout과 SocketTimeout 설정이 모두 필요합니다. 만약 두 가지 Timeout을 설정하지 않으면 어떤 일이 벌어질까요?
URL 접속시 무한 대기할 수 있습니다. 서버에서 특정 URL을 접속하는 케이스가 있다면 더욱 더 신중히 설정할 필요가 있습니다.
(OS 레벨에서 Timeout이 설정되어 있는 경우 그 설정값이 적용됩니다.)

궁금증 2. ReadTimeout은 무엇인가? ConnectionTimeout 또는 SocketTimeout과는 다른 값일까?

HttpClient 코드를 들여다보면 아래와 같은 코드를 접할 수 있습니다.

/**
* Sets the read timeout to a specified timeout, in
* milliseconds. A non-zero value specifies the timeout when
* reading from Input stream when a connection is established to a
* resource. If the timeout expires before there is data available
* for read, a java.net.SocketTimeoutException is raised
. A
* timeout of zero is interpreted as an infinite timeout.
*
*<p> Some non-standard implementation of this method ignores the
* specified timeout. To see the read timeout set, please call
* getReadTimeout().
*
* @param timeout an <code>int</code> that specifies the timeout
* value to be used in milliseconds
* @throws IllegalArgumentException if the timeout parameter is negative
*
* @see #getReadTimeout()
* @see InputStream#read()
* @since 1.5
*/
public void setReadTimeout(int timeout) {
   if (timeout < 0) {
      throw new IllegalArgumentException("timeout can not be negative");
   }
   readTimeout = timeout;
}

즉, ReadTimeout은 SocketTimeout과 유사하다고 볼 수 있습니다.
각 구현체마다 readTimeout과 socketTimeout을 혼용해서 사용하는 것은 아닌가 생각이 듭니다.

같은 팀이었던 분이 공유해 준 SocketTimeout 재현을 위한 코드입니다.(https://github.com/sukmin/http-cleint-recipe)



참고


Posted by 마이너 Tomining

댓글을 달아 주세요