Java-приложение генерирует ClosedByInterruptException сразу при открытии сокета, причина? - PullRequest
2 голосов
/ 14 сентября 2011

У меня есть Java-приложение, которое поддерживает множество подключений к адресу, возможно, в пределах 2000 единиц, практически без активности, в основном открыто для целей мониторинга, время от времени пропуская несколько байтов.Когда нужно открыть новые соединения, он автоматически открывает их и добавляет их в свой пул.Однако иногда, по неизвестной причине, приложение получает ClosedByInterruptException сразу во время / после создания сокета для удаленного адреса.Насколько я знаю, это происходит только на стороне клиента в результате сигнала прерывания для потока.Я проверил и перепроверил исходный код, окружающий проблемную область, и кажется, что все в порядке.Я надеялся, что смогу получить чей-то опыт в отношении возможной альтернативной причины, например, помимо исходного кода, есть ли системная причина, которая вызывает это?Есть ли аппаратная причина?Уровень сервера / уровень маршрутизатора?Знание своей сети я бы посчитал любительским, но не слишком ли много 2К соединений для маршрутизатора или нет?

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;
}

1 Ответ

0 голосов
/ 15 сентября 2011

На какой ОС вы это запускаете? Я не знаю насчет Windows, но в Linux (и, вероятно, в других Unix-подобных ОС) у вас могут не хватать файловые дескрипторы, имея большое количество сокетов. Вы можете обойти это, выполнив ulimit -n 8192 или аналогичное перед запуском приложения Java. Или отредактируйте /etc/security/limits.conf и установите nofile. Все это говорит, ClosedByInterruptedException было бы странным способом заметить это.

Если вышеупомянутое не является проблемой, следующее, что я попробую, будет запускать tcpdump (если мы говорим о машине без GUI) или Wireshark (если мы нет) и захватывает трафик, генерируемый вашей программой, ища странные вещи, происходящие в момент установления соединения.

...