Видишь somaxconn? И я не вижу. А он есть
Мне всегда нравилась FreeBSD. Нравилась лаконичностью, простым и понятным расположением и назначением файлов, элементов, структур и какой-то «тёплой», «домашней» консервативностью. Но с выходом 10-ки я замечаю, что она всё больше от меня отдаляется и я всё больше не понимаю что и зачем в ней меняется. И дело даже не в том, что не развиваются те вещи которыми была всегда сильна FreeBSD и которые нужно развивать, как морально и архитектурно устаревший сетевой стек. Дело в мелочах.
— Видишь суслика?
— Нет.
— И я не вижу. А он есть!
© ДМБ (2000 г. реж. Роман Качанов)
Те кому доводилось тюнить FreeBSD (начиная с 4-ки) без труда вспомнят параметр ядра kern.ipc.somaxconn. С его увеличения обычно начиналось «улучшение» работы с TCP. Он же и сейчас описан в RU-хэндбуке:
12.13.1.2. kern.ipc.somaxconn
Переменная sysctl kern.ipc.somaxconn ограничивает размер очереди для приема новых TCP соединений. Значение по умолчанию 128 слишком мало для надежной обработки новых соединений для нагруженного web сервера. Для такого сервера рекомендуется увеличить это значение до 1024 или выше. Даемон сервиса может сам ограничивать очередь приема новых соединений (например, sendmail (8), или Apache), но обычно в файле настройки даемона есть директива для настройки длины очереди. Более длинная очередь также помогает избежать атак Denial of Service (DoS).
То есть параметр есть?
Здесь и далее
$ uname -or
FreeBSD 10.3-STABLE
Допустим мы не помним в какой секции точно находится somaxconn. Найдём его grep’нув вывод sysctl:
$ sysctl -A | grep somaxconn
$
Нет такого параметра?
Вспоминаем, что он в секции kern.ipc.
$ sysctl kern.ipc.
kern.ipc.maxsockbuf: 2097152
kern.ipc.sockbuf_waste_factor: 8
kern.ipc.max_linkhdr: 16
kern.ipc.max_protohdr: 60
kern.ipc.max_hdr: 76
kern.ipc.max_datalen: 92
kern.ipc.sendfile.readahead: 1
kern.ipc.maxsockets: 2095270
kern.ipc.numopensockets: 77
kern.ipc.soacceptqueue: 128
kern.ipc.shm_allow_removed: 0
kern.ipc.shm_use_phys: 0
kern.ipc.shmall: 131072
kern.ipc.shmseg: 128
kern.ipc.shmmni: 192
kern.ipc.shmmin: 1
kern.ipc.shmmax: 536870912
kern.ipc.semaem: 16384
kern.ipc.semvmx: 32767
kern.ipc.semusz: 632
kern.ipc.semume: 50
kern.ipc.semopm: 100
kern.ipc.semmsl: 340
kern.ipc.semmnu: 150
kern.ipc.semmns: 340
kern.ipc.semmni: 50
kern.ipc.msgseg: 2048
kern.ipc.msgssz: 8
kern.ipc.msgtql: 40
kern.ipc.msgmnb: 2048
kern.ipc.msgmni: 40
kern.ipc.msgmax: 16384
kern.ipc.piperesizeallowed: 1
kern.ipc.piperesizefail: 0
kern.ipc.pipeallocfail: 0
kern.ipc.pipefragretry: 0
kern.ipc.pipekva: 49152
kern.ipc.maxpipekva: 1072775168
kern.ipc.nmbufs: 26114730
kern.ipc.nmbjumbo16: 1360140
kern.ipc.nmbjumbo9: 1813521
kern.ipc.nmbjumbop: 2040212
kern.ipc.nmbclusters: 4080424
kern.ipc.maxmbufmem: 33426839552
$
И визуально его также не обнаруживаем… Но если задать полный путь
$ sysctl kern.ipc.somaxconn
kern.ipc.somaxconn: 128
то суслик находится.
Не обнаружив в man’е sysctl такой особенности вывода параметров и несколько недоумевая смотрим в исходники, где в sys/kern/uipc_socket.c и наблюдаем:
/*
* Limit on the number of connections in the listen queue waiting
* for accept(2).
* NB: The orginal sysctl somaxconn is still available but hidden
* to prevent confusion about the actual purpose of this number.
*/
static int somaxconn = SOMAXCONN;
static int
sysctl_somaxconn(SYSCTL_HANDLER_ARGS)
{
int error;
int val;
val = somaxconn;
error = sysctl_handle_int(oidp, &val, 0, req);
if (error || !req->newptr )
return (error);
if (val < 1 || val > USHRT_MAX)
return (EINVAL);
somaxconn = val;
return (0);
}
SYSCTL_PROC(_kern_ipc, OID_AUTO, soacceptqueue, CTLTYPE_UINT | CTLFLAG_RW,
0, sizeof(int), sysctl_somaxconn, "I",
"Maximum listen socket pending connection accept queue size");
SYSCTL_PROC(_kern_ipc, KIPC_SOMAXCONN, somaxconn,
CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_SKIP,
0, sizeof(int), sysctl_somaxconn, "I",
"Maximum listen socket pending connection accept queue size (compat)");
То есть somaxconn больше не в почёте и заменён на soacceptqueue? Так как этот файл имеет непосредственное отношение к системному вызову listen смотрим его man, где и обнаруживаем:
$ man listen | col | tail -n 11
HISTORY
The listen() system call appeared in 4.2BSD. The ability to configure
the maximum backlog at run-time, and to use a negative backlog to request
the maximum allowable value, was introduced in FreeBSD 2.2. The
kern.ipc.somaxconn sysctl(3) has been replaced with
kern.ipc.soacceptqueue in FreeBSD 10.0 to prevent confusion about its
actual functionality. The original sysctl(3) kern.ipc.somaxconn is still
available but hidden from a sysctl(3) -a output so that existing applica-
tions and scripts continue to work.
What?! Оказывается это сделано с заботой обо мне? Чтобы «предотвратить путаницу»?
А то, что у кого-то в древнем скрипте, который кочует десяток лет может быть парсинг параметров sysctl kern.ipc. или sysctl -A | grep somaxconn никого не волновало? Ну не нравится вам описание функционала данного параметра добавьте параллельно синоним, но убирать-то его из выдачи sysctl зачем?
Мне даже страшно представить, что может произойти с десятками других параметров ядра, которые не отражают точного смысла…