Размеры очередей

FreeBSD

Переменная sysctl kern.ipc.somaxconn ограничивает размер очереди для приема новых TCP соединений. Значение по умолчанию 128 слишком мало для надежной обработки новых соединений для нагруженного web сервера. Для такого сервера рекомендуется увеличить это значение до 1024 или выше. Демон сервиса может сам ограничивать очередь приема новых соединений (например, sendmail(8), или Apache), но обычно в файле настройки демона есть директива для настройки длины очереди. Более длинная очередь также помогает избежать атак Denial of Service (DoS).

Во FreeBSD команда netstat -Lan показывает размеры очередей на слушающих портах. До версии 4.1-STABLE эта команда выводит примерно следующее:

Current listen queue sizes (qlen/incqlen/maxqlen)
Listen         Local Address        
40/38/3000     *.80                  
0/0/5          *.22

В этом примере максимальный размер очереди на 80-ом порту — 3000 соединений. Это размер задаётся параметром backlog в вызове listen(2) и не может быть больше, чем задано в sysctl kern.ipc.somaxconn. На самом деле, максимальный размер всегда больше указанного в полтора раза, то есть, в данном случае это 4500 соединений. В очереди присутствует 40 соединений, из которых только два готовы для accept(2), а остальные 38 находятся в состоянии установления соединения (например, получен SYN от клиента).

Во FreeBSD 4.1-STABLE появились accept-фильтры и это отразилось на выводе netstat -Lan. Если слушающий порт использует accept-фильтр, то установленное соединение, не прошедшее фильтр, остаётся в очереди как неготовое. Если к предыдущим 40 соединениям в нашем примере добавить 50 соединений, не прошедших фильтр, то netstat -Lan покажет следующее:

Current listen queue sizes (qlen/incqlen/maxqlen)
Listen         Local Address        
90/89/3000     *.80                  
0/0/5          *.22

Обратите внимание, что из двух готовых соединений из первого примера фильтр прошло только одно. Вы спросите, где же находятся 50 не прошедших фильтр соединений в первом примере ? Ответ — они уже приняты сервером, часть из них может быть уже даже давно закрыта. Дело в том, что в современных accept-фильтрах (dataready и httpready) не предусмотрены никакие таймауты и соединение может находиться в очереди несколько часов, пока не будет удалено по истечении keepalive-таймаута в TCP (если он включён).

Во FreeBSD 4.4-STABLE появились syncache и syncookie, и в очереди остались только установленные соединения. Если accept-фильтр не используется, то наш пример выглядит так:

Current listen queue sizes (qlen/incqlen/maxqlen)
Listen         Local Address        
2/0/3000       *.80                  
0/0/5          *.22

а с использованием accept-фильтра — вот так:

Current listen queue sizes (qlen/incqlen/maxqlen)
Listen         Local Address        
1/51/3000      *.80                  
0/0/5          *.22

Таким образом, в современных версиях FreeBSD qlen показывает число соединений, готовых для accept(), а incqlen — число принятых, но не прошедших фильтр, соединений.

Не маловажным фактом стоит отметить, что из incqlen при переполнении выкидываются самые старые соединения.

Linux

В линуксе аналогичные опции выглядят так и дефолтные значения лучше увеличить:

net.core.netdev_max_backlog = 10000
net.core.somaxconn=32768

Замечу, что в линуксе нет ключа -L в команде netstat. Поэтому, либо используем команду ss -l, либо применяем конструкцию

# netstat -ntp --tcp | fgrep ESTABLISHED | awk '{ if ($7 == "-") arrQueue[$4]=arrQueue[$4]+1; } END { for (service in arrQueue) print service" "arrQueue[service]}'

Solaris

В Solaris за это отвечают параметры

tcp_conn_req_max_q
  Specifies the default maximum number of pending TCP connections
  for a TCP listener waiting to be accepted by accept(3SOCKET).

tcp_conn_req_max_q0
  Specifies the default maximum number of incomplete (three-way
  handshake not yet finished) pending TCP connections for a TCP listener.

Но меняются они так (начиная с 11-ой версии):

# ipadm set-prop -p _conn_req_max_q=1024 tcp
# ipadm set-prop -p _conn_req_max_q0=2048 tcp

Для 10-ой версии и ниже так:

# ndd -set /dev/tcp tcp_conn_req_max_q 1024
# ndd -set /dev/tcp tcp_conn_req_max_q0 2048

Приложения.

А что касательно приложений? Дело в том, что выше мы описали глобальные системные параметры, но для каждого приложения ещё есть и свои параметры backlog’a, которые можно узнать из той же команды netstat -Lan.

— nginx:

listen 80 backlog=1024;

— apache

ListenBacklog 1024

— exim

smtp_connect_backlog=1024

— mysql 

back_log=1024

Для некоторых приложений (например, dovecot, vsftpd), нужно править в исходниках переменную BACKLOG (или аналогичную) и пересобирать.

Использовалась информация со следующих источников: http://sysoev.ru, http://opennet.ru

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *