Re: nginx 1.18.0 ест всю память и swap на Ubuntu Server 20.04.1 LTS
Maxim Dounin
mdounin на mdounin.ru
Пн Авг 31 16:41:18 UTC 2020
Hello!
On Mon, Aug 31, 2020 at 04:48:36PM +0300, Alexey Galygin wrote:
> мы запросили у организации, которая занимается DDoS Protection
> список всех запросов за интервал теста
>
> пытаемся по этим ссылкам ходить скриптом…
>
> на штатный resize пришлось не более 800 запросов за всё время эксперимента, вряд ли бы это забило всю память
> (файлики jpg они маленькие, ну допустим текло по 1 Мб на запрос, ну утёк бы 1 Гб за 5 минут, а не 300…)
>
> ну и точно такой же nginx 1.18.0 на эталонном сервере так не утекает
>
> изменилось в стенде только — Ubuntu — была 16.04 стала 20.04 (тут я подозреваю, сменился аллокатор памяти, что-то с FS подкрутили, может дескрипторы если не утекают, то кэш избыточный накапливается в ОЗУ)
> память — было 192 — стало 256
> FS как была ext4 так и осталась ext4…
> ЦОД — было нормальное железо — стала платформа VMWare Cloud Director… на вид работает даже шустрее
Это называется "сменилось примерно всё".
Я бы начал с простого:
0. Внимательно изучил конфигурацию.
Простая оценка максимального потребления памяти рабочим процессом:
worker_connections * (сумма всех буферов в конфиге). Стандартные
размеры буферов невелики, и сумму всех можно смело считать как
"меньше одного мегабайта", если в конфиге задано что-то иное -
соответственно прибавлять. Относительно большие размерыы буферов
встречаются только в image-фильтре (image_filter_buffer 1m) и mp4
(mp4_max_buffer_size 10m).
Нюанс: простая оценка не работает, если используются подзапросы
(SSI, cache background update, и так далее - каждый подзапрос
может иметь свои буфера, соответственно надо умножать на
количество подзапросов в одном соединении) и/или HTTP/2 (умножать
на http2_max_concurrent_streams + http2_max_concurrent_pushes).
Если результат больше или сравним с наблюдаемым потреблением
памяти - то чинить конфигурацию, если заметно больше - то искать
дальше.
Если я правильно помню приведённые фрагменты конфига, то там 4096
worker_connections, буферов мегабайта на 2 минимум, используется
background update. Если HTTP/2 не используется, то общее
потребление памяти в пределе будет 4096 * 2m * 2 == 16 гигабайт.
Это меньше, чем наблюдается, но не сильно. Что уже наводит на
всяческие мысли. Если же ещё и HTTP/2 используется - то один
рабочий процесс может занимать до пары терабайт, что явно не
соответствует возможностям машины.
То есть в принципе все наблюдаемые эффекты могут просто
объясняться конфигурацией и характером нагрузки, без всяких
утечек. Можно попробовать отключить HTTP/2, если вдруг
используется, и/или покрутить размеры буферов вниз. Ну и
количество рабочих процессов тоже.
Отдельный вопрос - почему не наблюдаются такие же или близкие
размеры рабочих процессов на старом сервере. Если конфигурации
полностью совпадают - возможно, причина в несколько другом
характере нагрузки, в частности - из-за смены ядра и платформы.
Меня, в частности, сильно смущает, что все рабочие процессы в
состоянии "D", смотреть стоит на дисковую подсистему.
1. Если есть какие-то сторонние модули - исключил их из конфига
(или сборки, если они собраны статически), и убедился, что
проблема воспроизводится. Если модули очень нужны - то можно
попробовать переписать конфиг так, чтобы вынести их в отдельный
инстанс nginx'а.
2. Если в конфиге используется скриптовый код - perl, njs,
whatever - то этот код может потреблять произвольный объём памяти,
даже если код кажется простым. Опять же, лучше всего попробовать
воспроизвести проблему без этого кода.
Ну и логи таки имеет смысл почитать, дабы точно понимать, что
происходит, а не строить предположения.
[...]
--
Maxim Dounin
http://mdounin.ru/
Подробная информация о списке рассылки nginx-ru