Понятие протокола, и связанные с ним понятия

Вид материалаДокументы

Содержание


Оптимизация TCP. Управление потоком.
MTU (Maximum Transportation Unit), а по ней MSS
Медленный старт в TCP.
Устранение перегрузок средствами TCP.
Сообщение о превышении контрольного времени Тип=11 Код:0/1
ELSE IF(/base_rtt
Подобный материал:
1   2   3   4   5   6   7   8   9   10   ...   20

Оптимизация TCP. Управление потоком.

Выбор размера TCP-сегмента и синдром “узкого окна”.


Синдром «узкого окна».

Простым и понятным алгоритмом выбора размера сегмента TCP представляется следующий.

Определяем величину MTU (Maximum Transportation Unit), а по ней MSS (Maximum Segment Size). Если она не указанна соответствующей опцией при инициализации сеанса TCP, то принимаем некое значение, принятое по умолчанию (RFC-791 советует 576 байт для IP-пакета, что при отсутствии опций в заголовках TCP и IP дает 536 байт для данных пользователя. С некоторым запасом можно принять 512 байт=0.5Кбайт). В случае, если стек TCP/IP функционирует не в сети Internet, а в некой корпоративной сети, построенной на базе ограниченного числа известных технологий, за MTU можно принять минимальную по технологиям максимальную длину поля данных кадра, за MSS=MTU–120(40)байт (по 60 байт заголовков TCP и IP, либо по 20, если известно, что опции не будут использоваться).

В настоящее время ряд реализаций TCP/IP используют динамическое определение размера пакета, который может быть передан адресату без фрагментации, посредством алгоритма Patch MTU Discovery (RFC-1191). Сущность его заключается в зондировании пути пакетами с установленным флагом запрета фрагментации. Сперва посылается пакет максимального размера. Если приходит сообщение о его ликвидации по причине необходимости фрагментации, размер зондирующего пакета уменьшается. Поскольку максимальные размеры кадров/пакетов основных базовых технологий известны, можно упорядочить их по убыванию и использовать для определения размера следующего зондового пакета, так что допустимый размер находится всего за несколько проб. Если сообщение о ликвидации пакета указывает допустимый размер на следующем шаге, число проб может быть еще сокращенно.

Если размер окна, показанного программой на противоположном конце соединения в последнем сегменте, больше MTU, то за размер сегмента принимаем MTU, если меньше – размер окна.

Однако такой простейший подход может приводить к нежелательным результатам. Одним из них является так называемый «синдром глупого окна» (Робачевский [2]) или «синдром узкого окна» (silly window syndrome– SWS; Clark, 1982).

Он заключается в том, что, однажды возникнув, малые окна могут повторяться снова и снова. Выделение очень малого окна приводит к передаче данных очень маленькими сегментами, тогда как лучший режим осуществляется при использовании сегментов большего размера. Ведь каждый сегмент несет в себе, по крайней мере, 40 байт служебной информации (минимум по 20 байт заголовков TCP и IP), независимо от того, сколько он несет полезной информации.

Время от времени у TCP-клиента возникает необходимость отправить небольшой сегмент немедленно (с установкой флага PUSH).

Кроме того, можно ожидать, что при не очень большом окне программа TCP вначале отправит столько данных, сколько может, то есть полностью использует заявленное окно раньше, чем придет первое подтверждение, а далее передача будет осуществляться по мере получения подтверждений.

Если программа TCP просто посылает столько данных, сколько может, всякий раз, когда окно ненулевое, то передаваемые данные будут разбиваться на большие и малые сегменты. Действительно, раз отправив небольшой сегмент, мы затем вынуждены будем отправить один из последующих сегментов размером поменьше, поскольку это будет диктоваться оставшимся окном.

Пусть окно =2Кбайт, и мы ведем передачу сегментами по 512 байт. В определенный момент нам нужно срочно отправить, допустим, 64 байта. Получив подтверждение на очередной сегмент 512 байт, мы немедленно отправляем наши 64 байта, а последующий наш сегмент будет иметь размер, равный оставшемуся окну, т.е. 448 байт. Отправляя данные в пределах разрешенного окна, мы через некоторое время получим подтверждение наших 64 байт, которое откроет нам окно на 64 байта, и отправим новый сегмент 64 байта, затем то же повторится с подтверждением 448. Снова 512 байт оказались разорванными на 2 сегмента, хотя необходимость в этом уже отсутствует!

По истечении некоторого времени случающиеся паузы в выделении окна получателем данных приведут к разбивке больших сегментов на многочисленные и уже не столь большие пары. По прошествии некоторого времени передача данных будет осуществляться преимущественно малыми сегментами. Это приводит к росту накладных расходов и засорению сети множеством коротких сегментов в одну сторону и множеством подтверждений – в другую.

Чтобы избежать применения малых окон, получателю данных предлагается откладывать изменение окна до тех пор, пока свободное место не составит X процентов от максимально возможного в памяти для этого соединения, где X может быть от 20 до 40 (RFC-793). Робачевский [2] советует 50% максимального окна, либо MSS, в зависимости от того, какое из двух значений больше.

Другой совет, чтобы не посылать малые сегменты, состоит в том, чтобы отправитель не спешил с посылкой данных, пока окно не станет достаточно большим. Но если клиент дает команду на использование функции проталкивания, то данные следует немедленно отправлять, даже если это будет осуществляться малым сегментом.

Робачевский [2] даже советует воздерживаться от посылки подтверждений, если, во-первых, принятый сегмент не несет флага PUSH, что дает основания предполагать, что за ним вскоре последуют другие сегменты, и во-вторых, если нет необходимости передать измененное значение окна. К сожалению, это противоречит рекомендации RFC-793. Во избежание ненужных повторных пересылок не нужно медлить с посылкой подтверждений. Стратегия может заключаться в посылке подтверждения при получении сегмента малого размера (без обновления информации об окне), затем посылается другое подтверждение с новой информацией об окне, если последнее расширяется. Следует, правда, отметить, что это – сужение приемного окна, а оно не приветствуется тем же RFC-793.

Сегмент, посылаемый для проверки нулевого окна, также может инициировать разбивку передаваемых данных на все более и более мелкие сегменты. Если сегмент, содержащий единичный байт данных и отправленный для проверки нулевого окна, получен, то он займет один байт в имеющемся в данный момент окне. Если программа TCP просто посылает столько данных, сколько может, всякий раз, когда окно ненулевое, то передаваемые данные будут разбиваться на большие и малые сегменты. По истечении некоторого времени случающиеся паузы в выделении окна получателем данные приведут к разбивке больших сегментов на пары, и так далее. Вновь по прошествии некоторого времени передача данных будет осуществляться преимущественно малыми сегментами.

Предложение состоит в том, чтобы реализации протокола TCP активно пытались объединить малые окна в более крупные, поскольку механизмы управления окном стремятся ввести много малых окон в простейших реализациях протокола.

Медленный старт в TCP.


Как мы уже отмечали простейшие реализации протокола TCP вначале отправят столько данных, сколько может (то есть полностью использует заявленное окно), не дожидаясь подтверждения даже первого сегмента, а далее передача будет осуществляться по мере получения подтверждений.

В этот начальный период, когда обратная связь еще отсутствует, особенно в том случае, когда станция-отправитель имеет в своем распоряжении высокоскоростной канал, а получатель, в полном соответствии с требованиям RFC-793, заявил достаточно большое окно, такая реализация может привести к взрывообразному росту трафика, и спровоцировать затор, переполнение буферов промежуточных маршрутизаторов, и, как следствие, потерю пакетов. Потеря пакетов, в свою очередь, приведет к их повторной передаче в том же темпе, причем, скорее всего, не только потерянных, но и всех, следующих за первым потерянным. Создается эффект, подобный “пробке” на дороге в час пик, когда рост нагрузки замедляет ее обслуживание, снижает реальную пропускную способность.

Поэтому желательно было бы ввести обратную связь на возможно более раннем этапе.

С другой стороны, передача по одному сегменту не позволяет использовать преимущество большого окна и пропускную способность канала. Если протокол TCP работает таким образом в небольшой локальной сети, время ожидания подтверждения будет, скорее всего, небольшим и с передачей по одному сегменту в этом случае можно смириться. Но в крупной корпоративной сети, а тем более в Internet, с такими издержками мириться нельзя.

Эффективная скорость передачи может быть оценена как B=window*MSS*8/RTT;

где B – эффективная скорость виртуального канала в бит/с, а MSS – максимальный размер сегмента в байтах, а размер окна window – в сегментах.

Хорошим компромиссом является алгоритм, известный как «медленный старт» (slow start). Суть его заключается в следующем.

Наряду с существующим, вводится дополнительное окно отправителя, называемое окном переполнения (congestion window, CWND). Это окно показывает объем данных, которые отправитель может послать, не дожидаясь подтверждения. Таким образом, максимальный объем данных, пересылаемых не дожидаясь подтверждения, определяется меньшим из двух значений – свободного окна, заявленного получателем, и окна переполнения CWND. В начале, перед пересылкой первого сегмента данных, CWND устанавливается равным одному сегменту.

Таким образом, модуль TCP отправителя отправляет один сегмент и ждет подтверждения. После получения подтверждения он увеличивает окно переполнения до двух сегментов, отправляет 2 сегмента и ждет подтверждений. Когда передача каждого сегмента текущего окна переполнения подтверждена, окно переполнения удваивается CWNDn+1=2*CWNDn.

По мере отправления сегментов и получения подтверждений размер окна переполнения растет в геометрической прогрессии, и если все в порядке, то достаточно быстро оно достигает размера окна приема.

В условиях, когда время передачи сегмента много меньше времени ожидания подтверждения (обычно в достаточно большой сети так и есть), через t=n*RTT (Round Time Trip – Время оборота) CWNDn=2n*CWND0=2n*MSS.

Таким образом, достаточно быстро достигается режим, когда количество отправляемых данных управляется окном получателя, но при этом на каждом этапе медленного старта осуществляется обратная связь. Может произойти так, что на определенном этапе скорость отправки сегментов превысит эффективную пропускную способность сети между отправителем и получателем. Это приведет к росту RTT и задержит дальнейший рост окна переполнения CWND. Далее в таком случае следует задействовать алгоритм преодоления затора.

Устранение перегрузок средствами TCP.


Затор, или переполнение, для большой сети явление неприятное, но закономерное. Даже в локальных сетях, построенных на коммутаторах, возможны ситуации, когда трафик, направляемый извне в какой-либо сегмент сети, превысит пропускную способность либо самого этого сегмента сети, либо канала/транка, связывающего этот сегмент с остальной сетью. Затор возникает в сети по многим причинам, связанным с временным колебанием трафика, изменением состава сети и предоставляемых сервисных служб, а иногда и с нерациональной работой алгоритмов маршрутизации, когда данные направляются по низкоскоростному каналу вместо более быстрого потому, что маршрут, включающий этот канал имеет, с точки зрения алгоритма маршрутизации, более привлекательную метрику, либо игнорируются альтернативные маршруты.

Ситуация затора может диагностироваться по сообщениям ICMP, прежде всего вспомним сообщение для приостановки отправителя Тип=4 Код=0. Оно отправляется шлюзом, который вынужден ликвидировать IP-пакеты, когда у него нет места в буфере. Сообщение о приостановке может послать и адресат, если пакеты приходят слишком быстро, чтобы успеть их обработать. Сообщение о приостановке является запросом для отправителя уменьшить скорость посылки данных на этот конкретный адрес. Реакция на него должна обеспечиваться модулем TCP/IP отправителя, который может снизить скорость передачи пакетов, например, вдвое, либо прекратить передачу на какое-то время.

Косвенным свидетельством затора является также Сообщение о превышении контрольного времени Тип=11 Код:0/1, показывающее, что пакет «умер от старости» в буфере маршрутизатора, либо фрагменты пакета не были собраны получателем до истечения контрольного времени.

Если в ходе TCP-сессии получено сообщение ICMP(4) (переполнение канала – приостановка отправителя quench), требующее снижения потока данных, то CWDN делается равным одному сегменту, а величина порога медленного старта SSTHRESH не изменяется. Но следует помнить, что потеря пакета может произойти на устройствах, не поддерживающих ICMP.

Протоколом TCP ситуация затора может определяться по следующим признакам: увеличение времени оборота RTT, неполучение подтверждения до истечения контрольного времени, получение дубликатов подтверждения. Все алгоритмы устранения затора основаны на предположении, что потеря сегментов из-за ошибок данных по вине технологий канального и физического уровня – явление очень редкое, (вероятность его, во всяком случае, менее 1%). При использовании современных сетевых технологий эти условия, как правило, выполняются. Следовательно, потеря данных свидетельствует о заторе. Если потеря пакетов из-за их искажения существенна, понижение CWND не поможет, и пакеты будут теряться с той же вероятностью (здесь было бы уместно поискать оптимальное значение MTU/MSS).

В этом случае запускается алгоритм устранения затора. Вот один из таких алгоритмов, реализованный совместно с алгоритмом медленного старта.

В этом случае добавляется еще один параметр, управляющий окном передачи – порог медленного старта SSTHRESH порогу (ssthresh = slow start threshold).

В начальный момент SSTHRESH инициализируется значением 65535 (64К-1), а CWND, как и прежде, 1 MSS.

В случае обнаружения затора (по получению дубликатов подтверждений, тайм-ауту) порог медленного старта SSTHRESH устанавливается равным половине текущего окна передачи, но не менее 2 MSS. Если причиной решения является тайм-аут повторной передачи, то дополнительно окно переполнения CWND устанавливается равным 1 MSS, таким образом, заново запускается медленный старт. Но медленный старт в его классическом варианте продолжается только до того момента, пока CWND. После этого алгоритм расчета нового CWND меняется с геометрической прогрессии на арифметическую, при которой за один цикл подтверждения окна происходит приращение не более, чем на один сегмент (MSS).

CWNDn=1=CWNDn+MSS

В некоторых случаях рекомендуется еще меньшее приращение, например, CWNDn=1=CWNDn+(MSS*MSS)/CWNDn+MSS/8, (TCP-reno, 1990г), но малое приращение может спровоцировать синдром узкого окна!

Таким образом, после порога медленного старта скорость передачи растет гораздо медленнее, чем в исходном алгоритме медленного старта. Это сокращает скорость передачи (поскольку она определяется размером окна), точнее, замедляет ее рост, и таким образом, способствует рассасыванию затора. Этот режим называется режимом исключения перегрузки (congestion avoidance), или AIMD (Additive Increase, Multiple Decrease).

С другой стороны, когда TCP обнаруживает потерю пакета по получению дубликатов подтверждений, запускается алгоритм быстрой повторной передачи, CWND(t) и SSTH(t) обновляются иначе:

SSTH(t) =(CWND(t))/2; CWND(t)=SSTH(t);

Дело в том, что получение дубликатов подтверждений может свидетельствовать о получении неупорядоченных сегментов. Получение более чем 2-х дубликатов в этом случае рассматривается как свидетельство потери (возможно, случайной) именно того сегмента, который следует за последним подтвержденным, и этот сегмент передается повторно, не дожидаясь истечения тайм-аута повторной передачи, таймер повторной передачи этого и последующих сегментов пересчитывается, но медленный старт не запускается. Основанием таких действий является соображение, что приход дубликатов подтверждений свидетельствует о том, что вообще-то пакеты в сети нормально проходят, потеря одного обусловлена случайными причинами, следовательно, необходимости в запуске медленного старта нет. Режим быстрой повторной передачи приближает TCP к системам с адресным переспросом. Алгоритм TCP-reno после этого переходит в фазу быстрого восстановления. В этой фазе размер окна увеличивается на один сегмент, когда получается дублированное подтверждение (ведь подтверждение, хотя бы дубликат, свидетельствует, что какой-то полноразмерный сегмент покинул сеть). С другой стороны, CWND(t) делается равным SSTH(t), когда приходит не дублированный отклик для пакета, посланного повторно. В случае таймаута SSTH(t)=(CWND(t))/2; CWND=1.

Алгоритмы быстрой повторной передачи и быстрого восстановления (Fast Retransmit/Fast Recovery) таким образом, приближают TCP, который в исходном варианте представляет собой протокол со скользящим окном и возвратом к первому потерянному сегменту (если для сегмента истек таймаут повторной передачи, то скорее всего, и все сегменты, отправленные после него, до получения подтверждения будут переданы повторно), к алгоритму со скользящим окном и селективным переспросом, что повышает его производительность при случайных потерях пакетов.

TCP-Vegas (1994г) контролирует размер окна путем мониторинга отправителем RTT для пакетов, посланных ранее. Если обнаруживается увеличение RTT, система узнает, что сеть приближается к перегрузке и сокращает ширину окна. Если RTT уменьшается, отправитель определит, что сеть преодолела перегрузку, и увеличит размер окна. Следовательно, размер окна в идеальной ситуации будет стремиться к требуемому значению.

. В частности на фазе исключения перегрузки, размер окна будет равен

DIFF=(CWND(T)/base_rtt)-(CWND(T)/rtt)

IF(DIFF</base_rtt) CWND(T+Ta)= CWND(T)+1

ELSE IF(/base_rtt

ELSE CWND(T+Ta)= CWND(T)-1

END IF

где rtt[сек] зарегистрированное RTT, base_rtt[сек] наименьшее встретившееся в данном цикле RTT, а a и b - некоторые константы. Эта модификация ТСР требует высокого разрешения таймера отправителя.

Алгоритмы медленного старта, устранения заторов, быстрой повторной передачи и быстрого восстановления описаны документом RFC-2001 и реализованы в большинстве современных TCP-систем.

Все эти оптимизации не работают для коротких сеансов (не успеет алгоритм подобрать окна, а все данные уже переданы). Интересной возможностью является привлечение вместо ТСР протокола T/TCP (TCP for Transactions), который улучшает эксплуатационные характеристики виртуального канала в случае коротких транзакций. T/TCP помещает данные запроса и флаг завершения FIN в начальный SYN-сегмент. Это может интерпретироваться, как попытка открыть сессию, передать данные, и закрыть сессию со стороны отправителя. Если сервер воспринимает такой формат, он откликнется одним пакетом, содержащим SYN-отклик, ACK на полученные данные и закрывающий сессию флаг FIN. Для окончательного завершения сессии клиент должен послать серверу сегмент с флагами ACK и FIN. К сожалению, внедрение T/TCP предполагает модификацию программного обеспечения, как сервера, так и клиента. Для многих реализаций TCP получение сегмента с флагами SYN и FIN приведет к созданию не полностью открытого соединения, причем не исключено, что и Keepalive-таймер не будет активирован, так что это соединение будет существовать до перезагрузки сервера.

Следует отдавать себе отчет, что алгоритмы управления потоком не всесильны. Борясь с заторами на канальном, сетевом и транспортном уровнях, эти алгоритмы, в конце концов, загоняют его на прикладной. Само по себе управление потоком не создает пропускной способности и, в общем случае, не уменьшает задержку у пользователя. В лучшем случае они могут предотвратить перегрузку в сети, ухудшающую положение всех (или многих) пользователей, чаще же всего – относительно быстро преодолеть критическую перегрузку, которая уже возникла. Если в сети, или каком-то ее элементе, перегрузки возникают регулярно – это предмет анализа и вмешательства администратора.