본문 바로가기
Java

HttpURLConnection setTimeout 적용 안될때, 안된다고 착각 할 때

by nomore7 2013. 11. 7.



java.net.HttpURLConnection 에서 

 

 connection을 맺고, setConnectTimeout()을 설정하고 설정이 안된다.

적용이 안된다고 하는 글이 있다.

 

사실 나..;

 

확인해본결과 해당 함수는 잘 작동한다.

 

객체를 만들고 openConnection()을 한 이후에 시간을 설정해서 안되는건가  생각했는데, 감히 java.net클래스를 의심했는데... 

 

역시나 그럴리가 없었다.

잘되는 것이였다.

 

안된다고 생각하는 이유는..

다른 원인의 문제를 이함수에서 찾기 때문이다.( setConnectTimeout()에서)

 

함수이름을 잘보면 Connection에 대한 timeout이다.

 

모든 것에 대한 timeout이 아니다.

 

(근데 누가봐도 그렇게 보지는 않을듯.. 무슨 문제가 있으면 그시간안에 끈어줄 거라고 생각하는게 정상인거 같다. )

 

자세한 예제와 내용은 다음에 적여야지


timeout을 설정해야 하는 이유는

사실 아무문제가 없을때를 위해서가 아니라

문제가 있을때를 위해서 이기 때문에 정확히 알 필요가 있다.

 

timeout은 어떠한 서버로 연결을 할 때 시도하여 성공하지 못하였을 때를 위해 존재하는 것이다.

 

코드를 예제를 대충 짯다. (이클립스는 멋지다.)

 

try {

url = new URL("http://google.com");

conn = (HttpURLConnection)url.openConnection();

start = System.currentTimeMillis();

System.out.println("start : " + start);

conn.setConnectTimeout(5000);

conn.setReadTimeout(1000);

conn.setDoOutput(true);

conn.getOutputStream();

System.out.println(conn.getConnectTimeout());

} catch (MalformedURLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

end = System.currentTimeMillis();

System.out.println("end : " + end);

System.out.println("delay time : " + (end - start));

e.printStackTrace();

}finally{

conn.disconnect();

 

}

 

위코드는  보면 아시겠지만 5초의 타임아웃을 둔것이고, 

default로 conn.setConnectTimeout(5000); 주석처리하고 기본설정으로 동작하면 결과는 아래와 같다.

 

결과

start : 1383367909501

end : 1383367930526

delay time : 21025

 

java.net.ConnectException: Connection timed out: connect

 

대략 21초정도 시간이 걸렸다.

 


다시 위와 같은 코드에서 conn.setConnectTimeout(5000); 같은 설정으로 실행하면 잘 동작한다.

 

결과

start : 1383367472728

end : 1383367477746

delay time : 5018

 

java.net.SocketTimeoutException: connect timed out

 

그렇다면 이렇게 잘 동작하는데 왜 안되는 것일까?

 

문제는 url에 있다.

 

1. 만약 url 자체가 유효하지 않다면..

 

예를 들어

url = new URL("http://google.comm");

이러한 코드는 timout exception이 아닌  다른 exception을 내며 setConnectTimeout 과 관계가 없음을 알 수 있다.

 

결과

start : 1383368640946

end : 1383368643238

delay time : 2292

 

java.net.UnknownHostException: google.comm

 

이처럼 UnknownHostException는 차라리 빠른 시간내에 결과를 리턴하므로 다행이지만 다른 경우가 있을 수 있다.

 

2.url이 유효하더라도 이를 인식할 수 없다면..

 

url은 dns서버를 통해 해당 url의 실제 경로를 찾게 된다. 그런데 dns를 잘못 설정한다면 어떻게 될까?

 

dns를 바꿔보면 리눅스의 경우 /etc/resolve.conf , 윈도우의 경우 네트워크연결 - 인터페이스의 속성 - ipv4 protocal의 dns를 수정하면 된다.

 

테스트는 윈도우 리눅스 모두에서 진행해보았다.

 

 

url = new URL("http://google.com"); 

// 일반적인 상황에서 멀쩡한 주소인 구글님 -dns 주소 1.1.1.1로 잘못된 주소로 설정함.

 conn.setConnectTimeout(5000);

 

결과

start : 1383368927849

end : 1383368942127

delay time : 14278

 

java.net.UnknownHostException: google.com

 


같은 UnknownHostException 이지만 dns서버를 찾지못하는 경우에는 14초이상 걸렸다.

이럴때 사람들은 5초이내로는 커넥션이 끊어질거라고 기대하고 5초안에 정상적인 finally로 돌아오길 바라지만, 아닌 상황도 발생할 수 있다는 것이다.


이런경우 본의아니게  connection을 오래잡고 있어 서비스가 지연되거나  마비될 수 있다. 

 

 그렇다면 자세한 상황에 대해 패킷을 분석해 보도록하자.는 다음에


이상입니다!