Марк Брукер (Marc Brooker), инженер из компании Amazon Web Services (AWS), разобрал заблуждения, связанные с повышением эффективности передачи мелких сообщений при использовании
алгоритма Нейгла, применяемого по умолчанию в TCP/IP стеке. Рекомендации сводятся к отключению по умолчанию алгоритма Нейгла через выставление опции TCP_NODELAY для сетевых сокетов при помощи вызова setsockopt, что уже давно делается в таких проектах, как Node.js и curl.
алгоритма Нейгла, применяемого по умолчанию в TCP/IP стеке. Рекомендации сводятся к отключению по умолчанию алгоритма Нейгла через выставление опции TCP_NODELAY для сетевых сокетов при помощи вызова setsockopt, что уже давно делается в таких проектах, как Node.js и curl.
Алгоритм Нейгла позволяет агрегировать мелкие сообщения для снижения трафика — приостанавливает отправку новых сегментов TCP до получения подтверждения о приёме ранее отправленных данных. Например, без применения агрегирования при отправке 1 байта, дополнительно отправляется 40 байтов с TCP и IP заголовками пакета. В современных условиях использование алгоритма Нейгла приводит к заметному возрастанию задержек, неприемлемых для интерактивных и распределённых приложений.
Приводится три основных довода в пользу использования по умолчанию опции TCP_NODELAY, отключающей алгоритм Нейгла:
- Несовместимость алгоритма Нейгла с оптимизацией «delayed ACK», при которой ACK-ответ направляется не сразу, а после получения ответных данных. Проблема в том, что в алгоритме Нейгла поступление ACK-пакета является сигналом для отправки агрегированных данных, а если ACK-пакет не поступил, отправка выполняется при наступлении таймаута. Таким образом, возникает замкнутый круг и ACK-пакет как сигнал не работает, так как другая сторона не получает данные из-за их накопления на стороне отправителя, а отправитель не отправляет их до таймаута, так как не получает ACK-пакет.
- RFC для алгоритма Нейгла принят в 1984 году и он не рассчитан на параметры современных высокоскоростных сетей и серверов в датацентрах, что приводит к возникновению проблем с отзывчивостью. Задержка между отправкой запроса и получением ответа (RTT) в современных сетях составляет 0.5 мс + несколько миллисекунд при обмене данными между датацентрами в одном регионе + до сотни миллисекунд при отправке по всему миру. За эти миллисекунды современный сервер способен выполнить огромный объём работы.
- Современные распределённые приложения давно не отправляют единичные байты данных, а агрегирование мелких данных обычно реализуется на уровне приложения. Даже если размер полезных данных составляет считанные байты, то, как правило, фактически размер отправляемой информации существенно возрастает после применения сериализации, использования API-обвязок в JSON и отправки с использованием TLS-шифрования. Экономия 40 байтов становится не столь актуальной.
Источник: http://www.opennet.ru/opennews/art.shtml?num=61145