我有一个java应用程序,可以打开许多连接到一个地址,可能同时在2,000个球场,几乎没有任何活动,大多数用于监视目的,偶尔传递几个字节。当需要打开新连接时,它会自动打开它们并将它们添加到池中。但有时,由于未知原因,应用程序在创建到远程地址的套接字期间/之后立即收到ClosedByInterruptException。据我所知,这只发生在客户端,因为线程的中断信号。我检查并重新检查了问题区域周围的源代码,似乎没问题。我希望我可以获得某人的专业知识,如果可能有另一个原因,除了源代码,例如,是否有导致这种情况的系统原因?有硬件原因吗?服务器级别/路由器级别?我的网络知识我会考虑业余,但路由器的2K连接太多,或者没有?
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 :(得分:0)
你在运行什么操作系统?我不了解Windows,但是在Linux(可能是其他类Unix操作系统)上,你可以通过使用大量套接字来耗尽文件句柄。在运行Java应用程序之前,您可以通过执行ulimit -n 8192
或类似操作来解决此问题。或者,修改/etc/security/limits.conf
并设置nofile
。所有这些都说ClosedByInterruptedException
是一种奇怪的方式来注意这一点。
如果以上不是问题,我接下来要做的就是运行tcpdump
(如果我们谈论的是无GUI的机器)或Wireshark(如果我们不是)并捕获程序生成的流量,寻找连接开始时发生的奇怪事情。