Когда на вашем сервере/процессе заканчивается память, у Linux есть два способа справиться с этим: первый - это сбой ОС (Linux), и вся система падает, а второй - убить процесс (приложение), из-за которого в системе закончилась память. Лучшая ставка для второго варианта - убить процесс и спасти ОС от краха.
Out-Of-Memory Killer (OOM Killer) - это процесс, который отвечает за завершение приложения, чтобы спасти ядро от краха, поскольку он убивает только приложение и спасает всю ОС от краха.
Одной из основных задач операционной системы Linux является выделение памяти процессу, когда он запрашивает выделение памяти. В большинстве случаев процесс/приложение запрашивает память у ОС, но не использует всю запрошенную память.
Если операционная система выделит память всем процессам, которые запрашивают память, но не планируют ее использовать, то вскоре память закончится - и система аварийно завершит работу.
Для того чтобы справиться с этим сценарием, в операционной системе есть функция, которая позволяет ОС выделять память процессу без фактического выделения памяти. Выделение памяти происходит только тогда, когда процесс действительно планирует использовать эту память. Иногда у ОС может не быть свободной памяти, но она будет выделять память процессу, а когда процесс планирует использовать память, ОС выделит выделенную память, если она будет доступна. Недостатком этой функции является то, что иногда ОС фиксирует память, а в момент выделения у нее не будет доступной памяти для выделения, и система аварийно завершит работу.
OOM играет важную роль в этом сценарии и убивает процесс(ы), чтобы спасти ядро.
Настройка OOM killer для одного процесса
Делайте это в тех случаях, когда вы не хотите менять настройки на уровне программы, а хотите отключить OOM killer только для одного процесса. Это полезно, когда вы работаете на общей машине/сервере.
OOM killer использует метрику уровня процесса под названием oom_score_adj, чтобы решить, убивать ли процесс или нет. Этот файл находится в /proc/$pid/oom_score_adj. oom_score_adj может изменяться от -1000 до 1000, по умолчанию он равен 0.
Вы можете добавить большой отрицательный балл в этот файл, чтобы уменьшить вероятность того, что ваш процесс будет выбран и завершен OOM killer. Если вы установите значение -1000, процесс может использовать 100% памяти и при этом избежать завершения OOM killer.
С другой стороны, если присвоить ему значение 1000, ядро Linux будет продолжать убивать процесс, даже если он использует минимальное количество памяти.
Выполните эту команду
1 | sudo echo -1000 > /proc/<PID>/oom_score_adj |
Нам нужны права root/sudo, так как Linux не позволяет обычным пользователям уменьшать показатель OOM. Вы можете увеличить показатель OOM как обычный пользователь без каких-либо специальных прав.
Настройка OOM killer на уровне операционной системы
Это отключает oom killer на уровне ОС и позволяет избежать выполнения ранее упомянутых шагов для каждого процесса. Делайте это, если вы находитесь на машине/сервере, который вы используете специально для вашего приложения, например, на облачном vm для конкретной работы.
По умолчанию Linux имеет несколько поврежденную концепцию управления памятью: он позволяет вам выделять больше памяти, чем есть в системе, а затем произвольно стреляет процессу в голову, когда у него возникают проблемы. (Фактическая семантика того, что именно убивается, более сложна - Google "Linux OOM Killer" для множества деталей и споров о том, хорошо это или плохо).
Чтобы отключить это поведение:
Отключите OOM Killer (поставьте vm.oom-kill = 0 в /etc/sysctl.conf).
1 2 | echo "vm.oom-kill = 0" > /etc/sysctl.conf sysctl -p |
Отключите перераспределение памяти (Поставьте vm.overcommit_memory = 2 в /etc/sysctl.conf)
1 2 | echo "vm.overcommit_memory = 2" > /etc/sysctl.conf sysctl - p |
Обратите внимание, что это значение:
- 0 - оценивать, достаточно ли у нас оперативной памяти
- 1 - Всегда говорить "да"
- 2 - говорить "нет", если у нас не достаточно памяти
Эти настройки заставят Linux вести себя традиционным образом (если процесс запрашивает больше памяти, чем доступно, malloc() не сработает, и процесс, запрашивающий память, должен справиться с этой ошибкой).
Перезагрузите машину, чтобы заставить ее перезагрузить /etc/sysctl.conf, или используйте файловую систему proc для включения сразу, без перезагрузки:
1 | echo 2 > /proc/sys/vm/overcommit_memory |