Протокол управления передачей (TCP) — это сетевой протокол, ориентированный на поток, построенный поверх интернет-протокола (IP). TCP гарантирует, что сетевые пакеты принимаются в том порядке, в котором они были отправлены, без дублирования. Это делается с помощью встроенных в TCP механизмов подтверждения и повторной передачи.
Протокол TCP не требует подтверждения каждого IP-пакета перед отправкой следующего. Количество данных (IP-пакетов), которые могут находиться “в полете” до подтверждения другой стороной, называется “окном TCP”. Первоначально окно TCP могло иметь максимальный размер 65 535 байт. Но появление современных сетей сделало это ограничение непрактичным.
В настоящее время данные передаются с гораздо более высокой скоростью, чем когда был изобретен протокол TCP. Скорость передачи данных в центре обработки данных может легко достигать 100 Гбит/с, что делает небольшое окно TCP узким местом для эффективного использования сети.
Вот почему масштабирование TCP-окон было добавлено в качестве официального расширения TCP в RFC 1323 еще в 1992 году. Это расширение позволяет создавать TCP-окна гораздо большего размера, размером примерно до 1 ГБ. В этой статье мы рассмотрим, как работает масштабирование TCP-окна, а также его преимущества и недостатки.
Сначала давайте немного углубимся в TCP-окна и в то, как они работают на практике.
На самом деле существует два TCP-окна, по одному для каждой стороны потока. Одна сторона потока поддерживает ”счетчик отправки“ и «счетчик подтверждения”. Счетчик отправки подсчитывает, сколько байтов было отправлено, в то время как счетчик подтверждения информирует другую сторону о том, сколько байтов было получено. Другая сторона TCP-соединения поддерживает те же счетчики. Оба счетчика представляют собой 32-разрядные поля, встроенные в заголовки пакетов TCP.
На следующей диаграмме показан левый одноранговый узел, отправляющий 90 байт тремя пакетами, а правый одноранговый узел подтверждает прием этих 90 байт, устанавливая свой счетчик подтверждения на порядковый номер, отправленный левым одноранговым узлом:
В приведенном выше примере окно составляло 90 байт. В исходных спецификациях TCP максимальное количество байт, которое можно было отправить без получения подтверждения, составляло 65 535.
В случае быстрой и надежной сети исходное ограничение TCP-окна является огромным узким местом. Первоначальный максимальный размер окна в 65 535 байт при скорости сети 100 Гбит/с преобразуется в трафик продолжительностью около 6 микросекунд. Это означает, что другая сторона должна будет подтверждать полученные данные по крайней мере каждые 6 микросекунд, чтобы полностью использовать доступную пропускную способность сети.
К сожалению, это вряд ли произойдет, учитывая короткий период времени и потому, что операционная система будет чрезвычайно занята обработкой входящих данных и, скорее всего, не будет своевременно отправлять подтверждения.
Передачи обычно происходят неравномерно. В большинстве случаев одна сторона TCP-соединения действует как клиент, который отправляет запрос, а другая сторона отвечает данными. Таким образом, на практике при TCP-соединении подавляющее большинство данных передается однонаправленно, и принимающей стороне придется отправлять пустые пакеты только для подтверждения полученных данных, что неэффективно.
Для большого объема трафика внутри центра обработки данных используются гигантские фреймы Ethernet. Они могут передавать около 9000 байт данных, в то время как обычные фреймы Ethernet — около 1500 байт. При использовании больших фреймов ограничение TCP-окна может быть достигнуто всего после 7 пакетов. Опять же, постоянная потребность в подтверждении от принимающей стороны замедлит сетевой трафик
Масштабирование TCP-окна — это расширение TCP, определенное в RFC 1323. Обе стороны ведут переговоры во время установления соединения с первыми двумя пакетами, которыми обмениваются обе стороны. Для этих двух пакетов установлен флаг TCP “synchronize” (обычно сокращенно флаг SYN). Масштабирование TCP-окна является множителем исходного TCP-окна. Множитель равен степени 2 и может варьироваться от 2^0 (т. Е. Без изменений в окне TCP) до 2^14.
Если первоначальный пакет SYN, отправленный клиентом, включает расширение масштабирования окна со шкалой 0, это позволяет другой стороне согласовать масштабирование окна. Поэтому рекомендуется, чтобы, даже если клиентская сторона не хотела увеличивать размер своего TCP-окна, она по-прежнему включала расширение null для масштабирования TCP-окна, позволяющее серверной стороне согласовывать собственное масштабирование TCP-окна.
Максимальный размер TCP-окна, который может быть достигнут с помощью масштабирования TCP-окна, составляет 2^14 = 16 384, что дает размер окна 16 384 x 65 535 = 1 073 725 440 байт, или приблизительно 1 ГБ. Следует отметить, что размер счетчиков TCP составляет 32 бита, поэтому их все еще можно использовать без изменений, поскольку они могут содержать максимальное значение 4 ГБ.
Если вы используете Linux, вы можете проверить, включено ли расширение масштабирования TCP-окна, выполнив следующую команду:
$ cat /proc/sys/net/ipv4/tcp_window_scaling
При этом будет отображаться “1”, если оно включено, или “0”, если нет.
Чтобы временно включить масштабирование TCP-окна, выполните следующую команду:
$ sysctl net.ipv4.tcp_window_scaling=1
Вот как включить его на постоянной основе:
$ echo net.ipv4.tcp_window_scaling=1 \ > /etc/sysctl.d/50-tcp-window-scaling.conf \ && sysctl --system
Преимущества масштабирования TCP-окна кажутся очевидными, и у вас может возникнуть соблазн включить его везде. Однако бывают обстоятельства, когда масштабирование TCP-окна на самом деле вызывает больше проблем, чем решает, особенно когда сеть ненадежна или работает медленно.
В этом случае лучше иметь окно меньшего размера; в противном случае будет слишком много повторных передач, и производительность TCP—соединения может резко упасть — до такой степени, что подавляющее большинство трафика будет состоять из повторных передач. Учитывая, что сеть изначально медленная и/или ненадежная, вы можете понять, что такая ситуация негативно скажется на производительности TCP-соединения.
Пока используемая вами сеть надежна, а количество отброшенных или задержанных пакетов невелико, включение масштабирования TCP-окна является хорошей идеей и значительно повысит скорость передачи. Однако вам следует использовать небольшое окно в ненадежных или перегруженных сетях, чтобы TCP не запускал слишком много повторных передач и не перегружал сеть еще больше.