Windows 2008 Server 在混合以太网速度下 — 从共享下载速度很慢,但普通 TCP 速度很快

Windows 2008 Server 在混合以太网速度下 — 从共享下载速度很慢,但普通 TCP 速度很快

我有一台 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):

dot_nc.cs

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();
 }
}

dot_nc_l.cs

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

Windows 服务器是否具有SMB 签名启用?SMB 签名会增加速度,并且默认启用在域控制器上。

答案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

相关内容