Мой веб-сервер VPS, работающий на CentOS 5.4 (ядро Linux 2.6.16.33-xenU) нерегулярно (например, раз в месяц или несколько недель), перестает отвечать из-за запуска oom-killer. Мониторинг сервера показывает, что он не обычно не хватает памяти, просто так часто.
Я прочитал несколько блогов, которые указывают на эту страницу, где обсуждается настройка ядра для лучшего управления перегрузками с использованием следующих параметров sysctl:
vm.overcommit_memory = 2
vm.overcommit_ratio = 80
Мое понимание этого (которое может быть неправильным, но я не могу найти каноническое определение для пояснения) состоит в том, что это предотвращает чрезмерное выделение памяти ядром сверх уровня подкачки + 80% физической памяти.
Тем не менее, я также прочитал некоторые другие источники , в которых говорится, что эти настройки не очень хорошая идея - хотя критики этого подхода, похоже, говорят: «Не делайте ничего, чтобы сломать вашу систему, вместо того, чтобы пытаться сделать это», предполагая, что Причинность всегда известна.
Итак, мой вопрос: каковы плюсы и минусы этого подхода в контексте веб-сервера Apache2, на котором размещено около 10 сайтов с низким трафиком? В моем конкретном случае веб-сервер имеет 512 МБ ОЗУ и 1024 МБ подкачки. Это кажется достаточным для подавляющего большинства времени.
/proc/<PID>/oom_score_adj
для этой цели. Например, если вы установите для oom_score_adj значение -1000 для sshd, oom killer никогда не нацелится на sshd, когда захочет что-то убить. Полное прекращение работы oom killer не является хорошей идеей, так как тогда ваши программы не смогут распределить память, и они все равно умрут.Раздел 9.6 «Overcommit and OOM» в документе, который упоминает @dunxd, особенно наглядно показывает опасность разрешения overcommit. Тем не менее,
80
мне это тоже показалось интересным, поэтому я провел несколько тестов.Я обнаружил, что это
overcommit_ratio
влияет на общую оперативную память, доступную для всех процессов. Корневые процессы, похоже, не обрабатываются иначе, чем обычные пользовательские процессы.Установка отношения к
100
или меньше должна обеспечить классическую семантику, где возвращаемые значенияmalloc/sbrk
надежны. Установка коэффициентов ниже, чем это100
может быть способом зарезервировать больше оперативной памяти для непроцессных операций, таких как кэширование и так далее.Итак, на моем компьютере с 24 ГБ ОЗУ, с отключенной подкачкой, 9 ГБ в использовании, с
top
показомВот некоторые
overcommit_ratio
настройки и объем оперативной памяти, которую могла бы получить моя программа-потребитель (касаясь каждой страницы) - в каждом случае программа выходила чисто послеmalloc
сбоя.Запуск нескольких одновременно, даже с некоторыми из них как пользователем root, не изменил общее количество, которое они потребляли вместе. Интересно, что он не мог потреблять последние 3+ ГиБ или около того;
free
не опускалась значительно ниже того , что показано здесь:Эксперименты были беспорядочными - все, что использует malloc в тот момент, когда используется вся ОЗУ, может привести к сбою, так как многие программисты ужасно относятся к проверке сбоев malloc в C, некоторые популярные библиотеки коллекций игнорируют его полностью, а C ++ и различные другие языки даже хуже.
Большинство ранних реализаций мнимой ОЗУ, которые я видел, предназначались для обработки очень специфического случая, когда один какой-то большой процесс - скажем, 51% + доступной памяти - был необходим
fork()
дляexec()
какой-то вспомогательной программы, обычно намного, намного меньшего размера. Операционные системы с семантикой копирования при записи позволили быfork()
, но с условием, что если разветвленный процесс действительно попытается изменить слишком много страниц памяти (каждая из которых затем должна будет создаваться как новая страница, независимая от первоначального огромного процесса) это закончится тем, что его убьют. Родительский процесс был только в опасности, если выделил больше памяти, и мог справиться с исчерпанием, в некоторых случаях, просто подождав немного, пока какой-то другой процесс умрет, а затем продолжил. Дочерний процесс обычно просто заменяет себя (обычно меньшей) программой черезexec()
и был тогда свободен от оговорки.Концепция чрезмерной
fork()
загрузки в Linux - это экстремальный подход, позволяющий как происходить, так и обеспечивать массовое перераспределение отдельных процессов. Случаи смерти, вызванные OOM-убийцами, происходят асинхронно, даже с программами, которые действительно ответственно обрабатывают распределение памяти. Лично я ненавижу общесистемную перегрузку в целом и оком-убийцу в частности - она поощряет дьявольский подход к управлению памятью, который заражает библиотеки и через них каждое приложение, которое их использует.Я бы предложил установить соотношение равным 100, а также иметь раздел подкачки, который, как правило, в конечном итоге будет использоваться только огромными процессами, которые часто используют лишь небольшую часть той части себя, которая вставляется в своп, и, таким образом, защитить подавляющее большинство процессов от неправильной работы убийцы OOM. Это должно сохранить ваш веб-сервер в безопасности от случайной смерти, и если он был написан для
malloc
ответственного обращения , даже в безопасности от самоубийства (но не делайте ставку на последний).Это означает, что я использую это в
/etc/sysctl.d/10-no-overcommit.conf
источник