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

Итак, у меня есть приложение, которое работает поверх сетки и работает довольно успешно в течение 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

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(), Некоторые низкоуровневые вызовы ввода / вывода реагируют на прерывание, генерируя исключение, и создаваемое здесь корневое исключение выглядит как одно из таких исключений.

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

Другие вопросы по тегам