Что делать, если Python-сервер падает из-за утечки памяти?

Привет, Хабр! Это наша экспериментальная рубрика, в которой мы даем новичкам быстрые ответы на четкие вопросы. Писать статью будет излишним, а некоторую пользу до аудитории донести, возможно, получится.
Итак, допустим, агент спустя время начинает расти по памяти и в итоге все падает. Где копать и как временно ограничить ущерб, пока ищете утечку?
Первое, что нужно сделать — измерить и локализовать. tracemalloc показывает, какие строки выделяют больше всего памяти, gc — количество объектов.
Часто проблема в неограниченных кэшах, списках или в C-расширениях. Сначала стоит включить tracemalloc, дать процессу поработать и снять снапшот:
import tracemalloc tracemalloc.start() # после нагрузки snapshot = tracemalloc.take_snapshot() top = snapshot.statistics('lineno')[:10] for stat in top: print(stat)
Параллельно делайте gc.collect() и логируйте число объектов len(gc.get_objects()), чтобы увидеть рост. На время расследования применяйте эксплуатационные меры: для WSGI-сервисов используйте Gunicorn с --max-requests и --max-requests-jitter, чтобы процессы периодически перезапускались и не накапливали мусор. А в контейнерах ставьте cgroup-пределы (--memory) и настраивайте restart-политику, чтобы платформа автоматически перезапускала упавшие поды.
Пример запуска Gunicorn:
gunicorn myapp:app --workers 4 --max-requests 1000 --max-requests-jitter 50
Если утечка в C-расширении или сторонней библиотеке, то временно автоматический перезапуск и мониторинг позволяют сохранить сервис работоспособным, пока вы находите корень проблемы и исправляете код.
Если хотите освоить инструменты Python, то в Академии Selectel у нас есть отдельная подборка статей. Там мы рассказываем, как настраивать инструменты, работать с базами данных, создавать программы с интерфейсом и использовать Python для парсинга.
































