Java

SocketException "Connection time out" 왜 나는 걸까..

_침묵_ 2006. 4. 24. 20:17
출처 : http://www.javaservice.net/~java/bbs/read.cgi?m=etc&b=unix&c=r_p&n=1005116773&p=10&s=t#1005116773

제목 : SocketException "Connection time out" 왜 나는 걸까요?
글쓴이: 손님(guest) 2001/11/07 16:06:13 조회수:1911 줄수:68
인터넷 뱅킹 Connection 문제점

환경 

1. 접속환경
                 FireWall    L4 Switch           
                    |           |
    인터넷      ----|-----------|------> (8401)  운영
                    |           |
    뱅킹(UNIX)  ----|-----------|------> (8402)  시스템(UNIX)
                    |           |
                    |           |

인터넷 뱅킹에서 FireWall과 L4 Switch를 통해
운영시스템에 접속 

인터넷 뱅킹은 클라이언트 소켓(C), 운영시스템은 서버 소켓(Java)

2. 데이터 전송 형태
                 FireWall    L4 Switch           
                    |           |
    인터넷      ----|-----------|------> (8401)  운영
                    |           |
    뱅킹(UNIX)  <---|-----------|------  (8402)  시스템(UNIX)
                    |           |
                    |           |


인터넷 뱅킹은 포트 8401을 통하여 데이터를 전송하고
운영 시스템은 8401을 통하여 데이터를 수신하고 8402
포트를 통하여 데이터를 송신

3. 문제점
                 FireWall    L4 Switch           
                    |           |
    인터넷      ----|-----------|------> (8401)  운영
                    |           |
    뱅킹(UNIX)  <---|-----------|xxxxxx  (8402)  시스템(UNIX)
                    |           |
                    |           |

어떤 데이타 송수신 없는 상태에서
일정시간이 흐른후(대략 2시간) 운영 시스템으로 부터
인터넷뱅킹으로 송신되는 데이터 라인이 인터넷 뱅킹 요청을
수신(8401)한 후 송신시 SendQ에 해당 데이터가 쌓이게되는
현상 발생 (아래 netstat 출력 참조)
tcp        0    128  cardt1.8402        15.32.40.12.52308         ESTABLISHED
tcp        0      0  *.8401             *.*                       LISTEN
tcp        0      0  *.8402             *.*                       LISTEN
tcp        0      0  cardt1.8401        15.32.40.12.52307         ESTABLISHED

sendQ에서 데이터가 쌓인 후 일정시간(대략 5분)이 흐른후
java java.net.SocketException 발생( message: Connection time out )하면서
해당 프로세스 종료
실제 데이타 송신 시 java Application은 실제 에러 발생여부를 확인할 수 없음.

특이사항 : 실제 운영시스템쪽에는 해당 포트가 사라졌음에도 불구하고
           인터넷뱅킹 쪽에는 해당 포트가 ESTABLISHED된 상태로 나타남.

4. java source

4.1 Listen Server Source
(첨부파일 참조)
Download Bczi12Bean.java (14474 Bytes) Bczi12Bean.java (14474 Bytes)


제목 : Re: TCP/IP ESTABLISHED & Connection Timeout
글쓴이: 이원영(javaservice) 2001/11/08 14:05:47 조회수:10035 줄수:181
저 역시 지금 유사한 문제에 직면하여 골머리를 썪히고 있습니다.
몇가지 정보를 공유하고자 합니다.


모 사이트에서의 경우는 다음과 같은 구성이 있습니다.

1. H/W, S/W 상황

머신A
IBM RS6000(4-way,2GB) AIX 4.3.3
IBM WebSpehre Application Server 3.5.4
IBM JDK 1.2.2 FP11

머신B
SUN E3500 solaris version ?
Solaris Default FTP Server

머신A 는 해당 고객사의 eCRM서버로서, Servlet을 통해 요청을 받고, JDBC로 DB2를
접근하여 필요로하는 정보를 획득한 후, 그 대량의 정보를 타회사의 FTP서버로
DM 발송하는 것으로써, Servlet 에서 sun.net.ftp.FtpClient 라는 JDK 내부 API로
타 회사의 FTP서버로 데이타를 전송하는 업무입니다.
회사가 다르다 보내, 내부 방화벽과 라우터를 거쳐 인터넷으로 나가고, 외부 회사 역시
라우터와 방화벽이 있을 것입니다.
일반적인 상황에서는 대부분 10초 이내에 끝이나는 업무 입니다.

2. 문제 현상

Application Server 에서 HTTP요청을 모니터링 할 수 있는 requestmon 이라는 모듈을
통해 실시간으로 현재수행중인 서비스를 관찰하고 있는데, 유독 이러한 DM발송업무가
몇개씩 짧개는 몇시간, 길게는 며칠동안이나 끝나지 않고 수행중인채로 남아 있는
것이 있더라는 것입니다.
머신A에서 "netstat -n"으로 확인해 본 결과, 그렇게 걸려 있는 서비스 개수와
타 회사로 TCP/IP 21 번 port 로 연결되어 있는 갯수와 정확히 일치하였습니다.
중요한 것은 머신A에서는 ESTABISHED 로 나타난다는 것입니다.
그러나, 막상 타회사 머신B에 telnet으로 들어가서 "netstat -n"을 해 보면,
전혀 ESTALISHED 된 것이 없었습니다.

머신A

머신B

PS:물론 머신B 입장에서는 머신A의 IP가 Local IP이기 때문에,  원격지로부터 들어오는
Real IP는 그 쪽 방화벽의 NAT(Network Address Translation)를 통해 변경된 대표IP로
보이게 될 것입니다.


3. Java와 관련된 이슈

java.io.InputStream 이나 FilterInputStream 류의 read(...) 메소드는 항상  마지막에는
java.net.SocketInputStream 의 socketRead()라는 JNI native 메소드를 호출합니다.
java.net.SocketInputStream은 JDK의 documents 에는 나오지 않는 숨어있는 내장 클래스
입니다. 이 메소드를 사용하는 상위 클래스(InputStream, FilterInputStream)의
documents를 보면 공통적으로 해당 소켓에서 읽을 data 가 available 할 때까지 
blocking 된다는 표현이 있습니다.

 public int read(byte b[],
                 int off,
                 int len) throws IOException

 Reads up to len bytes of data from this input stream into an array of bytes. 
 This method blocks until some input is available

여기서, 만약, Local 머신의 TCP/IP status가 ESTABLISHED 였다면, 어쩌면 이 메소드에서
"some input is available" 할 때까지 , 극히 정상적으로, blocking 되어 있을 수 있다는
것이지요.
IBM PMR을 서치하다보면, JVM Thread Dump 에 java.net.InputStream.socketRead() 
메소드에서 blocking 되어 있는 경우를 종종 볼 수 있습니다.

이 문제는 IBM JDK, AIX, TCP/IP 혹은 F/W, router 설정 등을 의심해 보아야 하는 문제일
가능성이 가장 높습니다. 현재로서는 (저는) 설령 F/W이나 router 에서 잘못됐더라도, 
AIX의 TCP/IP 레벨에서는 그 상황을 catch 해 내어  "some input is available" 일 때까지
blocking 되도록 할 것이 아니라 IOExcepiton을 발생시켜줄 수 있도록  AIX TCP/IP에서의
ESTABLISHED 상태를 해제시켜 주어야 할 것으로 보이며, 결국 AIX 의 버그 아니겠느냐라는
의구심을 가져 봅니다.

이 문제는 비단 그곳 모사이트뿐만 아니라 다른 몇몇 사이트에서도 유사한 현상을 얘기한
적이 있으며, 또, 몇몇 AIX/WebSphere 기반의 웹서비싱 사이트에서, 고객의 극히
정상적인 HTTP 80 port 에 대한 socketRead(), 그리고, nativeWrite() 함수에서 blocking
되어, 몇날 동안이나 해당 서비스가 끝나지 않고 걸려 있는 현상이, 많은 부분에서 유사성을
찾을 수 있습니다.


4. 왜 2시간?

앞서 글을 올린 분의 경우, "요청없이 2시간 정도 지난 후에..."라는 표현이 있는데,
어쩌면 그 부분은 아래 부분과 관련이 있지 않을까요?

Solaris/Linux 의 경우:
  # ndd -get /dev/tcp \?
  # ndd -get /dev/tcp  tcp_keepalive_interval
  default 7200000, minimum 10000  (단위 1/1000초, 7200000 = 7200초 = 2시간)

AIX의 경우 : 
  # no -a
  ......
  tcp_keepidle = 14400 
  ....
  
  (단위는 1/2초, 즉 14400 = 7200초 = 2시간)

이 처럼 2시간인 이유는 RFC1122 규약상 default 가 2시간이기 때문입니다. 즉, idle 한
상태로 최대 active 되어 있을 수 있는 시간은 2시간이라는 것이지요. 


5. 왜 5 분 ?

 모르겠습니다. 만약, 최초에 Socket 을 Open 시점에 발생한 것이라면, TCP/IP파라메터에
 그 시간을 설정하는 곳이 있습니다만, 이미 ESTABLISHED 된 Socket connection 에서
 write 시에 Connection timeout 이 발생하는 그 시간 설정은 어디에서 영향을 받고 있는
 지 모르겠습니다.


6. 방화벽/스위치 장비와의 관계?

 모 사이트 튜닝 때문에 확인한 사실이지만, 방화벽에서도 "세션"이라는 것이 있습니다.
 첫 요청이 들어오면, 그 패킷을 분석해서, source ip/port , destnation ip/port를
 세션테이블에 기록한 후 통과시키며, 관련된 응답패킷이 반대방향에서 오면 기존에
 세션테이블을 뒤져서 정상적인 허용된 패킷에 대한 응답일 경우 그것을 통과시켜주게
 된다는 것이지요. 여기서, 세션테이블에 해당 정보가 남아 있는 시간을 지정해 줄 수
 있는데, 통상 30분인듯 합니다. 만약, 응답패킷이 설정이 세션Timeout시간이 지난 후에
 도착하게 되면, 세션테이블에 내용이 없으므로 해당 패킷을 내보내지 않고 deny 시켜
 버린다고 합니다.(정책은 변경할 수 있답니다)
 
 또한, L7 스위칭 장비의 경우, 여러 서버에 대한 로드발란싱을 하게 할 수 있는데,
 sticky port 는 기능이 있어서, 특정 IP/PORT로 날아온 요청에 대해서 지속적으로
 특정 서버로만 dispatching 되도록 하는 기능이지요(이런 기능은 특히 HttpSession을
 사용할 경우에 반드시 필요하게 됩니다.) 이것 역시 일정시간동안 어딘가에
 그 세션정보를 기록해 두어야, 좀전에 왔던 요청과 지금 들어온 요청이 같다는 것을
 확인할 수가 있겠지요. 문제는 역시 그 세션 Timeout 시간인데, default 상태는
 2시간이랍니다. 물론 telnet 23 번 port 나 FTP 21 번 port 에 대해서는 이 같은
 로드발란싱을 스위치 장비가 하지 않겠지만, HTTP 80 이나 HTTPS 443 port 는 영향을
 주고 있을 듯 합니다.



PS: 따라서, 이 시점에서는 이 문제를 해결하는데,TCP/IP 전문가의 도움이 절실히
  필요합니다.
 
PS: Solaris Tuning 문서
 http://www.sean.de/Solaris/tune.html


------------------------------------------------------------
2001.11.19 첨가사항

일전에, 집에서 밤늦게까지 작업을 한 적이 있었습니다. 집에는 최근에 구입한 PC가 안방에
설치되어 있고, 한국통신 ADSL로 인터넷에 물려 있습니다. 최근 PC가 그렇듯 Windwos Me이
OS로 탑재되어 있습니다. 이 PC에는 Windows Me가 제공하는 "네트웍공유기"를 통해 조그만
10Mbps 더미허브로 TCP/IP 공유가 되어 있고, 늘 갖고 다니는 Noteboot을 집에선 옆방에서
연결하여 작업하곤 합니다.(안방의 PC는 늘 와이프 차지이다 보니, 전 이렇게 옆방에서
작업합니다.)

그날 밤엔 SecureCRT라는 SSL Telnet (port 22번)으로 밤늦게까지 javaservice.net 서버에서
작업을 하였는데, 그만 잠이 들어 버렸죠. 아침에 일어나보니, 작업하던 telnet 화면은
그대로 남아 있었습니다. 근데, 세수하고 안방으로 가보니, ADSL로 물려 있던 PC의 전원이
꺼져 있더라구요. 집사람이 꺼버린 것이죠.

순간, Notebook 의 netstat 를 보고 싶었죠...
Windows NT 이니 "netstat -n" 명령이 먹잖습니까. 아니나 다를까, notebook 의
"netstat -n" 의 결과는 javaservice.net 과 ESTABLISHED 상태로 나타나고 있었습니다.
물리적으로 ADSL로 연결된 안방의 PC는 분명히 전원이 꺼져 있는 상태인데 말입니다.

telnet 화면에서 "엔터키"를 툭 치니, "연결이 끊어졌으니..."하는 문구가 나오고나서야
"netstat -n"값은 ESTABLISHED 상태가 사라졌습니다.

이것으로 보건데, OS의 TCP/IP status 는 뭔가 응용어플리케이션으로부터 event 가
발생되어야 그 TCP/IP status 를 변경하는 듯 합니다.

마찬가지로, TCP/IP 응용어플리케이션이 data 를 기다리는 상태에서, N/W중간의 F/W에서
더이상 여하한의 data 를 통과시키지 않게 되면, 이 같은 TCP/IP ESTABLISHED 상태가
남아 있을 수 있지 않을까요? 특히, Socket 으로부터 read()상태로 대기하고 있는
어플리케이션이라면, 영원히(?) waiting 하지 않을까요?....


================================================
  자바서비스넷 이원영
  E-mail: javaservice@hanmail.net
  PCS:011-898-7904
================================================

'Java' 카테고리의 다른 글

JNI 를 이용한 PID( Process ID )추출( 윈도우 기반 )  (0) 2006.05.12
자바를 이용한 SNMP  (1) 2006.04.17
JAVA와 C 사용(JNI)시 데이터형  (0) 2006.04.07