混合以太网速度的Windows 2008 Server - 从分享速度慢,但快速普通TCP下载

Modified on: Mon, 19 Aug 2019 02:40:03 +0800

我有一台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 > NILdot_nc [client_ip] < 100m.dat。当我从共享中复制相同的100MB文件需要2分钟时,我得到大约9秒钟。

如何消除这种情况?


在Linux客户端上使用wireshark生成的一些图片:

将100MB文件从连接1Gbps网卡的Windows 2008 CIFS文件服务器下载到带有smbclient的100Mbps网卡连接的Centos 5 Linux客户端:

将100MB文件从连接1Gbps网卡的Samba上的Fedora Linux CIFS文件服务器下载到带有smbclient的100Mbps网卡连接的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
  );
 }
}
作者:,Tometzky

最佳答案

问题是由以下原因造成的:

  • 便宜的千兆交换机中的数据包缓冲区太小;
  • 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端口。我为我的Linksys千兆交换机和LC / MT-RJ多模光纤跳线(两者大约150美元)购买了带有LC端口的 Cisco 1000BASE-SX mini-Gbic模块(MGBSX1),并连接了所有100Mbps这个3com交换机的客户端。我也启用了流量控制,但不应该在没有连接100Mbps客户端的情况下导致速度下降。

感谢 SpacemanSpiff ,其评论有助于解决此问题。


相关问答

添加新评论