Data Center TCP (DCTCP) в Windows Server 2012 R2

DCTCP и управление TCP с использованием ECN - новый функционал Windows Server

Привет.

Сети датацентров – пожалуй, одно из самых высокотехнологичных и передовых мест в современных сетевых технологиях, которое вдобавок находится на стыке массы технологий. Задача вида “выжать максимум” здесь является не уникальной, а операционной, поэтому надо быть во всеоружии. Давайте поговорим про то, кто такой новый TCP – DCTCP и чем он нам поможет.

Я предполагаю, что читатель знаком с сетевыми технологиями хотя бы на уровне базового бесплатного курса Cisco ICND1 3.0. Если нет – не страшно, но для полного понимания логики происходящего всё ж лучше представлять, как работает TCP и его отдельные подсистемы.

DCTCP в Windows Server 2012 R2

  • Проблемы протокола TCP
  • TCP Flow Control
  • TCP Global Syncronization
  • Управление заторами – ECN
  • Включение поддержки ECN и DCTCP
  • Настройка профилей TCP / DCTCP в Windows Server 2012 R2

Начнём.

Проблемы протокола TCP

Протокол TCP – очень хороший протокол. Количество решаемых им задач и имеющегося функционала – очень велико. И потоком он управлять умеет, и sequencing делает, и полнодуплексно работает, и разные логики изменения размера окна знает, и всякие out-of-band данные отправлять умеет. Но есть минус. В протоколе TCP нет поддержки телепатии.

Казалось бы – при чём здесь, при обсуждении транспортного протокола, телепатия? А дело в том, что если бы TCP мог телепатически изучать конфигурацию всех сетевых устройств, включая L2-коммутаторы, которые расположены по трассе путешествия TCP-сегментов, жить ему было бы гораздо лучше. Рамочная суть проблемы TCP, связанной с заторами, формулируется так – протокол TCP при работе не понимает причину задержки/потери сегментов и пытается решить этот вопрос, играя размером окна. Он не знает, как именно идёт буферизация, чей и какой буфер перегружен, и не умеет понимать разницу между, допустим, приёмом данных во входящую очередь на порту и приёмом данных в буфер со стороны получателя.

Сразу оговорюсь, что вопросы тюнинга TCP и его функционала – штука крайне обширная, и в данной статье нет задачи охватить их все. Для хорошего изучения TCP нужен фундаментальный подход – при нескольких десятках модифицируемых параметров другие подходы смысла не имеют, нужно понимать суть, вариант “данный параметр лучше в такое значение, чем такое, просто потому что лучше” не подойдёт. Здесь же мы говорим про DCTCP.

Представьте себе для наглядности аналогичную ситуацию с другой подсистемой. Есть программный RAID, который получает запрос на запись большого количества данных. RAID радуется, распределяет их по дискам (например, это обычный stripe на пару дисков), и начинает передавать. У каждого диска – кэш, допустим 64МБ. Диски очень бодро кушают данные, RAID радуется, и выдаёт прогноз по скорости записи – мол, с такой-то скоростью мы сейчас всё очень быстро сделаем. Но после передачи около 128МБ диски неожиданно говорят – “Стоп, технический перерыв – нам надо теперь это по факту записать на блины”. RAID пугается и прогноз резко изменяется – теперь оказывается, что диски, быстро употребляющие данные, на самом деле гораздо медленнее, чем ожидалось. В зависимости от реализации RAID, работы ОС с этим RAID и работы приложения с API этой ОС могут быть разные ситуации – но суть будет в том, что данные могут начать сбрасываться “волнами”, что далеко по эффективности от возможной максимальной скорости записи на массив.

Как же выглядит работа обычного TCP в подобной ситуации?

TCP Flow Control

Стандартно в протоколе TCP реализован механизм управления потоком данных (не путать с 802.3x Flow Control, который реализован на уровне порта Ethernet), когда одна сторона может сказать другой “Притормози, а то ты много данных уже накидала через данную сессию конкретному приложению, оно не успевает разгружать буфер, если будешь присылать ещё, то придётся выбрасывать”. Данная ситуация может возникнуть по многим причинам – например, отправляющий хост может передавать быстро, а принимающий хост сильно загружен в плане процессора и то приложение, которому принадлежит принимающий порт, не успевает обрабатывать данные. Размер буфера обычно указывается при регистрации TCP-порта через интерфейс Winsock, а логика отправки уведомления “not ready” также может быть различной. Говоря проще, Вы можете влиять на то, при каком проценте заполненности буфера надо уведомлять противоположную сторону, что больше отправлять не надо – делать это при 100% загрузки уже поздно, ведь пока уведомление будет идти по сети, к Вам могут доехать дополнительные tcp-сегменты, которые уже будет некуда сохранять.

Но опять же, это не единственная проблема – плюс, данная логика отталкивается исключительно от степени заполнения буфера приёма. А с ним могут быть и другие проблемы.

TCP Global Syncronization

Глобальная синхронизация – нехороший артефакт TCP Flow Control. Суть его в том, что если у хоста много TCP-сессий, и все они управляются идентичной логикой, то возникают “waves of congestion”. Т.е. допустим, у Вас есть веб-сервер. Он честно, включаясь, застолбил за собой 80й TCP-порт, Winsock выделил буфер для приёма и началась работа. Клиенты начали подключаться и работать. Активно работать – например, постить комментарии в форум. Буфер приёма наполняется, приложение активно разбирает из него данные, но вот наполнение буфера переходит критическую границу, и Winsock немедленно рассылает всем уведомление “За мной не занимать, притормозите”. Okay – говорят все, и перестают постить огромные картинки. Приложение активно разбирает буфер, и, когда дело доходит до другого барьерного числа – “буфер разгружен” – стек Winsock рассылает всем сообщение – “продолжаем”. Все радостно и синхронно кидают висящие у них в буферах отправки данные, и буфер приёма разово перехлёстывает волной трафика так, что происходит tail-drop. Ситуация с криком “За мной не занимать” повторяется, только уже хуже – ещё и часть данных потеряли. Уведомление о том, что принята только часть (selective ack) отправляются – с отправкой-то всё ОК, поэтому отправители знают, что данные потеряны, и готовятся передать их повторно. Но, как понятно, при следующем сигнале “продолжаем” ситуация повторяется – опять разовая приливная волна, опять буфер затопило, опять часть данных потеряли, опять общий крик “притормозили”, и снова, снова.

Данная ситуация может быть и на уровне порта маршрутизатора, в который входит много данных, которые, допустим, массово хотят выйти через менее скоростной порт, ну или у маршрутизатора небыстрая обработка оных – опять будет ситуация вида “20 tcp-сессий равномерно передают данные, буфер кончился, у все разово по чуть-чуть потеряли сегменты, все разово в силу sliding windows схлопнули окно передачи, затаились (slow start), а потом разово выбросили пачки сегментов, и опять на том же порту разово перегрузился буфер”.

Что же со всем этим делать? Конечно, есть “лобовые” методы – например линейно увеличивать размеры буферов, скорость каналов, но это всё, в общем-то не панацея, притом совсем. Сетевик, который придёт к фин.ответственному лицу и скажет “у нас тут в общем канал 100Мбит наружу, там иногда пакеты пропадают, давайте гиг купим”, получит именно то, что заслуживает – трудовую.

Это не наш вариант. Что же привнесёт нового в TCP протокол DCTCP?

Управление заторами – ECN и ECN+

Explicit Congestion Notification – дополнение к протоколам IP и TCP, которое должно поддерживаться не только конечными участниками TCP-сессии, но и промежуточными узлами (привет покупателям “простой свичик главное чтобы гигабитный остальное ненужные навороты”). Суть его (ECN) работы достаточно проста, и разбивается на две части – работа с IP и работа с TCP.

ECN и IP

В IP ECN использует зарезервированные биты в ToS-поле заголовка, чтобы информировать про факт затора в сети. Эти биты – два оставшихся после DSCP-маркинга бита в ToS, никем до ECN особо не использовавшиеся. Если оба этих бита нули, то ECN не поддеживается (это называется Non-ECT – Non ECN Capable Transport). Если узел поддерживает ECN – он ставит 10, это обозначает ECN Capable Transport. Если произошёл затор – в эти биты ставится обе единицы. Это важный момент с точки зрения скорости, т.е. сетевое оборудование не нуждается в глубоком парсинге TCP-заголовков и отслеживанию session state, чтобы определить факт затора.

ECN и TCP

Поддержка ECN согласовывается в TCP на момент установки сессии. Если согласовалась – во всех IP-пакетах, в которые помещаются TCP-сегментых с данными, будет установлен признак ECT. Кстати, если поддерживается ECN+, то метиться на L3 будут ещё и служебные сегменты (ACK и SYN), что усиливает положительный эффект от ECN.

Полезная штука? Безусловно. Давайте сразу включим её.

Включение поддержки ECN и DCTCP

Сколько не видел материалов от Крутых Ситивиков из Microsoft, все поголовно тупо копипастили маркетинговую презентацию, где “Всё-это-само-работает-ничего-не-надо-настраивать”. Это не так.

Выполним под админскими правами данный командлет:

Set-NetTCPSetting -ECNCapability Enabled

Теперь DCTCP.

Set-NetTCPSetting -CongestionProvider DCTCP

Скорее всего, будет заметна ругань системы на то, что модифицировать можно только custom templates – а это значит, что нам надо будет углубляться в настройки. Ранее, в Windows Server 2012, был доступен для редактирования только template с названием Custom – теперь, в Windows Server 2012 R2 доступны InternetCustom и DatacenterCustom. В хелпе на сайте Microsoft пока что старая версия, не обращайте на неё внимание – шаблона Custom теперь просто нет. Поправим наши команды в соответствии со спецификой новой серверной ОС:

Set-NetTCPSetting -SettingName DatacenterCustom -ECNCapability Enabled -CongestionProvider DCTCP

База сделана, теперь конкретика – нам надо явно указать, что мы хотим для определённого трафика именно использования Datacenter-настроек.

Настройка профилей TCP / DCTCP в Windows Server 2012 R2

Профили TCP – это готовые пачки настроек системы для разных сценариев. Можно навскидку придумать как минимум три сценария – “для датацентров, где быстрая локальная сеть и мощные высоконагруженные хосты”, “для Интернета, где от меня до целевого узла куча сегментов и оборудования с разной пропускной способностью, MTU, загрузкой и размерами буферов”, и “универсальный с усреднёнными настройками”. Примерно так в Windows Server 2012 R2 и сделано – можете убедиться:

Get-NetTCPSetting

Какие подключения будут использовать какой из профилей? Это тоже можно посмотреть:

Get-NetTCPConnections

В правой колонке, где AppliedSetting, будет видно название профиля – заметим, что только для тех подключений, которые установлены и работают – для открытых портов (которые Listen), или TCP-сессий, находящихся в TimeWait, профиль не применяется, что и логично. Вывести все подключения, использующие конкретный профиль, тоже несложно:

Get-NetTCPConnections -AppliedSetting Internet

Ну а теперь создадим транспортный фильтр, который явно укажет, какой трафик должен использовать наш шаблон DatacenterCustom:

New-NetTransportFilter –SettingName DatacenterCustom –DestinationPrefix 172.16.0.0/16

Вы можете также задать условия в части портов отправителя/получателя, используя параметры -RemotePortStart и -RemotePortEnd, и -LocalPortStart и -LocalPortEnd. Параметра, задающего source prefix, нет, да он и не нужен – эта политика работает исходя из того, что под неё подпадают все TCP-сессии с локального хоста. Кстати, там есть ещё параметр -Protocol, намекающий, что возможно, это когда-нибудь будет работать и не только для TCP (технически это возможно), но пока декоративный.

В общем всё. Шаблон действует сразу, доп.команды по включению не нужны.

Используйте данную полезную технологию – преимуществ DCTCP много, это и экономия места для буферизации данных TCP, и уменьшение потерь пакетов, и ощутимо более шустрая работа при сценариях “получатель загружен несколькими потоками данных с разной интенсивностью”. Желающие почитать подробнее могут зайти вот по этой ссылке – http://simula.stanford.edu/~alizade/Site/DCTCP_files/dctcp_analysis-full.pdf и узнать полезные детали.

Удач в применении!

Возможно, вам будет также интересно почитать другие статьи про на нашей Knowledge Base

Ruslan V. Karmanov

Зайдите на сайт под своей учётной записью, чтобы видеть комментарии под техническими статьями. Если учётной записи ещё нет - зарегистрируйтесь, это бесплатно.