Назад | Перейти на главную страницу

Windows 2008 Server на смешанных скоростях Ethernet - загрузка с общего ресурса медленный, но быстрый простой TCP

У меня есть сервер Windows Server 2008 R2 x64, который является контроллером AD и файловым сервером. У меня проблема, с которой клиенты Windows XP работают ужасно медленно (менее 10 Мбит / с, на самом деле менее десяти мегабайт).биты-в секунду) загрузка файлов из общего ресурса.

Сервер подключается к коммутатору 1 Гбит / с с помощью карты Nvidia NForce 1 Гбит / с, а клиент подключается с помощью встроенной карты 100 Мбит / с.

Такую медленную загрузку можно также увидеть, когда я загрузил клиентский компьютер с CentOS Linux 5.5 Live-USB и использовал для загрузки smbclient. Но загрузка с общего ресурса Samba на сервере Linux, который также подключен по каналу 1 Гбит / с, выполняется быстро.

Что очень странно, я создал пару программ (прилагается ниже), которые тестируют простую пропускную способность TCP на C #, и они работают так, как ожидалось - примерно со скоростью 89 Мбит / с.

Я отключил брандмауэр на клиенте и использую dot_nc_l 21000 > NIL на клиенте и dot_nc [client_ip] < 100m.dat на сервере Windows. И у меня получается около 9 секунд, когда копирование того же файла размером 100 МБ из общего ресурса занимает более 2 минут.

Как это устранить?


Некоторые изображения, созданные с помощью wirehark на клиенте Linux:

Загрузка файла размером 100 МБ с файлового сервера CIFS Windows 2008, подключенного к NIC 1 Гбит / с, в клиент Centos 5 Linux, подключенный к NIC 100 Мбит / с с помощью smbclient:

Загрузка файла размером 100 МБ с файлового сервера CIFS Fedora Linux на Samba, подключенного к NIC 1 Гбит / с, в клиент Centos 5 Linux, подключенный к NIC 100 Мбит / с с smbclient (тот же масштаб, что и выше):


Вот эти программы (скомпилированные с использованием 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
  );
 }
}

Проблема была вызвана:

  • слишком маленькие буферы пакетов в недорогом гигабитном коммутаторе;
  • неадекватный алгоритм предотвращения перегрузки, используемый в файловых службах Windows Server 2008;
  • отключено управление потоком в сетевом адаптере (по умолчанию отключено).

Поскольку управление потоком было отключено, Windows отправляла пакеты размером до размера окна одним пакетом, используя соединение 1 Гбит / с. Поскольку клиент со скоростью 100 Мбит / с получает пакеты намного медленнее, почти все данные вплоть до размера окна необходимо буферизовать с помощью коммутатора. Поскольку этот дешевый коммутатор имеет очень маленькие буферы (размеры буфера даже не указаны в спецификациях, но он должен быть менее 64 КБ на порт, поскольку даже отключение масштабирования окна не помогло), ему пришлось отбрасывать лишние пакеты. Потеря пакетов вызвала задержку около 0,25 с, видимую на графике. Но алгоритм предотвращения перегрузки, используемый в файловых службах или его отсутствие, не уменьшал размер окна TCP, поэтому следующий пакет пакетов не был меньше - он снова и снова перегружал соединение, вызывая коллапс заторов.

Стандартные TCP-соединения (не файловые службы) должны использовать другой алгоритм управления перегрузкой и не перегружаться повторно. Я полагаю, что обработка файловых служб с помощью стека Windows TCP помогает в тестах, например, против Samba.

Итак, решения следующие:

  • Включите управление потоком в свойствах сетевого адаптера. Это не идеальное решение, так как любая передача файловых служб клиенту со скоростью 100 Мбит / с также замедлит одновременные передачи клиентам со скоростью 1 Гбит / с до скорости менее 100 Мбит / с.

  • Или подключать клиентов со скоростью 100 Мбит / с к коммутатору корпоративного класса с гораздо большими буферами. Это решение, которое я использовал. У меня есть коммутатор "3Com SuperStack 3 3300 SM" 10-летней давности с одним оптоволоконным гигабитным Ethernet-портом MT-RJ 1000Base-SX. я купил Модуль Cisco 1000BASE-SX mini-Gbic (MGBSX1) с портом LC для моего гигабитного коммутатора Linksys и многомодовым оптоволоконным патч-кордом LC / MT-RJ (около 150 долларов за оба) и подключил всех клиентов 100 Мбит / с к этому коммутатору 3com. Я также включил управление потоком, но это не должно вызывать замедления при отсутствии подключенного клиента со скоростью 100 Мбит / с.

Благодаря Космонавт, чьи комментарии помогли решить эту проблему.

Похоже на проблему с сетью нижнего уровня. Мои догадки:

  • Проблемы несоответствия дуплексного режима. Это, безусловно, немного снизит производительность. На стороне Linux используйте команду ethtool, чтобы убедиться, что вы ведете переговоры со скоростью 100 Мбит / с / полный дуплекс. Если ваша карта выполняет согласование на уровне 100 / Half, а коммутатор считает, что соединение установлено на 100 / Full, тогда возникнут все типы проблем. Возможно, вы захотите поэкспериментировать с форсировкой 100 / Full вместо автоматического согласования скорости (помните, что вам нужно принудительно установить 100 / Full на коммутаторе и системе)
  • Это также может быть проблема с буфером либо на сетевой карте клиента, либо на коммутаторе. Я видел, как драйверы сетевой карты не выделяют достаточно места в буфере и вызывают проблемы со скоростью. Я предполагаю, что такая же проблема может возникнуть с переключателем. Гораздо сложнее диагностировать, если не считать замены оборудования.

Может быть, это карта / коммутатор на 100 Мбит / с? Вы упомянули, что тот же клиент работает правильно, когда он находится на скорости 1 Гбит / с.

Есть ли на сервере Windows Подпись SMB включен? Подписание SMB добавляет медлительности и включен по умолчанию на контроллерах домена.

Можно попробовать скопировать через esetutil (если там есть обменный сервер)

Проверь это: http://blogs.technet.com/b/askperf/archive/2007/05/08/slow-large-file-copy-issues.aspx

Это может быть тест, если вы копируете большие файлы с клиента на сервер или наоборот, чтобы проверить, повысит ли производительность esetutil.

также у меня были аналогичные проблемы с Windows 2008 и Linux Server с опцией NetDMA (последний раздел). Это решило мои проблемы (был сетевой адаптер Broadcom с объединением)


Как включить и отключить NetDMA в Windows Server 2008 Чтобы включить или отключить NetDMA, выполните следующие действия: Нажмите Пуск, нажмите Выполнить, введите regedit и нажмите ОК. Найдите следующий подраздел реестра и щелкните его: HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ Tcpip \ Parameters. Дважды щелкните запись реестра EnableTCPA. Примечание. Если эта запись реестра не существует, щелкните правой кнопкой мыши «Параметры», выберите «Создать», «Значение DWORD», введите EnableTCPA и нажмите клавишу ВВОД. Чтобы включить NetDMA, введите 1 в поле «Значение» и нажмите «ОК». Чтобы отключить NetDMA, введите 0 в поле «Значение» и нажмите «ОК». Если запись реестра EnableTCPA не существует, включите функцию NetDMA. Продукты сторонних производителей, обсуждаемые в этой статье, производятся компаниями, независимыми от Microsoft. Microsoft не дает никаких явных или подразумеваемых гарантий относительно производительности или надежности этого продукта.


из службы поддержки Microsoft KB 951037

Проверьте, есть ли в BIOS ваших серверов / клиентов параметр «CPU C State» (возможно, в категории «Энергосбережение»). Если присутствует, попробуйте установить для этого параметра значение ОТКЛЮЧИТЬ.