System.IO.FileSystemWatcher для мониторинга папки сетевого сервера - Вопросы производительности - PullRequest
40 голосов
/ 30 сентября 2008

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

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

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

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

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

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

Ответы [ 7 ]

70 голосов
/ 30 сентября 2008

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

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

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

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

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

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

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

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

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

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

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

9 голосов
/ 01 октября 2008

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

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

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

3 голосов
/ 03 октября 2008

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

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

2 голосов
/ 30 сентября 2008

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

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

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

1 голос
/ 27 мая 2016

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

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

var fileNames = Directory.GetFiles(srcFolder);
foreach (string fileName in fileNames)
{
   string[] lines = File.ReadAllLines(fileName);
}
1 голос
/ 24 сентября 2014

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

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

0 голосов
/ 30 сентября 2008

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

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

Но это всего лишь домыслы. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...