У меня есть сервер 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):
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
);
}
}
Проблема была вызвана:
Поскольку управление потоком было отключено, 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 Мбит / с.
Благодаря Космонавт, чьи комментарии помогли решить эту проблему.
Похоже на проблему с сетью нижнего уровня. Мои догадки:
Может быть, это карта / коммутатор на 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» (возможно, в категории «Энергосбережение»). Если присутствует, попробуйте установить для этого параметра значение ОТКЛЮЧИТЬ.