45

我想查看网络服务器上的文件夹树是否有更改。这些文件都有一个特定的扩展名。树中有大约 200 个文件夹和大约 1200 个文件,扩展名为我正在查看。

我无法编写要在服务器上运行的服务(禁止!),因此解决方案必须在客户端本地。及时性并不是特别重要。我可以忍受一分钟或更长时间的通知延迟。我正在关注创建、删除、重命名和更改。

使用 .NET System.IO.fileSystemWatcher 会在服务器上产生大量负载吗?

10 个单独的观察者如何减少被观察的文件夹/文件的数量?(从 700 个文件夹减少到 200 个,总共从 5500 个文件减少到 1200 个)更多网络流量而不是更少?我的想法是在服务器上重新洗牌,将监视的文件放在一棵树下。我可能并不总是有这个选项,因此有观察者团队。

我想另一种解决方案是定期检查 FSW 是否在服务器上创建了过度负载,或者它是否由于一大堆 SysAdmin 类型的原因而不起作用。

有一个更好的方法吗?

4

7 回答 7

76

从服务器负载的角度来看,在您描述的场景中使用IO.FileSystemWatcher进行远程更改通知可能是最有效的方法。它在内部使用FindFirstChangeNotificationReadDirectoryChangesW Win32 API 函数,这反过来又以优化的方式与网络重定向器通信(假设标准 Windows 网络:如果使用第三方重定向器,并且它不支持所需的功能,事情会成功根本不工作)。.NET 包装器还使用异步 I/O 和一切,进一步确保最大效率。

这个解决方案的唯一问题是它不是很可靠。除了必须处理暂时断开的网络连接(这不是什么大问题,因为在这种情况下 IO.FileSystemWatcher 会触发一个您可以处理的错误事件),底层机制具有某些基本限制。来自 Win32 API 函数的 MSDN 文档:

换句话说:在高负载下(当您需要一个大缓冲区时),或者更糟糕的是,在随机未指定的情况下,您可能不会收到您期望的通知。这甚至是本地文件系统观察者的问题,但更多的是网络上的问题。这里关于 SO 的另一个问题更详细地详细说明了 API 的固有可靠性问题。

使用文件系统观察程序时,您的应用程序应该能够处理这些限制。例如:

  • 如果您要查找的文件有序列号,请存储您收到通知的最后一个序列号,以便您可以在未来的通知中查找“空白”并处理您未收到通知的文件;

  • 收到通知后,请始终进行完整目录扫描。这听起来可能很糟糕,但由于扫描是事件驱动的,它仍然比哑轮询更有效。此外,只要您将文件总数保持在单个目录中,以及要扫描的目录数在 1000 左右,此操作对性能的影响无论如何应该是非常小的。

设置多个监听器是你应该尽可能避免的事情:如果有的话,这会让事情变得更不可靠......

无论如何,如果您绝对必须使用文件系统观察程序,只要您了解这些限制,事情就可以正常工作,并且不要期望每个修改/创建的文件都有 1:1 的通知。

因此,如果您有其他选择(基本上,让写入文件的过程以基于非文件系统的方式通知您:任何常规 RPC 方法都将是一种改进......),从可靠性的角度来看,这些绝对值得研究观点。

于 2008-09-30T06:00:47.927 回答
10

我已经多次使用 C# 中的文件系统观察程序。第一次使用它们时,我遇到了它们停止工作的问题,主要是因为我正在处理报告更改的线程中的更改。

然而,现在,我只是将更改推送到一个队列并在另一个线程上处理该队列。这似乎解决了我最初遇到的问题。对于您的问题,您可以让多个观察者推送到同一个队列中。

但是,我没有将它用于您的问题规模。

于 2008-09-30T20:07:43.787 回答
3

以我的经验,FSW 不会产生高网络流量。但是,如果存在性能问题,您使用多个观察者并将其分解为更少被观察的文件夹的方法听起来是合理的。

不过,我在网络驱动器上使用 FSW 时遇到了一些大问题:删除文件总是抛出错误事件,而不是删除事件。我没有找到解决方案,所以如果有办法,我现在避免使用 FSW...

于 2008-10-03T11:09:14.430 回答
2

MSDN 文档表明您可以使用 FileSystemWatcher 组件来监视网络驱动器上的文件系统更改。

它还表明观察程序组件侦听文件系统更改通知,而不是定期询问目标驱动器的更改。

基于此,网络流量完全取决于您期望该网络驱动器的内容发生多少变化。FSW 组件不会增加网络流量的级别。

于 2008-09-30T05:31:16.610 回答
1

观察者看起来 100% 可靠 - 只需观察观察者对象上的缓冲区大小。我已经测试了数千个文件更新,没有一个丢失。

我建议使用多线程方法 - 触发器是文件观察器。它可以为检测到的每个文件更改启动一个线程。观察者可以更快地处理并且溢出的机会更少。(使用异步线程)

于 2014-09-24T17:13:23.243 回答
1

使用 System.IO.FileSystemWatcher 一段时间后。它不够稳定,无法处理来得太快的事件。确保 100% 读取文件。我使用简单的目录方法来搜索文件。阅读后,立即将文件复制到另一个文件夹。在您阅读文件时将其与添加的新文件隔离开来。

定时器用于定期读取文件夹。通过将已读取的文件复制到存档文件夹,可以确保不会再次读取它。随后的读取将始终是新文件。

var fileNames = Directory.GetFiles(srcFolder);
foreach (string fileName in fileNames)
{
   string[] lines = File.ReadAllLines(fileName);
}
于 2016-05-27T06:52:31.027 回答
-1

我认为带有 FSW 的计算机和其位置被监视的计算机之间没有任何类型的活动状态或通信。换句话说,FSW 不会 ping 联网操作系统来检查文件。

可以想象,消息或事件仅在发生更改时才会引发/发送到联网的 FSW。

但这一切都只是猜测。:)

于 2008-09-30T05:08:42.247 回答