【发布时间】: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.MaxServicePointIdleTime、ServicePointManager.DefaultConnectionLimit、ServicePointManager.Expect100Continue 和 HttpWebRequest.AllowWriteStreamBuffering。
是否有人对如何使 HTTP.sys 性能超过 200MB/s 有任何想法?有没有人看到它在任何环境下都表现得这么好?
更新:
下面是我看到的TcpListener 与HttpListener 的性能的更多细节:
首先,我编写了一个 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