Приложение 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 ответ
Существует несколько сценариев, когда дескрипторы файлов могут не закрываться:
- Там может быть какой-то другой код, который открывает файлы.
- Там может быть какой-то другой фрагмент кода, который вызывает
createChannel(...)
и не звонитfillContactBuffer(...)
Если
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()
, Некоторые низкоуровневые вызовы ввода / вывода реагируют на прерывание, генерируя исключение, и создаваемое здесь корневое исключение выглядит как одно из таких исключений.
Это не объясняет, почему это происходит, но я бы сказал, что это была серверная структура, которая пыталась решить проблему перегрузки или взаимоблокировки.