Подтвердить что ты не робот

System.IO.FileSystemWatcher для отслеживания папки сетевого сервера - соображения производительности

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

Я не могу написать службу для запуска на сервере (вне пределов!), поэтому решение должно быть локальным для клиента. Своевременность не имеет особого значения. Я могу жить с минутной или более поздней задержкой в ​​уведомлениях. Я наблюдаю за Create, Delete, Rename и Changes.

Будет ли использование .NET System.IO.fileSystemWatcher создавать большую часть загрузки на сервере?

Как насчет 10 отдельных наблюдателей, чтобы сократить количество папок/файлов, просматриваемых? (до 200 из 700 папок, 1200 из 5500 файлов) Больше сетевого трафика, а не меньше? Мои мысли - это перестановки на сервере, чтобы поместить наблюдаемые файлы в 1 дерево. Возможно, у меня не всегда есть этот вариант, поэтому команда наблюдателей.

Я полагаю, что другое решение является периодической проверкой, если FSW создает чрезмерную нагрузку на сервер или если он не работает для целого ряда причин типа SysAdmin.

Есть ли лучший способ сделать это?

4b9b3361

Ответ 1

С точки зрения загрузки сервера, использование IO.FileSystemWatcher для удаленных уведомлений об изменениях в описываемом вами сценарии, вероятно, является наиболее эффективным из возможных методов. Он использует функции WinF API FindFirstChangeNotification и WinD API ReadDirectoryChangesW для внутренних целей, которые, в свою очередь, обмениваются данными с сетевым перенаправителем оптимизированным образом (при условии использования стандартных сетей Windows: если используется сторонний перенаправитель и он не поддерживает требуемые функции, выигранные вещи не работает вообще). Оболочка .NET также использует асинхронный ввод-вывод и все остальное, еще больше обеспечивая максимальную эффективность.

Единственная проблема с этим решением состоит в том, что оно не очень надежно. Помимо необходимости иметь дело с временным разрывом сетевых подключений (что не является большой проблемой, поскольку IO.FileSystemWatcher будет инициировать событие ошибки в этом случае, которое вы можете обработать), базовый механизм имеет определенные фундаментальные ограничения. Из документации MSDN для функций Win32 API:

  • Сбой ReadDirectoryChangesW с ошибкой ERROR_INVALID_PARAMETER происходит, когда длина буфера превышает 64 КБ, и приложение отслеживает каталог по сети. Это связано с ограничением размера пакета базовыми протоколами обмена файлами.

  • Уведомления не могут быть возвращены при вызове FindFirstChangeNotification для удаленной файловой системы

Другими словами: при высокой нагрузке (когда вам потребуется большой буфер) или, что еще хуже, при случайных неуказанных обстоятельствах вы можете не получить ожидаемые уведомления. Это даже проблема с локальными наблюдателями файловой системы, но это гораздо большая проблема по сети. Еще один вопрос здесь, посвященный SO, более подробно описывает врожденные проблемы с API.

При использовании наблюдателей файловой системы ваше приложение должно справляться с этими ограничениями. Например:

  • Если файлы, которые вы ищете, имеют порядковые номера, сохраните последний порядковый номер, о котором вы получили уведомление, чтобы вы могли искать "пробелы" в будущих уведомлениях и обрабатывать файлы, о которых вы не получали уведомления;

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

Настройка нескольких слушателей - это то, чего вам следует избегать, насколько это возможно: во всяком случае, это сделает вещи еще менее надежными...

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

Итак, если у вас есть другие варианты (по сути, если процесс записи файлов уведомляет вас не на основе файловой системы: любой обычный метод RPC будет улучшением...), то это определенно стоит рассмотреть с точки зрения надежности. зрения.

Ответ 2

Я использовал наблюдателей файловой системы из С# несколько раз. В первый раз, когда я их использовал, у меня были проблемы с их прекращением работы, главным образом из-за того, что я обрабатывал изменения в потоке, сообщавшем об этом изменении.

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

Однако я не использовал это с вашей проблемой масштаба.

Ответ 3

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

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

Ответ 4

Документация MSDN указывает, что вы можете использовать компонент FileSystemWatcher для просмотра изменений файловой системы в сетевом диске,

Он также указывает, что компонент наблюдателя прослушивает уведомления об изменении файловой системы, а не периодически запрашивает целевой диск для изменений.

Исходя из этого, объем сетевого трафика полностью зависит от того, сколько вы ожидаете изменения содержимого этого сетевого диска. Компонент FSW не будет добавлять уровень сетевого трафика.

Ответ 5

Watcher выглядит на 100% надежным - просто посмотрите размер буфера на объект наблюдателя. Я тестировал тысячи обновлений файлов, не потерял.

Я рекомендую использовать многопоточный подход. Триггер является наблюдателем файлов. Он может запускать поток для каждого обнаруженного изменения файла. Наблюдатель может обрабатывать намного быстрее с меньшей вероятностью переполнения. (используйте Async-поток)

Ответ 6

После использования System.IO.FileSystemWatcher в течение некоторого времени. Он недостаточно стабилен для обработки событий, которые происходят слишком быстро. Для обеспечения 100% чтения файлов. Я использую простые методы каталогов для поиска по файлам. Прочитав его, сразу скопируйте файлы в другую папку. Чтобы изолировать его от новых файлов, добавляемых во время чтения файлов.

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

var fileNames = Directory.GetFiles(srcFolder);
foreach (string fileName in fileNames)
{
   string[] lines = File.ReadAllLines(fileName);
}

Ответ 7

Я бы не думал, что есть какое-либо активное состояние или связь между компьютером с FSW и компьютером, чье местоположение контролируется. Другими словами, FSW не проверяет сетевую ОС для проверки файла.

Можно предположить, что сообщение или событие only поднято/отправлено в сетевую FSW при возникновении изменения.

Но это все просто спекуляция.:)