Особые соображения при выполнении файлового ввода-вывода на общем ресурсе NFS с помощью демона на основе Python? - PullRequest
7 голосов
/ 16 августа 2011

У меня есть демон на основе Python, который предоставляет REST-подобный интерфейс через HTTP для некоторых инструментов командной строки .Общая природа инструмента заключается в том, чтобы принять запрос, выполнить какое-либо действие командной строки, сохранить измененную структуру данных на диск и вернуть некоторые данные вызывающей стороне.При запуске демона создается вторичный поток, который периодически просматривает данные на диске и выполняет некоторую очистку, основываясь на том, что находится в данных.

Это прекрасно работает, если диск, на котором находятся данные, является локальнымдиск на машине Linux.Если вы переключаетесь на диск, смонтированный по NFS, демон начинает нормально работать, но со временем ресурс, смонтированный по NFS, «исчезает», и демон больше не может определить, где он находится на диске, с такими вызовами, как os.getcwd().Вы начнете видеть это, регистрируя ошибки как:

2011-07-13 09:19:36,238 INFO Retrieved submit directory '/tech/condor_logs/submit'
2011-07-13 09:19:36,239 DEBUG CondorAgent.post_submit.do_submit(): handler.path: /condor/submit?queue=Q2%40scheduler
2011-07-13 09:19:36,239 DEBUG CondorAgent.post_submit.do_submit(): submitting from temporary submission directory '/tech/condor_logs/submit/tmpoF8YXk'
2011-07-13 09:19:36,240 ERROR Caught un-handled exception: [Errno 2] No such file or directory
2011-07-13 09:19:36,241 INFO submitter - - [13/Jul/2011 09:19:36] "POST /condor/submit?queue=Q2%40scheduler HTTP/1.1" 500 -

Необработанное исключение разрешает демону больше не видеть диск.Любые попытки выяснить текущий рабочий каталог демона с os.getcwd() на этом этапе потерпят неудачу.Даже попытка перейти в корень NFS-монтирования /tech не удастся.Все это время методы logger.logging.* успешно записывают журнал и отлаживают сообщения в файл журнала, расположенный на смонтированном NFS-ресурсе по адресу /tech/condor_logs/logs/CondorAgentLog.

Диск наиболее определенно все еще доступен.Существуют и другие демоны на основе C ++, которые читают и пишут с гораздо более высокой частотой на этом ресурсе во время работы демона на основе Python.

Я зашел в тупик, отлаживая эту проблему.Поскольку он работает на локальном диске, общая структура кода должна быть хорошей, верно?Есть что-то в смонтированных на NFS общих ресурсах и моем коде, которые несовместимы, но я не могу сказать, что это может быть.

Существуют ли особые соображения, которые необходимо реализовать при работе с долго работающим демоном Python, которыйбудете часто читать и записывать в файловый ресурс, смонтированный в NFS?


Если кто-то захочет увидеть код, то часть, которая обрабатывает HTTP-запрос и записывает выбранный объект на диск, находится в github. здесь .И часть, которую подпоток использует для периодической очистки содержимого диска с помощью чтения маринованных объектов: здесь .

Ответы [ 2 ]

5 голосов
/ 08 сентября 2011

У меня есть ответ на мою проблему, и он не имеет ничего общего с тем, что я выполнял файловый ввод / вывод в общей папке NFS.Оказывается, проблема обнаружилась быстрее, если ввод-вывод был подключен через монтирование NFS по сравнению с локальным диском.

Ключевой информацией является то, что код выполнялся с помощью потоков SocketServer.ThreadingMixIn и HTTPServerклассы.

Мой код обработчика делал что-то похожее на следующее:

base_dir = getBaseDirFromConfigFile()
current_dir = os.getcwd()
temporary_dir = tempfile.mkdtemp(dir=base_dir)
chdir(temporary_dir)
doSomething()
chdir(current_dir)
cleanUp(temporary_dir)

Это поток, более или менее.

Проблема была не в том, что я/ O был сделан на NFS.Проблема была в том, что os.getcwd() не является локальным для потока, это глобальный процесс.Таким образом, поскольку один поток выдал chdir() для перемещения во временное пространство, которое он только что создал в base_dir, следующий поток, вызывающий os.getcwd(), получит temporary_dir другого потока вместо статического базового каталога, где был запущен HTTP-сервер.в.

Есть и другие люди, сообщающие о подобных проблемах здесь и здесь .

Решением было избавиться от chdir() и getcwd() звонков.Чтобы запустить и остаться в одном каталоге и получить доступ ко всему остальному через абсолютные пути.

NFS против локальных файлов через меня для цикла.Оказывается, мой блок:

chdir(temporary_dir)
doSomething()
chdir(current_dir)
cleanUp(temporary_dir)

работал намного медленнее, когда файловая система была NFS по сравнению с локальной.Это привело к возникновению проблемы намного раньше, поскольку увеличило вероятность того, что один поток все еще находился в doSomething(), пока другой поток выполнял часть current_dir = os.getcwd() блока кода.На локальном диске потоки проходили через весь блок кода так быстро, что они редко пересекались таким образом.Но, уделите этому достаточно времени (около недели), и проблема возникнет при использовании локального диска.

Итак, большой урок по работе с потоками в Python!

2 голосов
/ 17 августа 2011

Чтобы ответить на вопрос буквально, да, есть некоторые ошибки с NFS. E.g.:

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

  • В частности, вы не можете полагаться на O_APPEND для атомарного добавления файлов.

  • В зависимости от сервера NFS, O_CREAT | O_EXCL может не работать должным образом (по крайней мере, он работает должным образом в современном Linux).

  • Особенно старые серверы NFS имеют недостаточную или полностью нерабочую поддержку блокировки. Даже на более современных серверах восстановление блокировки может быть проблемой после перезагрузки сервера и / или клиента. NFSv4, протокол с состоянием, должен быть более надежным, чем старые версии протокола.

Все это говорит о том, что ваша проблема на самом деле не связана с чем-либо из вышеперечисленного. По моему опыту, демоны Condor будут в какой-то момент, в зависимости от конфигурации, очищать файлы, оставшиеся от выполненных заданий. Мое предположение будет искать здесь подозреваемого.

...