我正在构建一个工具,可以将非常大的流数据集(可能在单个流中以 TB 为单位;通常以数十 GB 为单位)从一台服务器传输到另一台服务器。该工具的客户端部分将从源磁盘读取块,并通过网络发送它们。服务器端将从网络上读取这些块并将它们写入服务器磁盘上的文件。
现在我正在尝试决定使用哪种交通工具。选项是原始 TCP 和 HTTP。
我真的,真的很想能够使用 HTTP。HttpListener(或 WCF,如果我想走那条路)可以很容易地插入 HTTP 服务器 API (http.sys),我可以免费获得身份验证和 SSL 之类的东西。现在的问题是性能。
我编写了一个简单的测试工具,它使用 BeginWrite/EndWrite 异步 I/O 习惯用法发送 128K 块 NULL 字节,并在服务器端使用异步 BeginRead/EndRead。我已经修改了这个测试工具,因此我可以通过HttpWebRequest
/使用 HTTP PUT 操作或使用/HttpListener
的普通旧套接字写入来做到这一点。为了排除网卡或网络路径的问题,客户端和服务器都在一台机器上并通过 localhost 进行通信。TcpClient
TcpListener
在我的 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
.
有没有人对我如何获得超过 200MB/s 的 HTTP.sys 性能有任何想法?有没有人看到它在任何环境下都表现得这么好?
更新:
TcpListener
下面是关于我在vs中看到的性能的更多细节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 不是我需要完成的工作的正确工具,并且必须继续使用我们一直使用的手动套接字协议。