2008-09-30 11 views
37

Deseo ver un árbol de carpetas en un servidor de red para ver los cambios. Todos los archivos tienen una extensión específica. Hay alrededor de 200 carpetas en el árbol y aproximadamente 1200 archivos con la extensión que estoy viendo.System.IO.FileSystemWatcher para supervisar una carpeta de servidor de red - Consideraciones de rendimiento

No puedo escribir un servicio para que se ejecute en el servidor (¡fuera de límites!) Por lo que la solución debe ser local para el cliente. La puntualidad no es particularmente importante. Puedo vivir con un minuto o más de retraso en las notificaciones. Estoy mirando para Crear, Eliminar, Renombrar y Cambios.

¿Usaría .NET System.IO.fileSystemWatcher crearía mucha carga en el servidor?

¿Qué hay de 10 vigilantes por separado para reducir el número de carpetas/archivos que se ven? (hasta 200 de 700 carpetas, 1200 de 5500 archivos en total) ¿Más tráfico de red en lugar de menos? Mis pensamientos son una reorganización en el servidor para poner los archivos vistos bajo 1 árbol. Puede que no siempre tenga esta opción, por lo tanto, el equipo de observadores.

Supongo que la otra solución es una comprobación periódica si el FSW crea una carga indebida en el servidor, o si no funciona para un montón de razones de tipo SysAdmin.

¿Hay una mejor manera de hacerlo?

Respuesta

61

Desde el punto de vista de la carga del servidor, usar el IO.FileSystemWatcher para las notificaciones de cambio remoto en el escenario que describe es probablemente el método más eficiente posible. Utiliza las funciones de API Win32 FindFirstChangeNotification y ReadDirectoryChangesW internamente, que a su vez se comunican con el redirector de red de forma optimizada (suponiendo una red de Windows estándar: si se utiliza un redirector de terceros y no admite la funcionalidad requerida, las cosas ganaron no funciona en absoluto). .NET wrapper también usa asincronización de E/S y todo, asegurando aún más eficacia.

El único problema con esta solución es que no es muy confiable. Aparte de tener que lidiar con conexiones de red que se van temporalmente (lo cual no es un problema, ya que IO.FileSystemWatcher desencadenará un evento de error en este caso que puede manejar), el mecanismo subyacente tiene ciertas limitaciones fundamentales.A partir de la documentación de MSDN para las funciones de la API de Win32:

  • ReadDirectoryChangesW falla con ERROR_INVALID_PARAMETER cuando la longitud del búfer es mayor que 64 KB y la aplicación monitoriza un directorio a través de la red. Esto es debido a una limitación de tamaño de paquete con los protocolos de intercambio de archivos subyacentes

  • Notificaciones no podrá regresar al llamar FindFirstChangeNotification para un sistema de archivos remoto

En otras palabras: con carga alta (cuando lo haría necesita un gran búfer) o, peor aún, en circunstancias no especificadas al azar, es posible que no reciba las notificaciones que espera. Esto es incluso un problema con los observadores locales del sistema de archivos, pero es un problema mucho más grave en la red. Another question here on SO detalla los problemas de fiabilidad inherentes con la API con un poco más de detalle.

Al usar vigilantes del sistema de archivos, su aplicación debería ser capaz de manejar estas limitaciones. Por ejemplo:

  • Si los archivos que buscas tienen números de secuencia, almacenar el último número de secuencia que consiguió notificado acerca de, por lo que se puede buscar 'lagunas' en las futuras notificaciones y procesar los archivos para los que no fue notificado;

  • Al recibir una notificación, siempre realice un escaneo completo del directorio. Esto puede sonar muy mal, pero dado que el escaneo depende de los eventos, sigue siendo mucho más eficiente que un sondeo tonto. Además, siempre y cuando mantenga la cantidad total de archivos en un solo directorio, así como la cantidad de directorios para escanear, menos de mil, el impacto de esta operación en el rendimiento debería ser mínimo.

Configuración de varios oyentes es algo que se debe evitar tanto como sea posible: en todo caso, esto hará que las cosas aún menos fiable ...

De todos modos, si es absolutamente tiene utilizar los observadores del sistema de archivos, las cosas pueden funcionar bien siempre y cuando conozca las limitaciones, y no espere una notificación 1: 1 para cada archivo modificado/creado.

Entonces, si tiene otras opciones (básicamente, hacer que el proceso de escritura de los archivos le notifique de una manera que no sea de sistema de archivos: cualquier método RPC regular será una mejora ...), definitivamente vale la pena investigar desde el punto de vista de la confiabilidad.

-1

No creo que haya ningún tipo de estado activo o comunicación entre la computadora con el FSW y la computadora cuya ubicación está siendo monitoreada. En otras palabras, el FSW no está haciendo ping al sistema operativo en red para verificar el archivo.

Uno imaginaría que un mensaje o evento es solo elevado/enviado a la FSW en red cuando se produce un cambio.

Pero esto es solo especulación. :)

+0

¿Cómo sabría el cliente que algo había cambiado en el servidor si no lo hiciera? AFAIK, el FSW no ejecuta ningún proceso en el servidor. Aún así, AFIK no es mucho en este caso. –

+1

Tenemos una respuesta ahora, pero para responder a su pregunta: el FSW enviaría una solicitud a la computadora que le gustaría ser notificado cuando el archivo cambie. No sigues preguntando a una revista si aún tiene un nuevo problema, te suscribes una vez y envían nuevos problemas cuando se publican. – core

2

El MSDN documentation indicates que puede utilizar el componente FileSystemWatcher para ver los cambios del sistema de archivos en una red unidad.

También indica que el componente del vigilante escucha las notificaciones de cambio del sistema de archivos en lugar de interrogar periódicamente a la unidad de destino por cambios.

Basado en que la cantidad de tráfico de red depende completamente de cuánto esperas que cambie el contenido de esa unidad de red. El componente FSW no se agregará al nivel de tráfico de red.

7

He usado los vigilantes del sistema de archivos de C# varias veces. La primera vez que los usé, tuve problemas para dejar de trabajar, principalmente debido a que estaba procesando los cambios en el hilo que informaron el cambio.

Ahora, sin embargo, simplemente coloco el cambio en una cola y proceso la cola en otro hilo. Esto parece resolver el problema que originalmente tuve. Para su problema, podría hacer que varios observadores presionen la misma cola.

Sin embargo, no he usado esto con su tipo de escala de problema.

3

En mi experiencia, un FSW no crea un alto tráfico de red. Sin embargo, si hay un problema de rendimiento, su enfoque de usar varios observadores y descomponerlo en menos carpetas que se estén viendo suena razonable.

Tuve algunos problemas grandes con FSW en unidades de red: la eliminación de un archivo siempre arrojaba el evento de error, nunca el evento eliminado. No encontré una solución, así que ahora evito usar FSW si hay una forma de evitarlo ...

1

Watcher parece 100% confiable, solo mire el tamaño del buffer en el objeto Watcher. He probado miles de actualizaciones de archivos, ninguna perdida.

Recomiendo utilizar un enfoque de múltiples subprocesos: el activador es el vigilante de archivos. Puede iniciar un hilo por cada cambio de archivo detectado. El observador puede procesar mucho más rápido con menos posibilidades de desbordamiento. (use hilo Async)

+0

Puede parecer 100% confiable en un sistema de archivos local, pero es terriblemente poco confiable en un recurso compartido de red. Si se rebota un servidor de archivos que sirve un recurso compartido, el FSW tiene muerte cerebral. – DSoa

1

Después de usar System.IO.FileSystemWatcher por algún tiempo. No es lo suficientemente estable como para manejar eventos que llegan demasiado rápido. Para garantizar el 100% de lectura de los archivos. Utilizo métodos de directorio simples para buscar a través de los archivos. Después de leerlo, copie de inmediato los archivos a otra carpeta. Para aislarlo de los nuevos archivos que se agregan mientras lee los archivos.

El temporizador se utiliza para leer regularmente la carpeta. Al copiar el archivo ya leído en la carpeta de archivo, asegúrese de que no vuelva a leerse. La lectura posterior será siempre archivos nuevos.

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

Cuestiones relacionadas