Бачиш somaxconn? І я не бачу. А він є

Мені завжди подобалася FreeBSD. Подобалася лаконічністю, простим і зрозумілим розташуванням і призначенням файлів, елементів, структур і якийсь «теплою», «домашній» консервативністю. Але з виходом 10-ки я помічаю, що вона все більше від мене віддаляється і я не розумію що і навіщо у неї змінюється. І справа навіть не в тому, що не розвиваються ті речі, якими завжди була сильна FreeBSD і які потрібно розвивати, як морально і архітектурно застарілий мережевий стек. Справа в дрібницях.

image
— Бачиш ховрашка?
— Ні.
— І я не бачу. А він є!

© ДМБ (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.
$ 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, "І",
"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, "І",
"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.2 BSD. 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 — навіщо?
Мені навіть страшно уявити, що може статися з десятками інших параметрів ядра, які не відображають точного сенсу…
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.