Назад | Перейти на главную страницу

Сбой моего диска с использованием Java

У меня есть программа Java, которая должна делать следующие 3 вещи:

  1. Загрузите файл с веб-сайта.
  2. Запустите файл через testA и testB (оба в java)
  3. Удалите файл и сохраните результаты теста на диск.

Это сделано примерно для 1 000 000 различных сайтов. Задача должна была быть довольно простой, так как я просто склеивал детали из других программ: testA и testB и то, и другое уже выполнялось отдельно для десятков миллионов различных страниц без проблем, и процедура загрузки страниц также выполнялась для миллиона или около того страниц несколько раз и никогда не имела никаких проблем. Все они выполняются на машине Ubuntu 10.4.

Однако при выполнении этих трех операций один за другим, на какой бы диск ни записывались файлы, происходит сбой. В первый раз я запустил его на внешнем USB-накопителе, который мне пришлось вручную отключить и снова подключить, чтобы он возобновил работу (иначе Linux не распознал бы его). В следующий раз на внутреннем жестком диске вся система вышла из строя, и мне пришлось перезапустить ее вручную. То же самое произошло при записи на RAM Disk.

Проблема в том, что я не могу изолировать проблему. Для возникновения сбоя требуется слишком много времени (около 50 часов или около того, но это довольно случайное явление), поэтому тестирование занимает слишком много времени, и в системных журналах сбоя нет сведений, указывающих, где и как это происходит. Аппарат или HD просто перестают отвечать.

Кроме вылета все работает нормально. Файлы создаются и удаляются нормально, потоки не умирают и не выполняются должным образом, и оба теста работают нормально. Изменение памяти или количества потоков не повлияло на время блокировки. Я уже проверил, не закрываются ли сокеты или что-то подобное, но я даже не знаю, как начать тестирование, я понятия не имел, что аварийное завершение системы станет катастрофическим с Java.

РЕДАКТИРОВАТЬ: Под зависанием я подразумеваю, что когда я запускаю его на внешнем жестком диске, жесткий диск не распознается Linux, а когда я запускаю его на внутреннем жестком диске или RAM-диске, компьютер вообще не реагирует на какие-либо операции ввода-вывода, при этом ничего не записывается на диск, журналы cactii не записываются и т. д. Невозможно подключиться, например, по SSH.

Пример того, как работает программа:

List<String> pagesToDownload = getFromDataBase();
for(i=0;i<NumThreads;i++){
    launchTestThread();
}

А затем в каждом потоке:

String pageName = getNextPageToDownload();
File downloadedFile = downloadPage(pageName);
TestAResults testAResults = runTestA(downloadedFile);
TestBResults testBResults = runTestB(downloadedFile);
writeToDatabase(downloadedFile, testAResults, testBResults);
downloadedFile.delete();

Индивидуально функции runTestA, runTestB и downloadedPage работают с еще большим количеством файлов, но при таком вызове - нет. И это на том же самом оборудовании.

РЕДАКТИРОВАТЬ2: Думаю, я исключил, что проблема в оборудовании. Такое же аппаратно-интенсивное программное обеспечение работало на одной и той же машине последние 7 дней без каких-либо проблем. В любом случае, как только я получу неиспользуемую машину, я протестирую на ней программу.

Кроме того, все в тесте записывается в базу данных до момента, когда происходит сбой, и данные верны. В downloadedFile не передается в качестве параметра во время метода writeToDatabase, только его имя и размер.

Наконец, я провел тщательную проверку на предмет утечек памяти или файловых обработчиков и не обнаружил их, в том числе внутри рабочих тестов. Сейчас у меня деньги на какой-то странный баг с удалением файлов.

РЕДАКТИРОВАТЬ3: Наконец-то мне удалось достать еще одну машину, на которой можно было проверить программу. Другое оборудование, но та же версия Ubuntu (10.4 LTS). И там тоже происходит сбой, поэтому я действительно сомневаюсь, что это проблема с оборудованием. Это оставляет либо ошибку ОС, либо ошибку JVM, либо ошибку программирования (нет JNI или чего-то подобного). Я собираюсь попробовать запустить тест в какой-нибудь другой среде (настроить тест во FreeBSD будет довольно просто, и я могу попытаться найти машину с Windows, чтобы проверить это), чтобы проверить это.

РЕДАКТИРОВАТЬ4: Отвечая на вопрос Боба Кросса о размере файлов, это типичные веб-страницы, средний размер которых составляет около 20 КБ. Я должен удалить их, так как идея состоит в том, чтобы расширить приложение, сделав невыносимым использование диска. Но я собираюсь попробовать бесплатный запуск Deletion, как только смогу. Машина, на которой я проводил эти тесты, используется прямо сейчас, и мне трудно достать простаивающее оборудование.

Если система перестает отвечать, это ошибка в операционной системе или проблема с оборудованием. Программа не должна уметь зависать в системе, даже если она содержит ошибки.

Запустите вашу программу в другой системе и посмотрите, предоставляет ли она полезную диагностику для вашей программы, вместо того, чтобы просто отказываться.

С приведенным выше резюме немного сложно понять, что именно вы делаете, но я попытаюсь сделать предположение на основе этого абзаца:

Однако при выполнении этих трех операций один за другим, на какой бы диск ни записывались файлы, происходит сбой. В первый раз я запустил его на внешнем USB-накопителе HD, который мне пришлось вручную отключить и снова подключить, чтобы он возобновил работу (иначе Linux не распознал бы его). В следующий раз на внутреннем жестком диске вся система вышла из строя, и мне пришлось перезапустить ее вручную. То же самое произошло при записи на RAM Disk.

Как вы управляете своим файлом результатов относительно этого списка из миллионов сайтов, который вы проверяете? В частности, выглядит ли ваш код так (далее следует абстрагированный псевдокод):

  1. Откройте файл результатов.
  2. Цикл начинается: для каждого из миллиона сайтов
  3. TestA на сайте
  4. TestB на месте: цикл заканчивается
  5. Запишите результаты тестов сайта в файл результатов.

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

Если это то, что вы делаете, попробуйте следующее:

  1. Цикл начинается: для каждого из миллиона сайтов
  2. TestA на сайте.
  3. TestB на сайте.
  4. Откройте файл результатов.
  5. Запишите результаты тестирования сайта в файл результатов.
  6. Закрыть файл результатов: цикл заканчивается

Это должно гарантировать, что после каждого теста вы записываете результат в файл. Как минимум, вы должны иметь возможность наблюдать за процессом своей программы.

РЕДАКТИРОВАТЬ: продолжение редактирования вопроса:

writeToDatabase(downloadedFile, testAResults, testBResults); 

Два вопроса:

  1. Записываются ли когда-либо изменения в вашу базу данных? То есть они какое-то время пишут, а потом останавливаются? Или база данных полностью пуста?

  2. Неужели так написан код? Если это так, у вас есть потенциальная утечка памяти: эта ссылка на файл передается в ваш writeToDatabase метод. Вы уверены, что на эту ссылку ничего не стоит?

Возможно, вы удерживаете слишком много дескрипторов файлов из-за утечки ссылок на файлы и / или собственных дескрипторов файлов. Стоит проверить.

ИЗМЕНИТЬ СНОВА на основе дополнительных отзывов:

Сейчас у меня деньги на какой-то странный баг с удалением файлов.

Это возможность. Некоторые вещи для размышления:

  1. Насколько велики файлы, которые вы загружаете? Не могли бы вы попробовать выполнить отладку без удалений? Если вы будете работать дольше без этого кода, это, безусловно, будет интересным результатом.

  2. Меня все еще беспокоит, что у вас утечка файловых дескрипторов. Если вы проверите количество обработанных файлов и обнаружите какое-то подозрительное количество обработанных файлов, кратное 1024, я бы более внимательно посмотрел на то, что есть в методе удаления. Без реализации, конечно, сложно сказать.

Без дополнительной информации я предполагаю, что вы заполнили свой диск. Отсутствие возможности подключиться через SSH немного странно, но возможно, если вы не можете писать auth.log.

... сложно сказать без конкретной информации.

Все ли потоки ввода-вывода закрыты после записи файлов? Установлены ли у вас ограничения ввода-вывода в unix? Есть ли проблема с параллелизмом, потому что они изменяют файлы одновременно? Возможно, вы также можете время от времени делать несколько Thread.sleep (...), чтобы не перегружать диски.

... но на самом деле я понятия не имею, это всего лишь мои два цента.