Я использую веб-сервер Apache и хотел бы немного улучшить то, как обрабатывается ситуация с OOM.
Я знаю оценки OOM и уже внес некоторые изменения в этот вопрос, поэтому, когда происходит что-то плохое, Linux убивает правильные процессы. Но этого недостаточно.
Проблема в том, что иногда, когда происходит OOM, сервер перегружается, а затем вылетает и требует перезапуска. Я бы хотел справиться с этим без полного перезапуска сервера. Поэтому мне нужно каким-то образом «зацепить» скрипт на вызов OOM killer, который убьет все процессы apache (и его CGI), освободив таким образом память и снова запустив его (Apache).
Я знаю, что это сработает, потому что если произойдет OOM, и я достаточно быстр, чтобы войти на сервер и вручную убить Apache, тогда все в порядке.
К вашему сведению, сейчас у меня работает почти сотня этих веб-серверов, поэтому я ищу полностью автоматическое решение.
Одним из возможных решений, конечно же, было бы использование некоторого сторожевого таймера, который бы анализировал системный журнал и обнаруживал OOM таким образом - у меня уже есть что-то подобное, которое уведомляет об убийствах OOM по электронной почте. Этот подход может решить некоторые ситуации, но если OOM действительно плохой, сервер слишком перегружен, и мой скрипт даже не запускается (его запускает cron). Его можно улучшить, используя inotify для просмотра системного журнала или напрямую подключив системный журнал (например, с помощью FIFO) к сценарию.
Но все же мне интересно - а нет ли способа «зацепить» скрипт напрямую на OOM killer? Поэтому я бы поместил что-то подобное в какой-нибудь файл / etc / ..:
oom_action="sh /path/to/my/script.sh kill"
Или это просто невозможно?
Я использую Centos 6, Apache 2.2 и PHP как FastCGI.
Почему бы вам просто не отслеживать процессы apache и не устанавливать их oom_adj
значение 15, чтобы быть уверенным, что они первыми завершат работу при OOM? Вот некоторые инструкции по этому параметру.
В зависимости от вашей конфигурации вы можете либо изменить стартовые скрипты apache, либо настроить для этого простую задачу cron.
Вы также можете периодически наблюдать за выводом команды dmesg | grep -i oom
. Если будут какие-то строки, убийца OOM убил кого-то с момента последней загрузки сервера. Затем вы можете очистить буфер с помощью dmesg --clear
Поскольку я не нашел лучшего решения, я реализовал сторожевой таймер для чтения сообщений системного журнала ядра (через fifo):
/etc/rsyslog.d:
(...)
kern.err |/path/to/fifo
и ищем в них активность OOM-killer:
while read /path/to/fifo; do (..)
и когда OOM-убийца массово появляется (мне действительно нужно проверять только аварийную ситуацию), я убиваю (а затем запускаю) Apache.
Я знаю, что в дикой природе существуют ужасные PHP-приложения, их много, но их нет что-то вы могли бы делать на стороне Apache / FastCGI / PHP? Постоянный OOM-запуск Apache - это не то, с чем вы должны сталкиваться очень часто.
Попробуйте уменьшить максимальное количество процессов Apache и обработчиков FastCGI и посмотрите, не слишком ли велики ваши текущие настройки php.ini для максимального объема памяти на скрипт.
Кроме того, вполне возможно использовать ulimit
с Apache и ограничить количество памяти, которую может использовать процесс. Это может помочь вам до того, как сервер чуть не погибнет.
OOM - это самое последнее средство, и все, что может привести к нему, должно быть проверено.
Я думаю, лучше вам поместить свой процесс в подмножество памяти cgroup и использовать release_agent
для вызова внешнего скрипта при нехватке памяти
notify_on_release
contains a Boolean value, 1 or 0, that either enables or disables the execution of the release agent. If the notify_on_release is enabled, the kernel executes the contents of the release_agent file when a cgroup no longer contains any tasks (that is, the cgroup's tasks file contained some PIDs and those PIDs were removed, leaving the file empty). A path to the empty cgroup is provided as an argument to the release agent.
release_agent (present in the root cgroup only)
contains a command to be executed when a “notify on release” is triggered. Once a cgroup is emptied of all processes, and the notify_on_release flag is enabled, the kernel runs the command in the release_agent file and supplies it with a relative path (relative to the root cgroup) to the emptied cgroup as an argument. The release agent can be used, for example, to automatically remove empty cgroups
Используя cgroup, вы можете контролировать, сколько ресурсов вы можете использовать, и не перегружать свой сервер
Using cgroup you can control the server resources