Какие параметры влияют на производительность приложений? Часть 1. TCP Window Size
Самый простой способ понять значение термина размер TCP окна (TCP Window Size), это представить разговор двух человек. Один человек говорит, а второй кивает головой или говорит да, тем самым подтверждая, что он понял, а по сути, получил все слова, которые ему были сказаны. После этого разговор продолжается. Если мы встречаем особо говорливого человека, то наша голова быстро загружается, и мы начинаем терять нить разговора или переспрашивать нашего собеседника. Тоже самое происходит и в Матрице — в мире цифр и машин.
Размер TCP окна (TCP Window Size) – количество октетов (начиная с номера подтверждения), которое принимающая сторона готова принять в настоящий момент без подтверждения. На стадии установления соединения рабочая станция и сервер обмениваются значениями максимального размера TCP окна (TCP Window Size), которые присутствуют в пакете и эти значения можно легко увидеть, воспользовавшись захватом трафика.
Например, если размер окна получателя равен 16384 байта, то отправитель может отправить 16384 байта без остановки. Принимая во внимание, что максимальная длина сегмента (MSS) может быть 1460 байт, то отправитель сможет передать данный объем в 12 фреймах, и затем будет ждать подтверждение доставки от получателя и информации по обновлению размера окна. Если процесс прошел без ошибок, то размер окна может быть увеличен. Таким образом, реализуется размер скользящего окна в стеке протокола TCP.
В зависимости от состояния каналов связи, размер окна может быть больше или меньше. Каналы связи могут быть высокоскоростными (большая пропускная способность) и протяженными (большая задержка и возможно потери), поэтому при небольшом размере TCP окна мы будем вынуждены отправлять один или несколько фреймов и ждать подтверждения от получателя, затем процесс повторяется. Таким образом, наши приложения будут неэффективно использовать доступную полосу пропускания. Пакетов будет много, но реального полезного трафика будет передано не много. Чтобы получить максимальную пропускную способность, необходимо использовать оптимально установленный размер передающего и принимающего окна для канала, который вы используете.
Для расчёта максимального размера окна (т.е. максимальный объем данных, которые могут передаваться одним пользователем другому в канале связи) рассчитывается по формуле:
Полоса пропускания (бит/сек) * RTT (круговое время передачи по сети) = размер окна в битах
Таким образом, если ваши два офиса соединяет канал связи в 10 Мбит/сек и круговое время составляет 85 миллисекунд, то воспользовавшись данной формулой, мы получим значение окна равное:
10 000 000 * 0,085 / 8 = 106250 байт
Размер поля Window в заголовке TCP составляет 16 бит; это означает, что узел TCP может указать максимальный размер TCP окна 65535 байт. Таким образом, максимальная пропускная способность составляет:
65535 * 8 / 0,085 = 6,2 Мбит/сек
т.е. чуть больше 50% от реально доступной полосы пропускания канала.
В современных версиях операционных систем можно увеличить размер окна TCP Window Size и включить динамическое изменение окна в зависимости от состояния канала связи. В предложении RFC 1323 дано определение масштабирования окон, позволяющего получателю указывать размер окна больше 65535 байт, что позволит применять большие размеры окон и высокоскоростные каналы передачи. Параметр TCP Window Scale указывает коэффициент масштабирования окна, который в сочетании с 16-битным полем Window в заголовке TCP может увеличивать размер окна приема до максимального значения, составляющего примерно 1 ГБ. Параметр Window Scale отправляется только в сегментах синхронизации (SYN) при установке соединения. На нашем скриншоте из WireShark он составляет 256. Устройства, общающиеся друг с другом, могут указывать разные коэффициенты масштабирования для TCP окон.
Таким образом, активировав масштабирование окон TCP и уменьшив круговое время передачи по сети, мы сможем повысить эффективность использования доступной полосы пропускания и как следствие скорость работы приложений. А проверить это можно захватив пакеты, и посмотреть о каких значениях размера окна и коэффициенте масштабирования договорились устройства в момент установки соединения. Это динамическое увеличение и уменьшение размера окна является непрерывным процессом в TCP и определяет оптимальный размер окна для каждого сеанса. В очень эффективных сетях размеры окна могут стать очень большими, потому что данные не теряются. В сетях, где сетевая инфраструктура перегружена, размер окна, вероятно, останется маленьким.
Теория:Протоколы:TCP
TCP (transmission control protocol — протокол управления передачей) — один из основных протоколов передачи данных интернета, предназначенный для управления передачей данных. Сети и подсети, в которых совместно используются протоколы TCP и IP называются сетями TCP/IP.
В стеке протоколов IP TCP выполняет функции протокола транспортного уровня модели OSI.
Механизм TCP предоставляет поток данных с предварительной установкой соединения, осуществляет повторный запрос данных в случае потери данных и устраняет дублирование при получении двух копий одного пакета, гарантируя тем самым, в отличие от UDP, целостность передаваемых данных и уведомление отправителя о результатах передачи.
Реализации TCP обычно встроены в ядра ОС. Существуют реализации TCP, работающие в пространстве пользователя.
Когда осуществляется передача от компьютера к компьютеру через Интернет, TCP работает на верхнем уровне между двумя конечными системами, например, браузером и веб-сервером. TCP осуществляет надежную передачу потока байтов от одной программы на некотором компьютере к другой программе на другом компьютере (например, программы для электронной почты, для обмена файлами). TCP контролирует длину сообщения, скорость обмена сообщениями, сетевой трафик.
Содержание
Заголовок сегмента TCP
Бит | 0 — 3 | 4 — 9 | 10 — 15 | 16 — 31 | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Порт источника | Порт назначения | ||||||||||||||||||||||||||||||
32 | Порядковый номер | |||||||||||||||||||||||||||||||
64 | Номер подтверждения | |||||||||||||||||||||||||||||||
96 | Длина заголовка | Зарезервировано | Флаги | Размер Окна | ||||||||||||||||||||||||||||
128 | Контрольная сумма | Указатель важности | ||||||||||||||||||||||||||||||
160 | Опции (необязательное, но используется практически всегда) | |||||||||||||||||||||||||||||||
160/192+ | Данные |
Порт источника, Порт назначения
Эти 16-битные поля содержат номера портов — числа, которые определяются по специальному списку.
Порт источника идентифицирует приложение клиента, с которого отправлены пакеты. Ответные данные передаются клиенту на основании этого номера.
Порт назначения идентифицирует порт, на который отправлен пакет.
Порядковый номер
Порядковый номер выполняет две задачи:
- Если установлен флаг SYN, то это изначальный порядковый номер — ISN (Initial Sequence Number), и первый байт данных, которые будут переданы в следующем пакете, будет иметь номер, равный ISN + 1.
- В противном случае, если SYN не установлен, первый байт данных, передаваемый в данном пакете, имеет этот порядковый номер
Поскольку поток TCP в общем случае может быть длиннее, чем число различных состояний этого поля, то все операции с порядковым номером должны выполняться по модулю 2 32 . Это накладывает практическое ограничение на использование TCP. Если скорость передачи коммуникационной системы такова, чтобы в течение MSL (максимального времени жизни сегмента) произошло переполнение порядкового номера, то в сети может появиться два сегмента с одинаковым номером, относящихся к разным частям потока, и приёмник получит некорректные данные.
Номер подтверждения
Если установлен флаг ACK, то это поле содержит порядковый номер, ожидаемый получателем в следующий раз. Помечает этот сегмент как подтверждение получения.
Длина заголовка (смещение данных)
Это поле определяет размер заголовка пакета TCP в 4-байтных (4-октетных) словах. Минимальный размер составляет 5 слов, а максимальный — 15, что составляет 20 и 60 байт соответственно. Смещение считается от начала заголовка TCP.
Зарезервировано
Зарезервировано (6 бит) для будущего использования и должно устанавливаться в ноль. Из них два (5-й и 6-й) уже определены:
- CWR (Congestion Window Reduced) — Поле «Окно перегрузки уменьшено» — флаг установлен отправителем, чтобы указать, что получен пакет с установленным флагом ECE (RFC 3168)
- ECE (ECN-Echo) — Поле «Эхо ECN» — указывает, что данный узел способен на ECN (явное уведомление перегрузки) и для указания отправителю о перегрузках в сети (RFC 3168)
Флаги (управляющие биты)
Это поле содержит 6 битовых флагов:
- URG — поле «Указатель важности» задействовано (Urgent pointer field is significant)
- ACK — поле «Номер подтверждения» задействовано (Acknowledgement field is significant)
- PSH — (Push function) инструктирует получателя протолкнуть данные, накопившиеся в приёмном буфере, в приложение пользователя
- RST — оборвать соединения, сбросить буфер (очистка буфера) (Reset the connection)
- SYN — синхронизация номеров последовательности (Synchronize sequence numbers)
- FIN (final, бит) — флаг, будучи установлен, указывает на завершение соединения (FIN bit used for connection termination).
Размер окна
В этом поле содержится число, определяющее в байтах размер данных, которые отправитель может отправить без получения подтверждения.
Контрольная сумма
Поле контрольной суммы — это 16-битное дополнение к сумме всех 16-битных слов заголовка(включая псевдозаголовок) и данных. Если сегмент, по которому вычисляется контрольная сумма, имеет длину не кратную 16-ти битам, то длина сегмента увеличивается до кратной 16-ти, за счет дополнения к нему справа нулевых битов заполнения. Биты заполнения (0) не передаются в сообщении и служат только для расчёта контрольной суммы. При расчёте контрольной суммы значение самого поля контрольной суммы принимается равным 0.
Указатель важности
16-битовое значение положительного смещения от порядкового номера в данном сегменте. Это поле указывает порядковый номер октета, которым заканчиваются важные (urgent) данные. Поле принимается во внимание только для пакетов с установленным флагом URG.
Опции
Могут применяться в некоторых случаях для расширения протокола. Иногда используются для тестирования. На данный момент в опции практически всегда включают 2 байта NOP (в данном случае 0x01) и 10 байт, задающих timestamps. Вычислить длину поля опции можно через значение поля смещения.
Механизм действия протокола
В отличие от традиционной альтернативы — UDP, который может сразу же начать передачу пакетов, TCP устанавливает соединения, которые должны быть созданы перед передачей данных. TCP соединение можно разделить на 3 стадии:
- Установка соединения
- Передача данных
- Завершение соединения
Состояния сеанса TCP
Состояния сеанса TCP | |
---|---|
CLOSED | Начальное состояние узла. Фактически фиктивное |
LISTEN | Сервер ожидает запросов установления соединения от клиента |
SYN-SENT | Клиент отправил запрос серверу на установление соединения и ожидает ответа |
SYN-RECEIVED | Сервер получил запрос на соединение, отправил ответный запрос и ожидает подтверждения |
ESTABLISHED | Соединение установлено, идёт передача данных |
FIN-WAIT-1 | Одна из сторон (назовём её узел-1) завершает соединение, отправив сегмент с флагом FIN |
CLOSE-WAIT | Другая сторона (узел-2) переходит в это состояние, отправив, в свою очередь сегмент ACK и продолжает одностороннюю передачу |
FIN-WAIT-2 | Узел-1 получает ACK, продолжает чтение и ждёт получения сегмента с флагом FIN |
LAST-ACK | Узел-2 заканчивает передачу и отправляет сегмент с флагом FIN |
TIME-WAIT | Узел-1 получил сегмент с флагом FIN, отправил сегмент с флагом ACK и ждёт 2*MSL секунд, перед окончательным закрытием соединения |
CLOSING | Обе стороны инициировали закрытие соединения одновременно: после отправки сегмента с флагом FIN узел-1 также получает сегмент FIN, отправляет ACK и находится в ожидании сегмента ACK (подтверждения на свой запрос о разъединении) |
Установка соединения
Процесс начала сеанса TCP (также называемый «рукопожатие» (handshake)), состоит из трёх шагов.
1. Клиент, который намеревается установить соединение, посылает серверу сегмент с номером последовательности и флагом SYN.
- Сервер получает сегмент, запоминает номер последовательности и пытается создать сокет (буферы и управляющие структуры памяти) для обслуживания нового клиента.
- В случае успеха сервер посылает клиенту сегмент с номером последовательности и флагами SYN и ACK, и переходит в состояние SYN-RECEIVED.
- В случае неудачи сервер посылает клиенту сегмент с флагом RST.
2. Если клиент получает сегмент с флагом SYN, то он запоминает номер последовательности и посылает сегмент с флагом ACK.
- Если он одновременно получает и флаг ACK (что обычно и происходит), то он переходит в состояние ESTABLISHED.
- Если клиент получает сегмент с флагом RST, то он прекращает попытки соединиться.
- Если клиент не получает ответа в течение 10 секунд, то он повторяет процесс соединения заново.
3. Если сервер в состоянии SYN-RECEIVED получает сегмент с флагом ACK, то он переходит в состояние ESTABLISHED.
- В противном случае после тайм-аута он закрывает сокет и переходит в состояние CLOSED.
Процесс называется «трёхэтапным согласованием» (three way handshake), так как несмотря на то что возможен процесс установления соединения с использованием четырёх сегментов (SYN в сторону сервера, ACK в сторону клиента, SYN в сторону клиента, ACK в сторону сервера), на практике для экономии времени используется три сегмента.
Пример базового 3-этапного согласования:
В строке 2 TCP A начинает передачу сегмента SYN, говорящего об использовании номеров последовательности, начиная со 100. В строке 3 TCP B передает SYN и подтверждение для принятого SYN в адрес TCP A. Надо отметить, что поле подтверждения показывает ожидание TCP B приёма номера последовательности 101, подтверждающего SYN с номером 100.
В строке 4 TCP A отвечает пустым сегментом с подтверждением ACK для сегмента SYN от TCP B; в строке 5 TCP B передает некоторые данные. Отметим, что номер подтверждения сегмента в строке 5 (ACK=101) совпадает с номером последовательности в строке 4 (SEQ=101), поскольку ACK не занимает пространства номеров последовательности (если это сделать, придется подтверждать подтверждения — ACK для ACK).
Существуют экспериментальные расширения протокола TCP, сокращающие количество пакетов при установлении соединения, например TCP Fast Open. Ранее также существовало расширение T/TCP. Для прозрачного шифрования данных предлагается использовать расширение tcpcrypt.
Передача данных
При обмене данными приёмник использует номер последовательности, содержащийся в получаемых сегментах, для восстановления их исходного порядка. Приёмник уведомляет передающую сторону о номере последовательности, до которой он успешно получил данные, включая его в поле «номер подтверждения». Все получаемые данные, относящиеся к промежутку подтвержденных последовательностей, игнорируются. Если полученный сегмент содержит номер последовательности больший, чем ожидаемый, то данные из сегмента буферизируются, но номер подтвержденной последовательности не изменяется. Если впоследствии будет принят сегмент, относящийся к ожидаемому номеру последовательности, то порядок данных будет автоматически восстановлен исходя из номеров последовательностей в сегментах.
Для того, чтобы передающая сторона не отправляла данные интенсивнее, чем их может обработать приёмник, TCP содержит средства управления потоком. Для этого используется поле «окно». В сегментах, направляемых от приёмника передающей стороне, в поле «окно» указывается текущий размер приёмного буфера. Передающая сторона сохраняет размер окна и отправляет данных не более, чем указал приёмник. Если приёмник указал нулевой размер окна, то передача данных в направлении этого узла не происходит, пока приёмник не сообщит о большем размере окна.
В некоторых случаях передающее приложение может явно затребовать протолкнуть данные до некоторой последовательности принимающему приложению, не буферизируя их. Для этого используется флаг PSH. Если в полученном сегменте обнаруживается флаг PSH, то реализация TCP отдает все буферизированные на текущий момент данные принимающему приложению. «Проталкивание» используется, например, в интерактивных приложениях. В сетевых терминалах нет смысла ожидать ввода пользователя после того, как он закончил набирать команду. Поэтому последний сегмент, содержащий команду, обязан содержать флаг PSH, чтобы приложение на принимающей стороне смогло начать её выполнение.
Завершение соединения
Завершение соединения можно рассмотреть в три этапа:
- Посылка серверу от клиента флага FIN на завершение соединения.
- Сервер посылает клиенту флаги ответа ACK , FIN, что соединение закрыто.
- После получения этих флагов клиент закрывает соединение и в подтверждение отправляет серверу ACK , что соединение закрыто.
Известные проблемы
Максимальный размер сегмента
TCP требует явного указания максимального размера сегмента (MSS) в случае, если виртуальное соединение осуществляется через сегмент сети, где максимальный размер блока (MTU) менее, чем стандартный MTU Ethernet (1500 байт).
В протоколах туннелирования, таких как GRE, IPIP, а также PPPoE MTU туннель меньше, чем стандартный, поэтому сегмент TCP максимального размера имеет длину пакета больше, чем MTU. Это приводит к фрагментации и уменьшению скорости передачи полезных данных. Если на каком-либо узле фрагментация запрещена, то со стороны пользователя это выглядит как «зависание» соединений. При этом «зависание» может происходить в произвольные моменты времени, а именно тогда, когда отправитель использовал сегменты длиннее допустимого размера. Для решения этой проблемы на маршрутизаторах применяются правила Firewall-а, добавляющие параметр MSS во все пакеты, инициирующие соединения, чтобы отправитель использовал сегменты допустимого размера.
MSS может также управляться параметрами операционной системы.
Обнаружение ошибок при передаче данных
Хотя протокол осуществляет проверку контрольной суммы по каждому сегменту, используемый алгоритм считается слабым. Так, в 2008 году ошибка в передаче одного бита, не обнаруженная сетевыми средствами, привела к остановке серверов системы Amazon Web Services.
В общем случае распределенным сетевым приложениям рекомендуется использовать дополнительные программные средства для гарантирования целостности передаваемой информации.
Атаки на протокол
Недостатки протокола проявляются в успешных теоретических и практических атаках, при которых злоумышленник может получить доступ к передаваемым данным, выдать себя за другую сторону или привести систему в нерабочее состояние.
Реализация
Псевдозаголовок
TCP-заголовок не содержит информации об адресе отправителя и получателя, поэтому даже при совпадении порта получателя нельзя с точностью сказать, что сообщение пришло в нужное место. Поскольку назначением протокола TCP является надёжная доставка сообщений, то этот момент имеет принципиальное значение. Эту задачу можно было решить разными способами. Самый очевидный — добавить информацию об адресе назначения в заголовок TCP, однако это, во-первых, приводит к дублированию информации, что снижает долю полезной информации переносимой TCP-сегментом, а во-вторых, нарушает принцип инкапсуляции модели OSI. Поэтому разработчики протокола пошли другим путём и использовали дополнительный псевдозаголовок:
TCP-псевдозаголовок IPv4
Биты 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 0-31 IP-адрес отправителя (Source address) 32-63 IP-адрес получателя (Destination address) 64-95 0 0 0 0 0 0 0 0 Протокол (Protocol) Длина TCP-сегмента (TCP length) TCP-псевдозаголовок IPv6
- Протокол (Protocol)/Протокол верхнего уровня (Next header) — содержит в себе значение 6 (00000110 в двоичном виде, 0x6 — в шестнадцатеричном) — идентификатор TCP-протокола.
- Длина TCP-сегмента (TCP length) — содержит в себе длину TCP-сегмента в байтах (TCP-заголовок + данные; длина псевдозаголовка не учитывается).
Псевдозаголовок не включается в TCP-сегмент. Он используется для расчета контрольной суммы перед отправлением сообщения и при его получении (получатель составляет свой псевдозаголовок, используя адрес хоста, с которого пришло сообщение, и собственный адрес, а затем считает контрольную сумму).
Освобождение от расчёта контрольной суммы
Многие реализации стека TCP/IP предоставляют возможности использования аппаратной поддержки для автоматического расчёта контрольной суммы в сетевом адаптере до передачи в сеть или после приёма из сети для верификации. Это может освобождать операционную систему от использования ценных тактов процессора при вычислении контрольной суммы.
Эта функция может приводить к тому, что анализаторы трафика, перехватывающие исходящие пакеты до их передачи в сетевой адаптер и не знающие о делегировании расчёта контрольной суммы сетевому адаптеру, могут сообщать об ошибке контрольной суммы в исходящих пакетах.
В поисках утерянного гигабита или немного про окна в TCP
Поводом для написания этой статьи послужила лень, которая, как известно, двигатель прогресса и свидетель появления на свет невероятно облегчающих жизнь вещей.
В моём случае это была лень объяснять в тысячный раз клиенту, почему он арендовал канал точка-точка и в договоре чёрным по белому написано Ethernet 1Гбит/с, а он как ни измеряет, но чуть-чуть да меньше получается.
Где остальное? Почему недобор? Куда девался интернет из провода? А может его и вовсе страшно обманули?
Ну что ж, давайте искать, а заодно напишем заметку, которую будет не стыдно показать тысяче первому клиенту, у которого будет недосдача скорости.
Важно
Если вы сетевой инженер, то не читайте эту статью. Она оскорбит все ваши чувства т.к. написана максимально простым и доступным языком с множеством упущений.
История про окна. Мир до окон
Итак, чтобы понять, где скорость, нам придётся разобраться в том, как работает TCP в плане обеспечения надежности соединения.
Как нам всем известно, у ТСР есть финт последней надежды, когда все ухищрения доставить кадр до получателя не сработали, он просто заново отправляет испорченный или утерянный кадр.
Как это выглядит в простейшем случае:
- Кадр отправляется передатчиком. На передатчике включается таймер, в течении которого от получателя должно быть получено подтверждение АСК об успешном получении кадра или явное указание, что кадр был испорчен/утерян в пути — NACK
- Если по истечении таймера АСК не получен, пакет отправляется ещё раз
- Если приходит NACK, источник повторяет отправку кадра
- А если АСК получен, источник отправляет следующий кадр
Графически этот алгоритм легко представляется на временной шкале:
Называется этот алгоритм методом простоя источника, что сразу даёт нам понять его главный минус: катастрофически неэффективное использование канала связи. Технически, ничего не мешает передатчику сразу после отправки первого кадра отправлять второй, но мы принуждаем его ждать прихода ACK/NACK или истечения таймера.
Поэтому важно понимать, что процессы отправки и получения ACKов могут идти независимо друг от друга. На этой идее и был рождён метод скользящего окна.
Окно первое. Скользящее. Теоретическое.
После осознания минусов предыдущего метода, в голову приходит идея разрешить источнику передавать пакеты в максимально возможном для него темпе, без ожидания подтверждения от приёмника. Но не бесконечное их количество, а ограниченное неким буфером, который называется окном, а его размер указывает на количество кадров которое разрешено передать без ожидания подтверждений.
Вернёмся к картинкам:
Для наглядности рассмотрим окно размером К кадров, в котором находятся пакеты (1. N) в некий момент времени, т.е. у нас была отправлена пачка кадров, каждый кадр по мере своей возможности достиг получателя, тот их обработал и отправил подтверждение для каждого.
Теперь усложняем ситуацию, включив время.
В момент прихода АСК на первый кадр, последний ещё не был даже отправлен, но поскольку мы знаем об успешности доставки, в окно можно добавить следующий по порядку кадр, т.е. окно сдвигается и теперь включает в себя кадры 2. N+1. Когда приходит ACK на 2-й кадр, окно снова сдвигается: 3. N+2. И так далее. Получается, что окно как-бы «скользит» по потоку пакетов. Или пакеты через него, тут кому как удобней представлять.
Таким образом, все кадры глобально делятся на три вида:
- Прошлое.Были отправлены, были получены подтверждения
- Суровое настоящее. Состоит из отправленных кадров, но без полученных подтверждений и тех, кто уже в окне, но стоит в очереди на отправку
- Светлое будущее. Кадры в очереди на попадание в окно.
И как это влияет на скорость связи? – спросите вы.
Как мы видим из графика, необходимым условием для максимальной утилизации канала связи является регулярное поступление подтверждений в рамках действия окна. АСК не обязаны приходить в чётком порядке, главное чтобы АСК на первый кадр в окне пришёл раньше, чем будет отправлен последний кадр, иначе сработает таймер неответа, кадр будет отправлен заново, а движение окна прекратится.
Также, стоит отметить, что в большинстве реализаций алгоритма скользящего окна, подтверждения приходят не на каждый пакет, а сразу на всю принятую пачку (называется Selective Ack). Это позволяет ещё больше увеличить эффективную утилизацию канала за счёт снижения объёма служебной информации.
Итак, что же мы имеем в сухом остатке? Какие параметры имеют существенное влияние на эффективность передачи данных между двумя точками?
- Размер окна, который выбирается меньшим из двух: окно, объявленное получателем (размер его буфера) или CWND — размер, определяемый отправителем на основе RTT
- Само RTT: время приёма-передачи, равное времени, затраченному на отправку сигнала, плюс время необходимое для подтверждения о приёме.
И мы не должны передать больше, чем готов принять получатель или пропустить сеть.
Давайте представим, что у нас супер надёжная сеть, где пакеты практически никогда не теряются и не бьются. В такой сети нам выгодно иметь окно максимально возможного размера, что позволит нам минимизировать паузы между отправкой кадров.
В плохой же сети ситуация обратная — при частых потерях и большом количестве битых пакетов нам важно доставить каждый из них в целости и сохранности, поэтому мы уменьшаем окно так, чтобы трафик как можно меньше терялся и мы избежали фатальных переотправок. Жертвовать в этом случае приходится скоростью.
И как нам всем известно, реальность — это смесь двух крайних случаев, поэтому в реальной сети размер окна величина переменная. Причём он может быть изменён, как в одностороннем порядке на любой стороне, так и по согласованию.
Промежуточное резюме. Как мы видим, даже без привязки к конкретным протоколам, чисто технически крайне сложно утилизировать канал на все 100%, т.к. хотим мы того или нет, но даже в лабораторных условиях между кадрами будут минимальные, но задержки, которые и не дадут нам достичь заветных 100% утилизации полосы пропускания.
А что уж говорить про реальные сети? Вот во второй части мы и рассмотрим одну из реализаций на примере TCP.
Окно второе. Реализация в TCP
Чем замечателен ТСР? На основе ненадёжных дейтаграмм IP, он позволяет обеспечить надежную доставку сообщений.
При установлении логического соединения модули ТСР обмениваются между собой следующими параметрами:
- Размер буфера получателя — это верхнее ограничение размера окна
- Начальный порядковый номер байта, с которого начнётся отсчёт потока данных в рамках этой сессии
Сразу запоминаем важную особенность — в ТСР окно оперирует не количеством кадров, а количеством байт. Это значит, что окно представляет из себя множество нумерованных байт неструктурированного потока данных от верхних протоколов. Звучит громоздко, но проще написать не получается.
Итак, ТСР протокол дуплексный, а значит каждая сторона в любой момент времени выступает и как отправитель, и как получатель. Следовательно с каждой стороны должен быть буфер для приёма сегментов и буфер для ещё не отправленных сегментов. Но кроме того, должен быть ещё и буфер для копий уже отправленных сегментов, на которые ещё не получили подтверждения о приёме.
Кстати, отсюда следует упускаемая многими особенность: в двух направлениях условия сети могут быть разными, а значит разный размер окон и разная пропускная способность.
В такой ситуации пляска ведётся от возможностей получателя. При установлении соединения, обе стороны высылают друг другу окна приёма. Получатель запоминает его размер и понимает сколько байт можно отправить, не дожидаясь АСК.
Дальше включаются механизмы описанные в первой главе. Отправка сегментов, ожидание подтверждение, повторная отправка в случае необходимости и т.д. Важное отличие от теоретических изысканий — это комбинирование различных методик. Так например, получение нескольких сегментов, пришедших по порядку, происходит автоматически, прерываясь, только если сбивается очередность поступления. Это одна из функций буфера получателя — восстановить порядок сегментов. И то, если в потоке обнаруживается разрыв, ТСР модуль может повторить запрос потерянного сегмента.
Пара слов про буфер копий на отправителе. У всех сегментов, лежащих в этом буфере, работает таймер. Если за время таймера приходит соответствующий АСК, сегмент удаляется. Если нет — отправляется заново. Возможна такая ситуация, что по таймеру сегмент будет отправлен ещё раз до того, как придёт АСК, но в этом случае повторный сегмент просто будет отброшен получателем.
И вот от этого тайм-аута на ожидание и зависит производительность ТСР. Будет слишком короткий — появятся избыточные переотправки пакетов. Слишком длинный — получим простои из-за ожидания несуществующих АСК.
На самом деле ТСР определяет размер тайм-аута по сложному адаптивному алгоритму, где учитываются скорость, надежность, протяжённость линии и множество других факторов. Но в общих чертах он таков:
- При отправке каждого сегмента замеряется время до прихода АСК.
- Получаемые значения усредняются с весовыми коэффициентами, возрастающими от прошлого к будущему. Это позволяет более новым данным оказывать большее влияние на итоговый результат.
- Затем считается среднее значение от усреднений на предыдущем шаге и получается величина таймаута.Но если разброс величин очень велик, то учитывается ещё и дисперсия.
Но что-то мы всё больше про окно отправки, хотя окно приёма представляет из себя более интересную сущность. На разных концах соединения окна, обычно, имеют разный размер. В мире победивших клиент-серверных технологий, не приходится ожидать, что клиент будет готов оперировать окном того же размера, который может обрабатывать сервер.
Точно так же размер его может меняться динамически, в зависимости от состояния сети, но здесь неправильный выбор подразумевает уже “двойную” ответственность. В случае получения данных бОльших, чем может обработать ТСР модуль, они будут отброшены, на источнике сработает таймер, он переотправит данные, они опять не попадут в размер окна и т.д.
С другой стороны, установка слишком маленького окна приведёт к использованию канала на скорости равной скорости передачи одного сегмента.Поэтому разработчики ТСР предложили схему, в которой при установлении соединения размер окна устанавливается относительно большим и в случае проблем начинает сокращаться в два раза за шаг. Это действительно выглядит странно, поэтому были созданы реализации ТСР повторяющие привычную нам логику: начать с малого окна и, если сеть справляется, то начать его увеличивать.
Но на размер окна приёма может влиять не только принимающая сторона, но и отправитель данных. Если мы видим, что АСК регулярно приходят позже таймеров, что приходится часто переотправлять сегменты, то источник может выставить своё значение окна приёма и будет действовать правило наименьшего — будет принято самое маленькое значение, кто бы его ни назначил.
Остаётся рассмотреть ещё один вариант развития событий, а именно перегрузку ТСР-соединения. Это состояние сети характеризуется тем, что на на промежуточных и оконечных узлах возникают очереди пакетов. В данном случае у приёмника есть два варианта:
- Уменьшить размер окна.
- Совсем отказаться от приёма, установив размер окна, равный нулю.
Хотя полностью закрыть соединение таким образом нельзя. Существует специальный указатель срочности, который принуждает порт принять сегмент данных, даже если для этого придётся очистить существующий буфер. А принявший нулевой размер окна отправитель не теряет надежды и периодически отправляет контрольные запросы на приёмник и, если тот уже готов для принятия новых данных, то в ответ он получит новый, не нулевой, размер окна.
Итого
Капитан подсказывает — если одна TCP сессия в принципе не может обеспечивать 100% утилизацию канала, то используй две. Если мы говорим про клиента, который взял в аренду канал точка-точка и поднял в нём GRE туннель, то пусть поднимет второй. Дабы они не дрались за полосу, заворачиваем в первый важный трафик, во второй — всякую ерунду и страшно зарезаем ему скорость. Этого как раз хватит на то, чтобы выбрать остатки полосы, которую первая сессия не может взять чисто технически.
Заметки с полей.
Влияние задержки сообщения на максимальную скорость передачи данных
Рассмотрим понятие окна в протоколе TCP. При передаче потока данных они сегментируются на отдельные сообщения и отправятся к узлу назначения. Максимальный объем данных, которые могут быть отправлены без подтверждения, составляет размер окна. После отправки такого объема данных отправляющий узел прекращает передачу.
Учитывая работу протокола TCP, можно рассчитать максимальную скорость передачи данных в один поток:
Где W — размер окна, RTT — время, которое проходить с момента отправления сообщение до момента получения ответа.
65535 байт — это максимальный размер окна, равный наибольшему 16-ти битном числу без использования расширения позволяющее анонсировать размер окна гораздо большего размера.Приведем зависимость в таблице:
Расчеты проводились для размера окна равному 65535 байт. Из таблицы можно сделать следующие выводы: для того, чтобы оператор связи мог гарантировать предоставление услуги согласно тарифного плана, ему нужно гарантировать соответствующую задержку прохождения сообщений. Из формулы (3.1) можно вывести значение RTT, что нужно гарантировать при тарифном плане V бит в секунду: