Это хорошая идея, чтобы мультиплексировать блокирующие потоки в TCP-соединение?

13

Мне нужно несколько дуплексных каналов между двумя хостами. Существует несколько преимуществ для установки только одного TCP-соединения. Но я сомневаюсь, что мультиплексирование вызовет некоторые неизбежные проблемы. Повредит ли это производительности или значительно увеличит время ожидания? А как насчет использования памяти и процессора? Есть ли какие-либо предложения или предостережения, которые вы хотели бы дать?

Шервуд Ван
источник

Ответы:

10

TLDR . Основным недостатком, который вы можете заметить при мультиплексировании нескольких каналов поверх TCP (если вы все делаете правильно), является увеличенная задержка из-за блокировки заголовка между каналами.

Следствие: если вы не заботитесь о латентности, у вас все будет хорошо.

С другой стороны, использование одного TCP-соединения «означает меньшую конкуренцию с другими потоками и более долговечные соединения, что, в свою очередь, приводит к лучшему использованию доступной емкости сети» .

Блокировка заголовка строки через TCP

Если вы мультиплексируете несколько каналов поверх одного и того же потока TCP, каналы могут страдать от блокировки заголовка :

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

Когда вы мультиплексируете несколько потоков поверх TCP, вы получаете HOL между каналами .

Если канал A заполнил буфер отправки TCP, вам придется подождать, пока все эти данные не будут получены, прежде чем любые новые данные канала B могут быть эффективно переданы на уровень удаленного приложения.

См. «Мультиплексирование поверх TCP» для получения дополнительной информации о мультиплексировании каналов поверх TCP и обсуждении hackernews .

Примеры мультиплексирования по TCP

Мультиплексирование каналов по SSH (по TCP)

Типичным примером этого является SSH. SSH может мультиплексировать несколько каналов (см ControlMaster, ControlPathи ControlPersistв OpenSSH). Использование этого снижает стоимость инициализации нового сеанса SSH (начальная задержка), но интенсивная передача по одному каналу обычно увеличивает задержку / интерактивность других (что не происходит, если вы используете несколько потоков TCP): если вы используете интерактивный сеансы и начать активную передачу файлов по одному и тому же каналу, ваш сеанс станет намного менее интерактивным.

Мультиплексированный HTTP / 2 через TCP

HTTP / 2 использует мультиплексирование запросов / ответов по TCP, чтобы исправить блокировку HOL. Эта функция рекламируется во многих статьях и статьях о HTTP / 2. В HTTP / 2 RFC претензии:

В HTTP / 1.1 добавлена ​​конвейерная обработка запросов, но это лишь частично устраняет параллелизм запросов и все еще страдает от блокировки заголовка.

[...]

Полученный протокол более дружественен для сети, поскольку можно использовать меньше TCP-соединений по сравнению с HTTP / 1.x. Это означает меньшую конкуренцию с другими потоками и более длительные соединения, что, в свою очередь, приводит к лучшему использованию доступной емкости сети.

Однако, что не обсуждается, так это то, что блокировка HOL не разрешена полностью. HTTP / 2 по TCP все еще страдает ) от блокировки HOL на уровне TCP .

Это обсуждается в этой статье LWN о QUIC:

HTTP / 2 был разработан для решения этой проблемы с использованием нескольких «потоков», встроенных в одно соединение . [...] это создает новую проблему: потеря одного пакета остановит передачу всех потоков одновременно, создав новые проблемы с задержкой. Этот вариант проблемы блокировки заголовка встроен в сам TCP и не может быть исправлен с помощью дополнительных настроек на уровне HTTP.

Другие стратегии мультиплексирования

SCTP

Это одна из отличительных особенностей SCTP (многопоточность), вы можете иметь несколько независимых потоков в одной и той же ассоциации SCTP, и каждый поток не блокирует другие.

Посмотрите SSH по SCTP - Оптимизация многоканального протокола путем адаптации его к SCTP для эффекта использования SCTP во избежание многоканальной блокировки HOL в SSH:

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

[...]

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

SCTP не обязательно прост в развертывании (из-за доступности ОС, взаимодействия промежуточного ящика и т. Д.). Возможна реализация через UDP в пользовательском пространстве .

QUIC (мультиплексирование по UDP)

Другим примером является экспериментальный протокол QUIC , используемый для мультиплексирования HTTP поверх UDP (поскольку мультиплексирование нескольких потоков поверх TCP, когда HTTP / 2 действительно страдает от блокировки HOL ):

QUIC - это новый транспорт, который уменьшает задержку по сравнению с TCP. На первый взгляд, QUIC очень похож на TCP + TLS + HTTP / 2, реализованный в UDP.

[...]

Мультиплексирование без блокировки линии

Протокол QUIC от Google: перемещение Интернета из TCP в UDP представляет собой хороший обзор блокировок QUIC и HOL при мультиплексировании каналов поверх TCP.

В недавней презентации утверждается, что HTTP поверх QUIC улучшает задержку, но улучшение блокировки HOL - это «меньшее преимущество»:

0-RTT, более 50% улучшения задержки

[...]

Меньшее количество повторных передач на основе тайм-аута улучшает задержку хвоста […]

Другие, меньшие преимущества, например, блокировка заголовка линии

Обратите внимание, что хотя QUIC и описывается как «очень похожий на TCP + TLS + HTTP / 2, реализованный в UDP», на самом деле это транспорт общего назначения, который может использоваться независимо от HTTP / 2 и может удовлетворить ваши потребности.

Примечание: HTTP / QUIC будет стандартизирован как HTTP / 3 .

ysdx
источник
Я не думаю, что HOL - это реальная проблема, если есть механизм управления потоком. Открытие нескольких TCP-соединений также создает несколько оконных буферов, которые могут быть неэффективными для использования памяти.
Шервуд Ван
Я рассмотрел SCTP. Но кажется, что SCTP еще не был очень портативным, и устройства NAT справляются с этим плохо.
Шервуд Ван
@SherwoodWang, Наличие механизма потока управления в вашем протоколе мультиплексирования не предотвратит блокировку HOL.
ysdx
Когда у отправителя нет доступных данных, отправитель может отправить кадр управления потоком, чтобы сказать получателю переключиться на следующий мультиплексированный канал и продолжить отправку кадров данных этого канала. Поскольку приемник заполнен, аналогичный механизм также может быть использован. Это определенно предотвращает блокировку HOL только с половиной задержки в оба конца.
Шервуд Ван
@SherwoodWang, проблема TCP HOL действительно на стороне получателя. Если какой-либо пакет был потерян при передаче, получатель не может передать следующие пакеты в пространство пользователя. Он должен ждать повторной передачи и приема пакета. Все оставшиеся данные (событие из другого мультиплексированного потока) блокируются до тех пор, пока этот пакет не будет получен.
ysdx
3

Я бы сказал, что вам нужно прочитать руководство ZeroMQ , шаблоны, которые он дает, с причинами и недостатками, очень важны для чтения.

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

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

gbjbaanb
источник
2

Да, я построил систему клиент-серверной базы данных, используя именно этот принцип.

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

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

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

Мартин Кочански
источник