2011-09-14 2 views
2

나는 거의 모든 활동을 제외하고 즉시 한 번에 2,000의 야구장에서 열린 주소로 많은 연결을 유지하는 Java 응용 프로그램을 가지고 있습니다. 대부분 모니터링 목적으로 열 때마다 몇 바이트를 전달합니다. 새 연결을 열어야 할 때 자동으로 연결을 열어 풀에 추가합니다. 때로는 알 수없는 이유로 응용 프로그램이 원격 주소에 대한 소켓을 만드는 동안/후에 즉시 ClosedByInterruptException을 수신합니다. 가장 잘 알고있는 한, 스레드에 대한 인터럽트 신호의 결과로 클라이언트 측에서만 발생합니다. 문제 영역을 둘러싼 소스 코드를 확인하고 다시 확인해 보니 괜찮습니다. 예를 들어, 소스 코드 외에도 다른 원인이있을 수 있는지에 대해 누군가의 전문 지식을 얻을 수 있기를 바랬습니다. 시스템 원인으로 인해이 문제가 발생 했습니까? 하드웨어 원인이 있습니까? 서버 수준/라우터 수준? 내 네트워크 지식 나는 아마추어를 고려할 것이지만, 라우터에 2K 연결이 너무 많거나 없습니까?소켓을 열면 Java 응용 프로그램이 ClosedByInterruptException을 throw합니다. 원인은 무엇입니까?

INFO [08 Sep 2011 23:11:45,982]: Reconnecting id 20831 
ERROR [08 Sep 2011 23:11:45,990]: IOException while creating plain socket channel 
java.nio.channels.ClosedByInterruptException 
    at java.nio.channels.spi.AbstractInterruptibleChannel.end(AbstractInterruptibleChannel.java:184) 
    at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:518) 
    at com.*.createSocketChannelPlain(MyTask.java:441) 
    at com.*._executeTask(MyTask.java:176) 
    at com.*.executeTask(MyTask.java:90) 
    at com.*.ThreadPool$WorkerThread.run(ThreadPool.java:55) 
ERROR [08 Sep 2011 23:11:45,990]: Could not open socket 
WARN [08 Sep 2011 23:11:45,990]: WorkerThread_24 received interrupted exception in ThreadPool 
java.lang.InterruptedException 
    at java.lang.Object.wait(Native Method) 
    at java.lang.Object.wait(Object.java:485) 
    at com.*.TaskQueue.getTask(TaskQueue.java:39) 
    at com.*.ThreadPool$WorkerThread.run(ThreadPool.java:48) 

업데이트 : 내가 시도하고 다른 사람이 진단에 기여하기 위해 내가 할 수있는 모든을 제공하고 싶습니다. 그래서 여기에 예외가 발생하는 실제 함수가 있습니다. 차이점은 라인 441에 추가 한 라인 마킹뿐입니다.

private SocketChannel createSocketChannelPlain() throws TaskFailedException { 
    SocketChannel socketChannel = null; 
    try { 
     // Create a non-blocking socket channel to use to communicate for imap connection 
     socketChannel = SocketChannel.open(); 
     socketChannel.configureBlocking(false); 
     try {socketChannel.socket().setSoLinger(true, 0);} catch (Exception e) {} 
     try {socketChannel.socket().setKeepAlive(true);} catch (Exception e) {} 
     /*Line 441*/ socketChannel.connect(new InetSocketAddress(_HOSTNAME, _PORT)); 
     //System.out.println("Started connection"); 

     // Complete connection 
     while (!socketChannel.finishConnect()) { 
      // do something until connect completed 
      try { 
       //do what you want to do before sleeping 
       Thread.sleep(500);//sleep for 500 ms 
       //do what you want to do after sleeping 
      } catch(InterruptedException ie){ 
       //If this thread was interrupted by another thread 
       try { socketChannel.close(); } catch (Exception e) {} 
       finally { socketChannel = null; } 
       break; 
      } 
     } 
     //System.out.println("Finished connecting"); 

     return socketChannel; 
    } catch (IOException e) { 
     logger.error("IOException while creating plain socket channel to gmail", e); 
     try { socketChannel.close(); } catch (Exception e1) {} 
     finally { socketChannel = null; } 
     //throw new TaskFailedException("IOException occurred in createSocketChannel"); 
    } 
    return socketChannel; 
} 

답변

0

어떤 OS를 실행하고 있습니까? 나는 윈도우에 대해서는 잘 모르지만 리눅스 (아마도 다른 유닉스 계열의 OS)에서는 많은 수의 소켓을 가지고 파일 핸들을 다 쓸 수있다. Java 응용 프로그램을 실행하기 전에 ulimit -n 8192 또는 이와 비슷한 방법으로이 문제를 해결할 수 있습니다. 또는 /etc/security/limits.conf을 편집하고 nofile으로 설정하십시오. 그 말은 모두 ClosedByInterruptedException이이를 알리는 이상한 방법 일 것입니다.

위의 내용이 문제가되지 않는다면 다음 시도는 tcpdump (GUI가없는 시스템에 대해 이야기하는 경우) 또는 Wireshark (실행하지 않는 경우)을 실행하는 것입니다. 프로그램이 생성되는 동안 트래픽이 발생하여 연결이 시작될 때 발생하는 이상한 일들을 찾습니다.

+0

리눅스 데비안입니다. 나는 사실 파일 설명자 문제를 겪기 시작했고 예외적 인 설명은 계속해서 "나쁜 호스트 이름"이었다. 그 이후로 제한을 상당히 높이기 위해 시작 스크립트를 설정했습니다. 'tcpdump'는 실제로 아직 시도하지 않은 훌륭한 아이디어입니다. – casey

+0

sysadmin이 나에게 tcpdump하지 못하게했다. 나중에 개인 시스템에서이 것을 시험해 봐야 할 것이다. – casey

+0

아니면 명령을 주면 명령을 내릴 수 있습니까? 'tcpdump -i any -s 0 -w /tmp/casey.pcap port 80'은 거의 맞을 것입니다. 어쩌면 다른 사람의 트래픽을 덤핑하는 것을 피하기 위해 Google의 네트워크와 소스 IP를 제한으로 추가 할 수 있습니다. –

관련 문제