MAATRIX / Блог / Утечка памяти на сервере

Утечка памяти на сервере

Утечка памяти на сервере

MAATRIX

Сервер со временем съедает всю память, начинает тормозить, а потом сервисы падают без явной причины — классическая картина утечки памяти. Проблема коварна тем, что нарастает постепенно и проявляется не сразу. Ниже — как отличить настоящую утечку от нормального поведения, найти процесс-виновника и устранить причину, а не только симптом.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Как понять, что это именно утечка

Сначала разберёмся с терминами, потому что не всякий рост потребления памяти — утечка. Линукс сознательно использует свободную память под дисковый кэш, и это нормально: система показывает мало «свободной» памяти, но при необходимости мгновенно отдаёт её приложениям. Пугаться низкого значения free по этой причине не стоит — это признак эффективной работы, а не проблемы.

Настоящая утечка выглядит иначе: конкретный процесс со временем занимает всё больше памяти и не отдаёт её обратно, даже когда нагрузка спала. График потребления такого процесса ползёт вверх монотонно, час за часом, пока не упрётся в потолок. Кульминация — срабатывание OOM killer, механизма ядра, который при исчерпании памяти принудительно убивает самый прожорливый процесс, чтобы спасти систему. Если ваши сервисы периодически «умирают» сами по себе, особенно под нагрузкой или через равные промежутки времени, — это первый признак, что память течёт.

Первым делом: смотрим потребление памяти

Начните с общей картины. Команда обзора памяти показывает, сколько занято, сколько под кэшем и сколько ушло в своп:

free -h

Обращайте внимание не на строку «free», а на «available» — именно она показывает, сколько памяти реально доступно приложениям с учётом освобождаемого кэша. Если available близка к нулю, а своп заполняется — памяти действительно не хватает. Дальше найдите процессы, потребляющие больше всего, отсортировав их по памяти:

ps aux --sort=-%mem | head -10

В верхних строках вы увидите главных потребителей с их долей памяти. Запомните их и, что важнее, понаблюдайте за ними во времени: сама по себе высокая цифра ещё не улика, а вот процесс, чья доля стабильно растёт от замера к замеру без роста нагрузки, — почти наверняка тот, кто течёт. Один снимок показывает состояние, серия снимков показывает динамику, а именно динамика выдаёт утечку.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.

Арендовать VPS с запасом RAM

Своп и OOM killer: что происходит на пределе

Понимание этих двух механизмов помогает читать симптомы. Когда оперативной памяти не хватает, система начинает вытеснять её часть на диск — в своп. Своп спасает от мгновенного падения, но диск в тысячи раз медленнее памяти, поэтому активный свопинг превращает сервер в улитку: формально всё работает, а фактически каждая операция ждёт диск. Резкое, необъяснимое замедление всего сервера при живом процессоре — типичный признак ухода в своп.

Если и своп исчерпан, в дело вступает OOM killer. Он выбирает процесс, занимающий больше всего памяти, и убивает его, чтобы система не зависла целиком. Проблема в том, что под нож нередко попадает именно ваш важный сервис — база или бэкенд, — и сайт падает. Факт срабатывания OOM killer виден в системном журнале: там прямо написано, какой процесс и почему был убит. Это ценная улика, потому что она указывает и на жертву, и косвенно на масштаб проблемы.

Находим и подтверждаем виновника

Связав данные из наблюдения за процессами и записи OOM killer в журнале, вы обычно уже видите виновника. Но важно подтвердить именно утечку, а не разовый всплеск. Понаблюдайте за подозрительным процессом несколько часов: если его потребление растёт равномерно и не возвращается к исходному после спада нагрузки — это утечка. Если же память подскакивает на пике и опускается после — это нормальная работа под нагрузкой, и лечится она иначе, добавлением ресурсов, а не поиском бага.

Особое внимание — приложениям с рабочими процессами: обработчику PHP, серверам приложений на Python или Node. Каждый воркер со временем накапливает память, и если их слишком много или они живут слишком долго без перезапуска, суммарное потребление растёт незаметно, но неумолимо. Это одна из самых частых причин «утечки», которая на деле оказывается неудачной настройкой числа и времени жизни воркеров, а не ошибкой в коде.

Отдельно стоит разделять утечку в одном процессе и постепенное заполнение памяти множеством процессов. В первом случае график потребления одного процесса ползёт вверх, и виновник виден сразу. Во втором память тают из-за того, что процессов становится всё больше: приложение плодит соединения, зависшие обработчики не завершаются, фоновые задачи накапливаются. Внешне обе картины похожи — память кончается, — но лечатся они по-разному: одну исправляют в коде процесса, другую ограничением количества процессов и корректным их завершением. Поэтому, найдя, что память уходит, всегда уточняйте, растёт ли потребление одного процесса или увеличивается само их число, — этот вопрос экономит массу времени на неверном пути.

Частые источники утечки

Разберём типовые причины, чтобы сузить поиск. Первая — баг в коде приложения, которое не освобождает выделенную память: объекты копятся, ссылки не очищаются, потребление растёт. Это классическая утечка, и лечится она исправлением кода или обновлением проблемной библиотеки. Вторая — избыточное или бесконтрольное число воркеров у бэкенда: каждый занимает память, и десятки процессов суммарно съедают всю RAM.

Третья причина — раздутые кэши, которым не задан лимит: кэш приложения или базы растёт, пока не займёт всё. Здесь помогает явное ограничение размера кэша в настройках. Четвёртая — тяжёлые фоновые задачи, которые обрабатывают большие объёмы данных в памяти вместо потоковой обработки. Пятая — просто нехватка памяти под реальную нагрузку, ошибочно принимаемая за утечку. Знание этих пяти сценариев превращает расплывчатую «утечку» в конкретную гипотезу, которую можно проверить и устранить.

Временные меры и настоящее решение

Когда сервер уже задыхается, а разбираться некогда, помогают временные меры. Перезапуск текущего процесса-виновника мгновенно освобождает память и возвращает сервер к жизни — но это лишь отсрочка, память потечёт снова. Настроить автоматический периодический перезапуск воркеров или сервиса — более цивилизованный костыль, который держит потребление в узде, пока вы ищете корень. Для приложений с воркерами ограничение времени их жизни, после которого воркер перезапускается, часто решает проблему на практике.

Но настоящее решение зависит от причины. Если это баг в коде — его нужно исправить или обновить проблемный компонент, иначе перезапуски будут вечными. Если избыток воркеров или безлимитный кэш — привести настройки в соответствие с реальным объёмом памяти. А если утечки как таковой нет, а есть честная нехватка RAM под выросшую нагрузку, то единственное верное решение — добавить памяти. Бороться с нехваткой ресурсов бесконечными перезапусками — это лечить симптом, теряя стабильность и время.

Профилактика: чтобы память не подводила

Предотвратить проблему проще, чем ловить падения. Настройте мониторинг потребления памяти с оповещением при приближении к пределу — тогда вы среагируете заранее, а не по факту сработавшего OOM killer. Следите за динамикой, а не за мгновенными значениями: именно устойчивый рост выдаёт утечку до того, как она уронит сервис. Задавайте лимиты кэшам и разумное число воркеров, соответствующее объёму памяти сервера.

И держите запас RAM. Память — тот ресурс, где экономия оборачивается самыми неприятными сбоями: сервер без запаса уходит в своп и роняет сервисы на любом всплеске. Комфортный запас памяти делает сервер устойчивым к пикам и утечкам, давая время спокойно найти и устранить причину, а не тушить пожар. Если сервер регулярно упирается в потолок памяти даже после устранения явных утечек, это прямой сигнал, что проекту нужен тариф с большим объёмом RAM, и разумнее нарастить его, чем жить в режиме постоянных перезапусков.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.

Арендовать VPS с запасом RAM

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Частые вопросы

Свободной памяти почти нет — это утечка?

Не обязательно. Линукс использует свободную память под дисковый кэш; смотрите на показатель «available» и на динамику конкретных процессов, а не на «free».

Сервисы падают сами по себе — почему?

Вероятно, срабатывает OOM killer при исчерпании памяти: ядро убивает самый прожорливый процесс. Проверьте системный журнал — там указано, кто и почему был убит.

Как быстро вернуть сервер к жизни?

Перезапустить процесс-виновник — это освобождает память мгновенно. Но это временно: без устранения причины утечка вернётся.

Перезапускаю по кругу, а память течёт снова — что делать?

Найдите причину: баг в коде, избыток воркеров или безлимитный кэш. Если утечки нет, а есть нехватка RAM, добавьте памяти.

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.