Приложение Java Gridgain начинает давать сбой после 1 дня стресс-тестирования - PullRequest
1 голос
/ 22 октября 2009

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

2 голосов
/ 22 октября 2009

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

  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 (...) {
                ... 
            }
        }
    }
}

FOLLOWUP намного позже

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

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

...