Приложение Java Gridgain начинает давать сбой после 1 дня стресс-тестирования

Итак, у меня есть приложение, которое работает поверх gridgain и делает это довольно успешно в течение примерно 12-24 часов стресс-тестирования, прежде чем оно начинает вести себя забавно. По истечении этого периода времени приложение внезапно начнет отвечать на все запросы, за исключением java.nio.channels.ClosedByInterruptException (полная трассировка стека находится по адресу http://pastie.org/664717

Метод, из-за которого происходит сбой, (отредактировано для использования обратной связи @stephenc)

public static com.vlc.edge.FileChannel createChannel(final File file) {
    FileChannel channel = null;
    try {
    channel = new FileInputStream(file).getChannel();
    channel.position(0);
    final com.vlc.edge.FileChannel fileChannel = new FileChannelImpl(channel);
    channel = null;
    return fileChannel;
    } catch (FileNotFoundException e) {
    throw new VlcRuntimeException("Failed to open file: " + file, e);
    } catch (IOException e) {
    throw new VlcRuntimeException(e);
    } finally {
    if (channel != null) {
        try {
        channel.close();
        } catch (IOException e){
        // noop
        LOGGER.error("There was a problem closing the file: " + file);
        }
    }
    }
}

и вызывающая функция корректно закрывает объект

private void fillContactBuffer(final File signFile) {
    contactBuffer = ByteBuffer.allocate((int) signFile.length());
    final FileChannel channel = FileUtils.createChannel(signFile);
    try {
        channel.read(contactBuffer);
    } finally {
        channel.close();
    }
    contactBuffer.rewind();
}

Приложение в основном служит распределенным синтаксическим анализатором файлов, поэтому оно выполняет множество таких операций (обычно открывает около 10 таких каналов на запрос на узел). Кажется, что через определенный период он перестает открывать файлы, и я не могу объяснить, почему это может происходить, и был бы очень признателен любому, кто может сказать мне, что может быть причиной этого и как я могу отслеживать его вниз и фиксации его. Если это, возможно, связано с исчерпанием дескриптора файла, я хотел бы услышать какие-либо советы, чтобы узнать наверняка... то есть запросить JVM во время ее работы или использовать инструменты командной строки linux, чтобы узнать больше информации о том, какие дескрипторы в настоящее время открыты .

обновление: я использовал инструменты командной строки для опроса вывода lsof и не смог увидеть никаких доказательств того, что дескрипторы файлов остаются открытыми... каждый узел в сетке имеет очень стабильный профиль открытых файлов, который, как я вижу, меняется по мере выполнения приведенного выше кода... но он всегда возвращается к стабильному количеству открытых файлов.

Связано с этим вопросом: Освобождение дескрипторов файлов Java


person Jamie Cook    schedule 22.10.2009    source источник


Ответы (1)


Существует несколько сценариев, в которых дескрипторы файлов могут не закрываться:

  1. Там может быть какой-то другой код, который открывает файлы.
  2. Может быть какой-то другой фрагмент кода, который вызывает createChannel(...) и не вызывает fillContactBuffer(...).
  3. Если channel.position(0) выдаст исключение, канал не будет закрыт. Исправление состоит в том, чтобы изменить код таким образом, чтобы следующие операторы находились внутри блока try.

    channel.position(0);
    return new FileChannelImpl(channel);
    

РЕДАКТИРОВАТЬ: Глядя на трассировку стека, кажется, что эти два метода находятся в разных кодовых базах. Я бы указал пальцем на метод createChannel. Он потенциально негерметичен, даже если он не является источником ваших проблем. Требуется внутреннее предложение finally, чтобы убедиться, что канал закрыт в случае исключения.

Что-то вроде этого должно помочь. Обратите внимание, что вам нужно убедиться, что блок finally не закрывает канал в случае успеха!

public static com.vlc.edge.FileChannel createChannel(final File file) {
    final FileChannel channel = null;
    try {
        channel = new FileInputStream(file).getChannel();
        channel.position(0);
        FileChannel res = new FileChannelImpl(channel);
        channel = null;
        return res;
    } catch (FileNotFoundException e) {
        throw new VlcRuntimeException("Failed to open file: " + file, e);
    } catch (IOException e) {
        throw new VlcRuntimeException(e);
    } finally {
        if (channel != null) {
            try {
                channel.close();
            } catch (...) {
                ... 
            }
        }
    }
}

ПОСЛЕДУЮЩИЕ намного позже

Учитывая, что утечка дескриптора файла была устранена как возможная причина, моя следующая теория будет заключаться в том, что серверная сторона фактически прерывает свои собственные потоки, используя Thread.interrupt(). Некоторые низкоуровневые вызовы ввода-вывода реагируют на прерывание, генерируя исключение, и корневое исключение, генерируемое здесь, выглядит как одно из таких исключений.

Это не объясняет, почему это происходит, но я бы предположил, что это была серверная структура, пытающаяся решить проблему перегрузки или взаимоблокировки.

person Stephen C    schedule 22.10.2009