net

March 20, 2009

Сетевой стэк в линуксе по умолчанию рассчитан на скорость 100Mbit/s в отличие от Windows 2003 Server и ниже, чей стэк рассчитан на скорости не более 10 мегабит в секунду.
В принципе даже на гигабите сетевой стэк работает хорошо (и на windows в том числе), но только если система не испытывает серьёзных нагрузок, например раз в час кто-нить скачивает файлик размером менее 10 мегабайт, но если дело касается файлового сервера или веб-сервера или какого-либо другого сервера ситуация заметно меняется и не в лучшую сторону (катастрофы, конечно, не происходит, но ресурсы расходуются неоптимально).
Для файлового сервера принципиально максимальное использование предоставленного канала (даже в ущерб задержкам), то есть скорость передачи данных.
Для веб-сервера ил днс сервера принципиальна интерактивность работы (время отклика от сервера должно быть минимально даже если канал при этом используется не полностью).
Время отклика от сервера это очень важный показатель для любых видов серверов.
Для повышения эффективности сетевого стэка его надо настроить на определённый вид нагрузок, для этого необходимы достаточно глубокие знания поведения пакетов в сети, знание приёмов, используемых стэком для управления потоком данных, это исключительно статистическая информация, то есть то, что я тут рекомендую обязательно надо скорректировать под конкретный случай, под конкретный сервер, под конкретную нагрузку.
Сейчас я постараюсь вкраце, простенько изложить принцип работы сетевых протоколов в вопросах управления скоростью передачи данных и эффективностью использования предоставленной ширины пропускания канала...
Скорость передачи данных зависит от ёмкости канала по которому они передаются и эффективности его использования, как правило чем более эффективно используется канал, тем выше задержки при передаче информации. На данный момент в контексте протокола IP(далее всё будет относиться к протоколам передачи данных именно в контексте IP) популярны один сессионный протокол — tcp и два не сессионных протокола icmp и udp. Не сессионные протоколы как правило характеризуются тем, что подтверждение (если оно нужно) в ответ на полученные данные выполняется приложением, а не ядром, то есть доставка данных  самим протоколом не гарантируется. Сессионные протоколы в частности tcp гарантируют целостность принятых пакетов путём подтверждения получения каждого пакета, то есть для передачи данных устанавливается двунаправленная связь между источником и получателем данных — сессия, все ошибки как правило обрабатываются ядром операционного окружения (если приложением использутся не RAW сокеты и все потроха tcp не реализованы в самом приложении).
Для управления потоком данных используется протокол ICMP (http://ru.wikipedia.org/wiki/ICMP), который является неотъемлемой частью реализации протокола IP (именно поэтому крайне не рекомендуется полностью отключать поддержку ICMP путём срезания этих пакетов на файрволле).
UDP — это протокол, который используется для приложений, которым важно чтобы время ответа было минимальным (DNS) и важна высокая интерактивность, а целостность данных не очень принципиальна (интернет-радио, некоторые игры). Для несессионных протоколов их скоростью и интерактивностью можно управлять (на уровне системной части операционного окружения) только с помощью оптимизации длины буфера отправки пакетов, приложение или подсистема, отправившая пакет, могут узнать о сбое по тайм-ауту или нарушению последовательности пакетов.
TCP — это сессионный протокол гарантирующий доставку и целостность данных ( http://en.wikipedia.org/wiki/Transmission_Control_Protocol ). Поскольку в ядре операционного окружения (в частности ОО дистрибутивов Linux) предусмотрен механизм управления потоком данных tcp то влиять на этот поток можно не только с помощью длины очереди отправки пакетов, но и некоторыми методами, благо это возможно. Но для начала необходимо рассмотреть опять же кратко как работает стэк tcp. Допустим что мы установили tcp соединение (клиент послал syn, получил syn/ack, послал ack) и потекли данные... поскольку tcp не знает какова скорость передачи данных в предоставленном канале между сервером и клиентом, то начинает он со скромных скоростей ( http://en.wikipedia.org/wiki/Slow-start ) передачи данных и повышает частоту генерации пакетов по экспоненте до тех пор пока не перестанут приходить ответы на посланные пакеты или не начнут приходить сообщения об ошибках, как только появляется ошибка, tcp моментально сбрасывает скорость генерации пакетов, перепосылает пакет вызвавший ошибку и начинает снова её (скорость) повышать (потери при передаче данных по протоколу tcp — это нормальное явление), то есть если посмотреть на график зависимости скорости передачи данных от времени, то в классическом случае он пилообразный, с резкими падениями скорости (на форму переднего фронта влияет алгоритм повышения скорости, т.н. congestion avoidance algorithm , задний фронт будет всегда вертикальным). Механизм, который задаёт скорость и наращивания скорости после сбоя называется congestion control. Но есть маленький нюанс — если передавать следующий пакет исключительно после получения подтверждения о приёме посланного пакета, то об эффективности использования ширины пропускания предоставленного канала можно забыть (соответственно, будет сравнительно низкая скорость передачи данных) чтобы повысить эффективность использования ресурсов был придуман механизм т.н. избирательного подтверждения доставки пакетов, sack, при котором допустимо отправить ещё несколько пакетов не дожидаясь приёма подтверждения об отправке, однако отправить можно не больше, чем window size (предлагается клиентом, меняется сервером в зависимости от потерь и задержек подтверждения) данных без подтверждения, после чего ожидается подтверждение поступления первого пакета. Скорость реагирования на ошибки в этом случае менее интерактивна, однако за счёт пропагандирования более высокой скорости передачи данных стэк tcp поддерживает поток на уровне, более близком к физическому максимуму канала пропускания. Существует также механизм использующий дополнительные метки времени в каждом пакете tcp (т.н. Timestamps) позволяющие более эффективно и точно вычислять задержки при доставке пакетов и более адекватно корректировать window size.

.ipv4.ip_default_ttl

задаёт значение TTL, наиболее популярные значения 64 - linux, hp, 128 - windows, 255 - solaris, cisco.

net.ipv4.ip_local_port_range

диапазон портов источников, с которых отправляются ip пакеты(?)

net.ipv4.ip_forward

1 - разрешить проброс пакетов между сетевыми интерфейсами

0 - запретить проброс пакетов между интерфейсами

net.ipv4.tcp_abc

net.ipv4.tcp_adv_win_scale

net.ipv4.tcp_app_win

net.ipv4.tcp_congestion_control

net.ipv4.tcp_dsack

net.ipv4.tcp_fin_timeout

net.ipv4.frto

net.ipv4.tcp_max_orphans

net.ipv4.tcp_max_syn_backlog

net.ipv4.tcp_max_tw_buckets

net.ipv4.tcp_mem

net.ipv4.tcp_moderate_rcvbuf

net.ipv4.mtu_probing

net.ipv4.tcp_no_metrics_save

net.ipv4.tcp_orphan_retries

net.ipv4.tcp_reordering

net .ipv4.tcp_retrans_collapse

net.ipv4.tcp_rfc_1337

net.ipv4.tcp_rmem

net.ipv4.tcp_sack

net.ipv4.tcp_slow_start_after_idle

net.ipv4.tcp_syn_retries

net.ipv4.tcp_synack_retries

net.ipv4.tcp_syncookies

net.ipv4.tcp_timestamps

net.ipv4.tcp_wmem

Next Post