【问题标题】:Creating FileStream to network share ultra slow [closed]创建 FileStream 到网络共享超慢 [关闭]
【发布时间】:2014-03-07 10:26:48
【问题描述】:

我有一个 Windows 服务,它必须在 2 个网络共享的大约 20 个文件中写入大约 20kB 的数据。

Total Commander 写入文件的时间:小于 0.1s。

用我的应用程序编写文件的时间:大约 10 秒。

怎么了?是的,文件会不断地从两个共享中读取,但这应该不是问题,因为:

public void WriteData(string text, string fileName, bool forceBackup = false) {
    foreach (var dir in Locations) {
        var path = string.Format(@"{0}\{1}", dir, fileName);
        FileStream stream = null;
        try {
            stream = new FileStream(
                path,
                FileMode.Create,
                FileAccess.Write,
                FileShare.Read
            );
            using (StreamWriter writer = new StreamWriter(stream)) {
                stream = null;
                writer.Write(text);
            }
        }
        catch (Exception) { } // irrelevant now, tested it doesn't throw exceptions anyway
        finally {
            if (stream != null) stream.Dispose();
        }
        File.SetLastWriteTime(path, DateTime.Now);
    }
}

上面的代码适用于本地文件。将所有数据写入 RAM 驱动器需要一毫秒。我的网络共享也位于 RAM 驱动器上。

重要的是 - 使用 Total Commander 将这些文件复制到完全相同的位置也只需几毫秒。我的意思是 - 在满负荷下复制到网络共享。

没有共享冲突,应用程序在单个线程中写入文件。从 Total Commander 写入这些文件时没有问题,在不使用网络共享的情况下使用我的应用程序写入这些文件没有问题。

没有共享冲突,因为在写入时 - 这些文件只能由 Web 服务器读取,并明确设置了 FileAccess.ReadFileShare.ReadWrite

不,我不能在不使用网络共享的情况下写入这些文件,因为我的服务所做的是在两台服务器之间进行同步。不,我不能使用 DFSR,因为文件更新得太频繁了(每秒 2 次)。不,我不能使用 2 个单独的服务来更新两台机器上的文件,因为当我的服务的每个实例都可以停止而不停止两台服务器上的数据更新时,它会取消故障保护功能。

详细地说,在我的生产环境中,有 2 个该服务实例,其中一个正在更新文件,另一个持续监控活动的是否完成其工作。当检测到故障时,他们会切换角色。这一切都是实时发生的,并且具有魅力。有一个大故障:写入文件的延迟超长。

如果您想知道File.SetLastWriteTime() 代表什么 - 这是针对 Windows (.NET) 错误的解决方法,即文件上次写入时间未通过单独的 create / write 正确更新。当然,如果第一个实例按时更新文件,那么正确的修改时间对于另一个实例的检测至关重要。

另外:我收到报告说有时会从这些文件中读取一些垃圾。但它很少发生。我还没有确认这个错误。

但主要问题是 - 什么需要这么长时间?我的测试服务器和目标服务器之间有快速的 1GBit 链接,生产服务器之间有 10GBit 的链接。 Ping 低于 1ms。这不是网络问题。


经过更多测试后,我发现缓冲区大小和文件选项与写入时间无关。我发现网络 ping 非常重要。我无法在我的开发机器上测试代码,因为 ping 太大。

无论如何 - 如果所有文件都创建一次,然后在不重新创建流的情况下更新,则可以优化代码以将运行速度提高 80%。当用于本地共享时,它也非常快。无论如何 - 测试代码很快,同一台服务器上的生产代码慢了 50 倍。但是有一点点不同 - 生产文件会不断地被 Web 服务器读取,而测试文件则不会。

仍然 - 未达到目标。我需要在与 10GBit/s 以太网链接的 2 台服务器上每秒更新 20 x 1kb 文件。达到 200 毫秒的延迟是可以接受的,但它仅适用于测试文件,共享的真实文件每次更新仍然超过 6000 毫秒。

顺便说一句,当可靠性至关重要时,此处不能选择打开文件。该服务应该能够无缝地将所有更新切换到另一个实例,以防任何文件被删除,或者发生任何网络、数据库或磁盘错误。让文件保持打开状态可能会导致共享违规、内存泄漏和其他灾难。正确处理不断打开的文件也会非常复杂,这会使代码更难调试。

也许还有另一种方法可以在服务器之间共享数据?也许一个 zip 文件可以用来上传文件,然后另一个服务会解压缩文件?我确信压缩和解压缩 1kB 的数据不会花费 1 秒的时间!

【问题讨论】:

  • 虽然我认为它不能解决问题,但您可以通过使用File.WriteAllText(path, text) 来缩短代码很多。 (值得尝试看看它是否也让它更快,但我不希望它。)
  • 请不要在问题标题中包含有关所用语言的信息,除非没有它就没有意义。标记用于此目的。
  • @Jon Skeet:我不能,我需要共享文件以供阅读。我不能用 File.WriteAllText 指定文件共享模式,可以吗?
  • 啊,不。我错过了。即使StreamWriter 构造函数也不允许该选项。请注意,使用using 语句而不是try/catch/finally 会更简单:)
  • 创建一个微小的复制代码。这缩小了范围。像1)打开流,2)写一个字节。就是这样。

标签: c# .net networking


【解决方案1】:

我认为你的问题的答案在于这篇文章:

Writing to file using StreamWriter much slower than file copy over slow network

要直接回答这个问题,它是以 4kbyte 块而不是 64Kbyte 块写入文件,这会导致更多的往返。

你应该可以改变这个看到这个答案:

https://stackoverflow.com/a/14588922/3323733

【讨论】:

  • 很遗憾,它不起作用。文件小于 1KB。我在测试中使用 20 x 1KB 文件,写入时间与指定的各种缓冲区大小没有区别。顺便说一句,网络并不慢。这是一个非常快的网络,我在我的测试机器上上传了 10MBit,ping 不到 5ms。即使写入本地主机,问题也存在!在它们之间具有 10GBit 链接的生产服务器上进行测试时也会发生同样的情况。时间几乎相同。
  • 好的,这个答案专门针对大文件。您最好将它们写入临时文件夹,然后将它们复制到网络共享。这样,如果出现任何问题,您可以回滚
【解决方案2】:

我错了,它很慢。它不是。问题出在测试过程中。我已将基准测试代码添加到我的生产服务中,它显示它完全按预期工作。我的代码没有错误,我的系统也没有滞后。

一系列事件导致了这种情况:

  1. 一个叫我的人在更新我们的数据时出现了巨大的(超过 5 秒)延迟。
  2. 我在我的开发机器上运行了更新服务的调试版本,发现延迟几乎正好是 5 到 6 秒。
  3. 我创建了这个帖子和测试项目,它编写测试文件并测量时间
  4. 我在生产服务器上测试了代码,发现它运行良好,没有大滞后
  5. 我在生产服务中添加了基准测试代码,以查看它在现实生活中的表现(并且表现完美)
  6. 我给打电话的人打了电话,问他是否看到延迟 - 他说现在没有延迟

什么?!好吧,这可能是他的网络滞后!我的错!我应该从一开始就在生产服务器上测试代码。当网络连接速度和延迟对进程至关重要时,程序无法在任何其他环境中进行测试,或者可以进行测试,但不能测试速度或延迟。可能如果我有一个更大的文件,差异会不那么明显,但是如果有 20 个小文件,我的机器和生产服务器之间的差异就会很大。

顺便说一句,WriteData 方法是最佳的,没有什么可以改变的,测试了所有可能的文件模式和缓冲区大小。加快速度的唯一方法是保持所有文件打开,但这不值得。顺便说一句,生产服务器也可以将文件上传到远程 FTP 快 10 倍。好吧,我的 WAN 与公司 LAN 甚至与公司 WAN 相比是一只乌龟。从一开始就应该很明显。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-03
    相关资源
    最近更新 更多