본문 바로가기

네트워크

[네트워크] 타임아웃(Timeout) 정리

1. Timeout 개요



□ Timeout이란?

  • 사전적으로, '프로그램이 특정한 시간 내에 성공적으로 수행되지 않아서 진행이 자동적으로 중단되는 것'
  • 응답을 무한정 기다릴 수 없기 때문에 기다릴 시간을 정해야 함


□ Timeout 사용 사례

  • Socket(양방향 통신), Http(단방향 통신)에서 다양하게 활용함
  • JDBC
      - JDBC Driver Type4는 소켓을 사용하여 DBMS에 연결하는 방식
      - DB 커넥션 요청을 했으나, 특정 시간 내에 연결이 안될 때 → Connection Timeout 발생
  • 채팅 프로그램
      - 채팅 프로그램에서, 서버로부터 특정 시간 응답이 없을 때 → Socket Timeout 발생
  • WEB
      - 클라이언트에서 서버로 request를 날렸을 때, 연결이 되지 않은 상태로 특정시간 이상 대기 → Connection Timeout 발생

□ 관련 패키지

  • java.net
  • HttpClient

 

2. java.net 패키지


□ java.net 패키지 개요

 

  • 네트워킹 응용 프로그램을 구현하기위한 클래스를 제공하는 패키지
  • java.net 패키지는 크게 두 섹션으로 나눌 수 있음

  - 저수준 API :
    (1) Addresses, which are networking identifiers, like IP addresses.
    (2) Sockets, which are basic bidirectional data communication mechanisms.
    (3) Interfaces, which describe network interfaces.


  - 고수준 API :
    (1) URIs, which represent Universal Resource Identifiers.
    (2) URLs, which represent Universal Resource Locators.
    (3) Connections, which represents connections to the resource pointed to by URLs.

 

 

□ java.net 패키지에서 제공하는 4개의 socket

 

  • Socket : TCP 클라이언트 API이며 일반적으로 원격 호스트에 연결 하는 데 사용됨
  • ServerSocket : TCP 서버 API이며 일반적으로 클라이언트 소켓의 연결을 허용함
  • DatagramSocket : UDP 엔드포인트 API이며 datagram 패킷을 주고 받는데 사용됨
  • MulticastSocket : multicast 그룹을 처리하는 DatagramScoket의 하위클래스임
  • TCP 소켓을 통한 송수신은 Socket.getInputStream() 메소드 및 Socket.getOutputStream()메소드 를 통해 얻을 수 있는 InputStreams 및 OutputStreams를 통해 수행됨

docs.oracle.com/javase/7/docs/api/java/net/package-summary.html

 

java.net (Java Platform SE 7 )

Interface Summary  Interface Description ContentHandlerFactory This interface defines a factory for content handlers. CookiePolicy CookiePolicy implementations decide which cookies should be accepted and which should be rejected. CookieStore A CookieStore

docs.oracle.com

 

□ Socket 관련 Timeout 


ㅇ Connection Timeout
ㅇ Socket Timeout / Read Timeout

 

□ Connection Timeout

  • 정의
      - 클라이언트가 서버측으로 Connection을 맺길 원하지만, 서버의 장애 상황으로 connection조차 맺어지지 못할 때 발생하는 timeout
  • Connection 과정
      - TCP 소켓 통신에서 클라이언트와 서버가 연결(Connection)될 때 정확한 전송을 보장하기 위해 상대방 컴퓨터와 사전에 세션을 수립함. 이 과정을 3-Way handshake라고 함 
      - 3-way handshake가 정상적으로 끝나야 Connection이 됐다고 표현할 수 있음
      - 즉, Connection Timeout이란 3-way HandShake가 정상적으로 수행되어 서버에 연결되기까지 소요된 시간임
  • TCP 3-Way Handshake 절차
      (1) A클라이언트는 B서버에 접속을 요청하는 SYN패킷을 보낸다. 이때 A클라이언트는 SYN 을 보내고 SYN/ACK 응답을 기다리는SYN_SENT 상태가 되는 것이다.
      (2) B서버는 SYN요청을 받고 A클라이언트에게 요청을 수락한다는 ACK 와 SYN flag 가 설정된 패킷을 발송하고 A가 다시 ACK으로 응답하기를 기다린다. 이때 B서버는 SYN_RECEIVED 상태가 된다.
      (3) A클라이언트는 B서버에게 ACK을 보내고 이후로부터는 연결이 이루어지고 데이터가 오가게 되는것이다. 이때의 B서버 상태가 ESTABLISHED 이다.

  * SYN : synchronize sequence numbers
  * ACK : acknowledgment
  * 4-Way handshake: 3-Way handshake는 TCP의 연결을 초기화 할 때 사용한다면, 4-Way handshake는 세션을 종료하기 위해 수행되는 절차임

 

□ Socket Timeout

  • 정의
      - 클라이언트와 서버가 연결된 후에 서버는 데이터를 클라이언트에게 전송하게 됨. 이 때 하나의 데이터 덩어리가 아닌 여러개의 패킷으로 나눠서 전송하게 되는데, 각 패킷이 전송될 때 시간 차이(Gap)가 있음. 이 차이 시간의 제한(임계치)을 SocketTimeout 이라고 함
  • read timeout과의 관계
      - 클라이언트와 서버가 connection은 맺어졌지만 I/O작업이 길어지거나 락이 걸려 요청이 처리되지 못하고 있을 때 클라이언트는 더 이상 기다리지 못하고 커넥션을 끊음. 이런 상황을 Read Timeout 이라고 함.
  • java.net 에서는 socket timeout과 read timeout을 혼용하며, setSoTimeout() 메소드를 사용함

  - document 참조 "setSoTimeout() : InputStream에서 데이터를 읽을 때의 Timeout 설정"

  - timeout 시 SocketTimeout Exception 발생 : java.net.SocketTimeoutException: Read timed out"

 

예시코드

테스트

 

□ Connection, Socket/Read timeout과 관련된 예외

 

 

java.net.SocketException

: Thrown to indicate that there is an error creating or accessing a Socket. → connection timeout

 

java.net.SocketTimeoutException : Signals that a timeout has occurred on a socket read or accept. → socket timeout, read timeout

 

 

3. HttpClient 라이브러리


□ Apache HttpClient란


ㅇ 개요
- HTTP 프로토콜을 손쉽게 사용할 수 있게 해주는 클라이언트측 HTTP 전송 라이브러리
- Apache HttpComponents 제품군의 HttpClient는 http 통신을 위한 표준이 되어옴 
- httpURLConnection의 단점(connection pooling)을 채우는 다양한 API를 가진 성숙한 프로젝트
(HttpClient from Apache HttpComponents suite has been a standard choice for http communication. It is a mature project, with rich API that fills many HttpURLConnection shortcomings e.g. connection pooling.)
ㅇ 사용 예시
  - Apache HttpClient를 이용하면 간편하게 HTTP request를 보낼 수 있음. 간혹 웹 서버를 만들면서 다른 서버로 보터 request를 보내 response 받아 데이터를 처리해야 할 때가 있음. 이 때 HttpClient를 이용하면 간단하게 구현 가능함

 

java.net 패키지와의 차이점

- java.net 패키지는 HTTP를 통해 리소스에 액세스 하기 위한 기본 기능을 제공하지만,  많은 애플리케이션에 필요한 완전한 유연성이나 기능을 제공하지 않음

- HttpClient 패키지는 최신 HTTP 표준 및 권장 사항의 클라이언트 측을 구현하는 효율적이고 최신이며 기능이 풍부한 패키지를 제공하여 이 공백을 채우려고 함
  - 확장을 위해 설계된 HttpClient는 기본 HTTP 프로토콜에 대한 강력한 지원을 제공하는 동시에 웹 브라우저, 웹 서비스 클라이언트 또는 분산 통신을 위해 HTTP 프로토콜을 활용하거나 확장하는 시스템과 같은 HTTP 인식 클라이언트 응용 프로그램을 구축하는 모든 사람에게 유용 할 수 있음

 

□ HttpClient에서 제공하는 timeout 관련 메소드


ㅇ setConnectTimeout
  - 서버와 연결을 맺을 때의 타임아웃
ㅇ setConnectionRequestTimeout
  - ConnectionManager(커넥션풀)로부터 꺼내올 때의 타임아웃
ㅇ setSocketTimeout
  - 요청/응답간의 타임아웃


* Connection Pooling
HttpClient로 빈번히 connection을 맺었다가, 사용이 끝나면 끊고 하다 보면 더 이상 connection을 열 수 없는 경우가 발생할 수 있다.
그 이유는 connection을 닫는다고 호출을 해도, 실제로는 어느 정도 TIME_WAIT 상태에 있다가 끊어지는데 이런 것들이 많이 쌓여 있으면 File Descriptor가 꽉 찼다는 에러(Too Many Open Files)가 나면서 connection을 맺지 못 하게 된다.
이런 현상을 방지하기 위해서는 Connection을 재사용할 수 있도록 HttpClient에서 제공하는 Connection Pool을 사용하는 것이다.
getHttpClient를 호출할 때 Connection Pool이 지정된 사이즈로 생성된다. 그리고, Connection을 하나 만들어 리턴한다.
Pool을 사용할 때마다 항상 주의할 것은 역시 반환을 꼭 해 줘야 한다는 것이다.

 

finally에선 항상 리소스를 반납한다. ==> ConnectionManager.release(response);

 

□ Timeout 예시

ㅇ HttpClient 4.3 이전(Configuring Timeouts Before HttpClient 4.3)

DefaultHttpClient httpClient = new DefaultHttpClient();
int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(
  CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000);
httpParams.setParameter(
  CoreConnectionPNames.SO_TIMEOUT, timeout * 1000);
httpParams.setParameter(
  ClientPNames.CONN_MANAGER_TIMEOUT, new Long(timeout * 1000));

ㅇ HttpClient 4.3(Configure Timeouts Using the New 4.3. Builde)

int timeout = 5;
RequestConfig config = RequestConfig.custom()
  .setConnectTimeout(timeout * 1000)
  .setConnectionRequestTimeout(timeout * 1000)
  .setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client = 
  HttpClientBuilder.create().setDefaultRequestConfig(config).build();

ㅇ 기타 참조

HttpClient httpclient = new DefaultHttpClient();
int useTimeout = 3;
      //HttpClient timeout 셋팅
      if(useTimeout>0){ 
            httpclient.getParams().setParameter("http.protocol.expect-continue", false);//HttpClient POST 요청시 Expect 헤더정보 사용 x
            httpclient.getParams().setParameter("http.connection.timeout", useTimeout * 1000);// 원격 호스트와 연결을 설정하는 시간
            httpclient.getParams().setParameter("http.socket.timeout",  useTimeout * 1000);//데이터를 기다리는 시간
            httpclient.getParams().setParameter("http.connection-manager.timeout",  useTimeout * 1000);// 연결 및 소켓 시간 초과 
            httpclient.getParams().setParameter("http.protocol.head-body-timeout",  useTimeout * 1000);
        }

ㅇ 기타 참조

// There are 3 timeouts settings available:

val requestConfig = RequestConfig.custom()
    // Determines the timeout in milliseconds until a connection is established.
    .setConnectTimeout(5_000) 
    // Defines the socket timeout in milliseconds,
    // which is the timeout for waiting for data or, put differently,
    // a maximum period inactivity between two consecutive data packets).
    .setSocketTimeout(5_000)
    // Returns the timeout in milliseconds used when requesting a connection
    // from the connection manager.
    .setConnectionRequestTimeout(2_000)
    .build()
// 10초로 설정한 예제
HttpPost request = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom()
  .setSocketTimeout(10*1000)
  .setConnectTimeout(10*1000)
  .setConnectionRequestTimeout(10*1000)
  .build();
request.setConfig(requestConfig);

 

 

'네트워크' 카테고리의 다른 글

[네트워크] 소켓 프로그래밍이란(Socket Programming)  (0) 2020.12.21