我有一台 Windows Server 2008 R2 x64 服务器,它是 AD 控制器和文件服务器。我遇到一个问题,Windows XP 客户端速度非常慢(不到 10Mbps,实际上不到 10 兆位每秒)从共享下载文件。
服务器使用 1Gbps Nvidia NForce 卡连接到 1Gbps 交换机,客户端使用 100Mbps 内置卡连接。
当我从 CentOS Linux 5.5 Live-USB 启动客户端计算机并使用 smbclient 下载时,也可以看到这种缓慢的下载。但从 Linux 服务器上的 Samba 共享(也是使用 1Gbps 链路连接的)下载速度很快。
非常奇怪的是,我创建了一对程序(附在下面),用于在 C# 中测试普通 TCP 吞吐量,它们的性能符合预期——约为 89Mbps。
dot_nc_l 21000 > NIL
我已禁用客户端上的防火墙,并在客户端和Windows 服务器上使用dot_nc [client_ip] < 100m.dat
。我大约需要 9 秒,而从共享中复制相同的 100MB 文件则需要 2 分钟以上。
如何消除此问题?
在Linux客户端上使用wireshark生成的一些图片:
使用 smbclient 从连接 1Gbps NIC 的 Windows 2008 CIFS 文件服务器下载 100MB 文件到连接 100Mbps NIC 的 Centos 5 Linux 客户端:
使用 smbclient 从连接 1Gbps NIC 的 Samba 上的 Fedora Linux CIFS 文件服务器下载 100MB 文件到连接 100Mbps NIC 的 Centos 5 Linux 客户端(与上面相同的比例):
这些是这些程序(链接使用 mono 的 gmcs 编译,需要 .NET2):
using System;
using System.IO;
using System.Diagnostics;
using System.Net.Sockets;
public class dot_nc
{
public static void Main(string[] args) {
string hostname = args[0];
int port = int.Parse(args[1]);
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
TcpClient client = new TcpClient(hostname, port);
stopwatch.Stop();
Console.WriteLine("Connection: {0}ms", stopwatch.ElapsedMilliseconds);
stopwatch.Reset();
stopwatch.Start();
byte[] buffer = new byte[4096];
{
Stream stdin = Console.OpenStandardInput();
NetworkStream netout = client.GetStream();
while ( true ) {
int bytesread = stdin.Read(buffer, 0, buffer.Length);
if ( bytesread <= 0 ) {
break;
}
netout.Write(buffer, 0, bytesread);
}
}
stopwatch.Stop();
Console.WriteLine("Sending: {0}ms", stopwatch.ElapsedMilliseconds);
client.Close();
}
}
using System;
using System.IO;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
public class dot_nc
{
public static void Main(string[] args) {
int port = int.Parse(args[0]);
TcpListener server = new TcpListener(IPAddress.Any, port);
server.Start();
TcpClient client = server.AcceptTcpClient();
NetworkStream netin = client.GetStream();
byte[] buffer = new byte[4096];
Stream stdout = Console.OpenStandardOutput();
int processed_bytes = 0;
int processed_chunks = 0;
while ( true ) {
int bytesread = netin.Read(buffer, 0, buffer.Length);
if ( bytesread <= 0 ) {
break;
}
stdout.Write(buffer, 0, bytesread);
processed_bytes += bytesread;
processed_chunks++;
}
netin.Close();
client.Close();
server.Stop();
Console.Error.WriteLine(
"Received: {0} chunks of data of {1} average size",
processed_chunks, processed_bytes/processed_chunks
);
}
}
答案1
问题是由于:
- 廉价千兆交换机的数据包缓冲区太小;
- Windows Server 2008 文件服务中使用的拥塞避免算法不充分;
- 禁用网络适配器中的流量控制(默认情况下是禁用的)。
由于流量控制被禁用,Windows 使用 1Gbps 连接一次性发送最多达到窗口大小的数据包。由于 100Mbps 客户端接收数据包的速度要慢得多,因此几乎所有达到窗口大小的数据都需要通过交换机进行缓冲。由于这种廉价交换机的缓冲区非常小(规格中甚至没有说明缓冲区大小,但每个端口必须小于 64kB,因为即使禁用窗口缩放也无济于事),因此它必须丢弃多余的数据包。数据包丢失导致图表上显示大约 0.25 秒的延迟。但文件服务中使用的拥塞避免算法(或缺乏拥塞避免算法)并没有减少 TCP 窗口大小,因此下一批数据包并没有变小——它一次又一次地拥塞连接,导致拥塞崩溃。
标准 TCP 连接(非文件服务)必须使用不同的拥塞控制算法,并且不会反复拥塞。我认为通过 Windows TCP 堆栈专门处理文件服务有助于对 Samba 等进行基准测试。
因此解决方案是:
在网络适配器属性中启用流量控制。这不是一个理想的解决方案,因为任何文件服务向 100Mbps 客户端的传输也会将向 1Gbps 客户端的并发传输速度减慢到 100Mbps 以下。
或者将 100Mbps 客户端连接到具有更大缓冲区的企业级交换机。这是我使用过的解决方案。我有一个 10 年历史的“3Com SuperStack 3 3300 SM”交换机,带有一个 1000Base-SX 光纤千兆以太网 MT-RJ 端口。我买了一个思科 1000BASE-SX 迷你 Gbic 模块 (MGBSX1)为我的 Linksys 千兆交换机配备 LC 端口和 LC/MT-RJ 多模光纤跳线(两者约 150 美元),并将所有 100Mbps 客户端连接到此 3com 交换机。我还启用了流量控制,但在没有连接 100Mbps 客户端的情况下,它不应导致速度变慢。
谢谢太空人斯皮夫,其评论有助于解决这一问题。
答案2
答案3
可能是 100Mbps 卡/交换机的问题?您提到同一个客户端在 1Gbps 时可以正常工作。
答案4
您可以尝试通过 esetutil 复制(如果您那里有 Exchange 服务器)
检查一下:http://blogs.technet.com/b/askperf/archive/2007/05/08/slow-large-file-copy-issues.aspx
如果您将大文件从客户端复制到服务器或反之亦然,这可以作为一个测试,以测试 esetutil 是否获得更好的性能。
我在 Windows 2008 和 Linux Server 上也遇到了类似的问题,其中有一个选项叫 NetDMA(上一节)。这解决了我的问题(是具有协作功能的 Broadcom 网络适配器)
如何在 Windows Server 2008 中启用和禁用 NetDMA 要启用或禁用 NetDMA,请按照以下步骤操作:单击“开始”,单击“运行”,键入 regedit,然后单击“确定”。找到以下注册表子项,然后单击它:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters 双击 EnableTCPA 注册表项。注意如果此注册表项不存在,请右键单击“参数”,指向“新建”,单击“DWORD 值”,键入 EnableTCPA,然后按 ENTER。要启用 NetDMA,请在“数值数据”框中键入 1,然后单击“确定”。要禁用 NetDMA,请在“数值数据”框中键入 0,然后单击“确定”。如果 EnableTCPA 注册表项不存在,请启用 NetDMA 功能。本文讨论的第三方产品由独立于 Microsoft 的公司制造。Microsoft 不对这些产品的性能或可靠性做任何明示或暗示的保证
来自 Microsoft 支持 KB 951037