Как стать автором
Обновить

Дело всегда в TCP_NODELAY

Уровень сложностиПростой
Время на прочтение4 мин
Количество просмотров14K
Всего голосов 56: ↑56 и ↓0+84
Комментарии31

Комментарии 31

Начну с бесспорного утверждения: если вы создаёте чувствительную к задержкам распределённую систему, работающую на современном оборудовании датацентра, смело включайте TCP_NODELAY (то есть отключайте алгоритм Нейгла).

Если вы создаёте чувствительную к задержкам распределённую систему, используйте UDP. И ARP подкручивайте.

Вариант не проходить tcp хендшейк для каждого сообщения заново и просто использовать существующее соединение не рассматривается? ARP, кстати, можно не подкручивать (из-за использования конкретного термина, полагаю вы про таймеры), а делать gratuitous (а в ряде кейсов, например если клиент - обычный пользователь обычного оператора, имеющего вагон security штук а-ля rpf, подкручивать что-либо бесполезно в принципе). Про применимость arp в контексте ipv6 вообще душнить не буду.

Короче говоря, вы крайне категоричны.TCP/UDP - всего лишь транспорт. И, увы, на лэтэнси гораздо сильнее влияют совершенно другие, более физические вещи.

Даже если сделать хендшейк и держать коннект открытым - всё равно проблемы NODELAY, особенно в компании с delayed ACK, больно бьют, если оные вещи не выключить.

К сожалению часто это невозможно т.к. нужен, например, HTTP. А поддержка HTTP/3 нынче не очень широка в разных библиотеках и часто экспериментальна.

Даже интересно - хотя бы HFTшники (вот уж где latency важно) опускаются до UDP?

Не знаю про HFT (надеюсь, прокомментируют более близкие к теме люди), но это далеко не самая чувствительная область. В HFT вы рискуете максимум деньгами. А бывают приложения, где от задержек зависят жизни людей.

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

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

А от потерянных пакетов они не зависят?

Потерянные пакеты необязательно ловить средствами именно TCP.

Но вообще такие системы строятся так, что пакеты в штатном режиме не теряются.

Причина потери пакетов – либо сбой в работе оборудования, либо переполнение пропускной способности канала.

Выглядит так, что в таком случае TCP/IP стек - вообще лишнее, нужен просто надёжный аппаратный канал и какое то минимальное API поверх него. UDP/IP - уже не самая легковесная прослойка, надо думать, как IP пакеты нарежутся на аппаратные фреймы и т.д.

Тут дело в том, что свой драйвер под каждую сетевую карту геморройно писать.

Хотя мы как-то писали свой стек, было дело.

Уже упомянутый в треде DPDK не поможет? Даже в ядро лазить не придётся.

В DPDK тоже есть свои драйверы, причём только для небольшого числа железок.

Там куча железа поддерживается и нет никакой проблемы просто взять лучшую поддерживаемую сетевуху, допустим, если есть такая необходимость. В HFT & co стоимость конечного железа это мизерный процент от всех трат.

Для HFT да. А для промышленной автоматизации выбор железа определяется другими характеристиками. Какой-нибудь там температурной или радиационной стойкостью, например.

Это канальный уровень. Но вопрос API всё равно остаётся.

Если ретрансмит дорог (как при связи в Марсом, например, или Вояджерами), то нужно просто использовать коды избыточности, чтобы можно было компенсировать потерянный пакет.

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

Они часто и до DPDK опускаются

Такие издержки в 4 000%, конечно, раздражают, но в слабо нагруженных сетях ещё терпимы.

и

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

Судя по описанию и датам в тексте, это проблема эпохи палеолита, когда сети в 10 Мб\с были чем-то из научной фантастики, а в качестве процессора везде использовался Intel 80386.

В современных сетях я ни разу о такой проблеме даже не слышал.

в embedded системах с TCP/IP это становится важным, например когда у нас в сети куча девайсов по mqtt работают

Сейчас даже в таких системах используются преимущественно 100 Мбит трансиверы, чтобы из-за одного 10 Мбит девайса вся сеть не падала в 10 Мбит. А на 100 Мбит отправить 1,5 кБ пакет классическим способом будет быстрей, чем вот так извращаться с единичными байтами. Если же трафик тарифицируемый или сеть сильно загружена, то часто можно на стороне источника данных насобирать в буфер килобайт данных, после чего выплюнуть в сеть весь буфер.

нет, я имею в виду внутренний LAN и например много сенсоров. У mqtt пакеты коротенькие, без TCP_NODELAY латентность растёт неприятно

Если смотреть на вопрос шире конкретного TCP_NODELAY, то это противопоставление эффктивного использования полосы пропускания и минимизации задержек.

В локальных сетях это выстреливало в части VoIP и конвергентной инфраструктуры.

Или вот к примеру вполне современный гайд от vmware, как оптимизировать vSphere по сетевым задержкам https://www.vmware.com/docs/perf-latency-tuning-vsphere8

Судя по описанию и датам в тексте, это проблема эпохи палеолит

В ssh до недавнего времени посылали по одному байту. только потом начали подбирать пароли при интерактивном вводе: https://habr.com/ru/companies/ruvds/articles/770792/

Только в случае ssh фиксили другую проблему и другим образом. Фиксили возможность снизить количество комбинаций для перебора путем анализа таймингов между пакетами. И фиксили просто обфускацией интервалов отправки тех же самых пакетов.

Судя по описанию и датам в тексте, это проблема эпохи палеолита

Там первой же строчкой в статье

Занимаясь отладкой проблем в легаси-системах

Ваш К.О.

Вообще странно что в современных ядрах Linux эту опцию сокета не выключат по дефолту. По идее обратной совместимости в современном мире оно не должно сломать.

Обратной совместимости сломать не должно, но бенчмарки ухудшит.

А так вроде это в /etc/ настроить можно.

TCP_NODELAY нельзя отключить в sysctl. Нужно в каждой софтине, которая открывает сокет, эту опцию выставлять. В этом и проблема.

Был раньше флаг net.ipv4.tcp_low_latency , но его убрали давно, ещё в 4.х ядрах.

Вообще странно что в современных ядрах Linux эту опцию сокета не выключат по дефолту.

Ядро Linux используется в очень уж разных системах, далеко не только в датацентрах, как в этой статье. Поэтому луше умолчание для нее вынести в конфигурацию (файл и т.п.). И IMHO разумно дать возможность эту опцию настраивать отдельно для каждого сетевого интерфейса, как это было сделано в Windows в давние времена, когда она была ешё NT - к разным интерфейсам даже в одной системе могут бытьподключены весьма разные сети.

Да, хотя бы крутилку в sysctl получить - уже была бы победа...

Зарегистрируйтесь на Хабре, чтобы оставить комментарий