【问题标题】:How to maximize http.sys file upload performance如何最大化 http.sys 文件上传性能
【发布时间】:2011-02-16 04:04:21
【问题描述】:

我正在构建一个工具,用于将非常大的流数据集(可能在单个流中以 TB 为单位;通常为数十 GB)从一台服务器传输到另一台服务器。该工具的客户端部分将从源磁盘读取块,并通过网络发送它们。服务器端会从网络上读取这些块,并将它们写入服务器磁盘上的一个文件中。

现在我正在尝试决定使用哪种传输方式。选项是原始 TCP 和 HTTP。

我真的,真的很想能够使用 HTTP。 HttpListener(或 WCF,如果我想走那条路)可以很容易地插入 HTTP 服务器 API (http.sys),我可以免费获得身份验证和 SSL 之类的东西。现在的问题是性能。

我编写了一个简单的测试工具,它使用 BeginWrite/EndWrite 异步 I/O 习惯用法发送 128K 块 NULL 字节,并在服务器端使用异步 BeginRead/EndRead。我已经修改了这个测试工具,所以我可以通过HttpWebRequest/HttpListener 使用HTTP PUT 操作,或者使用TcpClient/TcpListener 进行普通的旧套接字写入。为了排除网卡或网络路径的问题,客户端和服务器都在一台机器上并通过 localhost 进行通信。

在我的 12 核 Windows 2008 R2 测试服务器上,此测试工具的 TCP 版本可以以 450MB/s 的速度推送字节,而 CPU 使用率最低。在同一个盒子上,测试工具的 HTTP 版本在 130MB/s 和 200MB/s 之间运行,具体取决于我如何调整它。

在这两种情况下,CPU 使用率都很低,而且绝大多数 CPU 使用率都是内核时间,所以我很确定我对 C# 和 .NET 运行时的使用不是瓶颈。该盒子有两个 6 核 Xeon X5650 处理器,24GB 单列 DDR3 RAM,仅供我自己进行性能测试使用。

我已经了解 HTTP 客户端调整,例如 ServicePointManager.MaxServicePointIdleTimeServicePointManager.DefaultConnectionLimitServicePointManager.Expect100ContinueHttpWebRequest.AllowWriteStreamBuffering

是否有人对如何使 HTTP.sys 性能超过 200MB/s 有任何想法?有没有人看到它在任何环境下都表现得这么好?

更新

下面是我看到的TcpListenerHttpListener 的性能的更多细节:

首先,我编写了一个 TcpClient/TcpListener 测试。在我的测试盒上,它能够推送 450MB/s。

然后使用反射器,我想出了如何获取 HttpWebRequest 底层的原始 Socket 对象,并修改了我的 HTTP 客户端测试以使用它。仍然没有喜悦;几乎没有 200MB/s。

我目前的理论是 http.sys 针对典型的 IIS 用例进行了优化,即大量并发的小请求,以及大量的并发和可能的大响应。我假设,为了实现这种优化,MSFT 必须以我试图完成的事情为代价,即单个非常大的请求的吞吐量非常高,响应非常小。

为了它的价值,我还尝试了最多 32 个并发 HTTP PUT 操作,看看它是否可以横向扩展,但仍然没有任何乐趣;大约 200MB/秒。

有趣的是,在我的开发工作站上,这是一个运行 64 位 Windows 7 的四核 Xeon Precision T7400,我的 TcpClient 实现约为 200MB/s,HTTP 版本也约为 200MB/s。一旦我将它带到运行 Server 2008 R2 的更高端的服务器级机器上,TcpClient 代码会达到 450MB/s,而 HTTP.sys 代码则保持在 200 左右。

在这一点上,我很遗憾地得出结论,HTTP.sys 不是我需要完成的工作的正确工具,并且必须继续使用我们一直使用的手动套接字协议。

【问题讨论】:

  • 很好,经过深入研究的问题。作为 HttpListener 的用户,我会看这个。 +1(在听说有一个开发者拥有比我自己的开发平台更强大的开发者之后,我暂且不谈)
  • 谢谢 :) 不要因为嫉妒而变绿;我与另外两个开发人员分时分享这个盒子(现在正好轮到我,但后来我不得不把它交给其他人)。因为那个盒子占用了本应用于更换我老化的开发笔记本电脑的预算。那好吧;会计给予,会计带走。
  • 不完全是一个答案,但我想知道像 Unison 这样的实用程序将如何处理这个alliance.seas.upenn.edu/~bcpierce/wiki/…
  • 根据我的经验,像 Unison 和 rsync 这样的同步工具根本无法按照我的需要执行,至少在 Windows 下不会。这并不是说无法使同步技术发挥作用。只是我还没有看到一个可以使一个像样的 RAID 0 SAS 阵列饱和的实现。

标签: c# .net performance http.sys


【解决方案1】:

除了这个Tech Note,我看不到太多的兴趣。可能值得一试MaxBytesPerSend

【讨论】:

  • 是的,我确实看到了。我没有干预MaxBytesPerSend 的原因是,在我的情况下,HTTP.sys 没有进行发送;我正在做一个带有大负载的 HTTP PUT,HTTP.sys 接收并流式传输到我的基于 HttpLisener 的服务器。此外,更大的 TCP 窗口应该有利于高带宽和高延迟的链路;因为我的测试是通过环回接口完成的,所以延迟是渐近为零的。 (还是)感谢你的建议。让他们来吧!
【解决方案2】:

如果您要通过 LAN 发送文件,那么 UDP 是可行的方法,因为在这种情况下 TCP 的开销是一种浪费。 TCP 提供速率限制 以避免太多丢失的数据包,而对于 UDP,应用程序必须自行解决。 NFS 会完成这项工作,如果不是你被 Windows 卡住了;但我确信必须有现成的 UDP 东西。还可以使用工具“iperf”(在 linux 上可用,也可能在 windows 上可用)对网络链接进行基准测试,而与协议无关。有些网卡很垃圾,过于依赖CPU,这会将你的速度限制在200mbit。您想要一个带有自己处理器的合适网卡(不知道确切的术语)。

【讨论】:

  • 感谢您的建议,但由于各种原因,我坚持使用 HTTP。我对 TCP 引入的开销非常熟悉,但仅此一项并不能解释我在这里支付的性能损失。使用原始 TCP,我能够以 450MB/s 的速度移动,而使用 HTTP.sys 的速度仅超过 200MB/s,因此很明显,HTTP 实现会产生额外的开销。我正在使用带有 TCP 卸载功能的 PCI-Express x4 Intel PRO/1000 双端口 GigE NIC,但这甚至无关紧要,因为我正在运行的测试是通过环回接口进行的。
  • 我觉得奇怪的是你会被 HTTP 卡住,像 TFTP 这样的东西会好得多。如何尝试一些命令行 HTTP 实现,例如。 curl 加上 C 中一些琐碎的 HTTP 服务器?从您所说的看来,这似乎是软件限制,因此请尝试其他一些实现。您可能想要一个映射文件的服务器?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-20
  • 2010-09-30
  • 2011-09-28
  • 2014-04-04
  • 2016-09-29
  • 1970-01-01
  • 2012-06-15
相关资源
最近更新 更多