Перейти к основному содержанию

Apache — постоянная перезагрузка

Apache

Пойман неприятный баг на web-сервере Apache. Симптомы простые, все сайты перестают отвечать: белый экран. Помогает перезагрузка Apache.

На сервере:

  • Ubuntu 22
  • Apache 2
  • PHP 7.2
  • PHP-FPM
  • php_prefork

В бою такой сервер использовать невозможно. Три часа работы, потом всё висит. Можно поставить проверку и автоматически перезагружать Apache, но это костыль.

В логах можно увидеть сообщение о том, что веб-сервер перезагружается:

caught SIGWINCH, shutting down gracefully

apache

Перезагрузку наблюдает модуль php_prefork. Этот модуль служит для изоляции процессов и ускорения работы веб-сервера с помощью предварительной загрузки тяжёлых PHP-приложений. При большой нагрузке на сервер данный модуль может сам перезагружать Apache. Если ваша проблема состоит только в том, что веб-сервер периодически перезагружается, то стоит обратить внимание на настройку конфигурации php_prefork, выделив под него дополнительные ресурсы.

Однако, проблему зависания сервера данный модуль не решает. В логах у нас есть такое:

child 5023 said into stderr: "(5023): Error Cannot kill process 2349: Operation not permitted!"

И это баг, товарищи. Вроде как пишут, что баг исправлен в версиях PHP 7.4.16 и 8.0.3. Так что проблему можно попытаться устранить обновлением PHP. Но это не всегда возможно.

Вероятно, проблема вызвана кривое реализацией PHP-FPM в связке с OPCache. Модуль OPCache занимается кэшированием данных. На сервере все пулы для определенной версии PHP совместно используют один и тот же главный процесс (принадлежащий root) и используют один и тот же пул памяти, выделенный для OPCache. Однако сами пулы принадлежат учетной записи веб-сервера (www-data).

Opcache периодически перезапускает пулы. Иногда ему требуется кильнуть всё, он дёргает функцию kill_all_lockers(). И прав ему не хватает. Что делать?

Вариант 0

Обновить PHP. Не всегда возможно.

Вариант 1

Отключить модуль OPCache. Ошибка устранена, но кеширования у вас больше нет. Не всегда можно на это пойти.

Вариант 2

Перейти на другой PHP handler — FastCGI. И это тоже не всегда возможно.

Вариант 3

Запретить вызов функции kill_all_lockers. В php.ini в раздел disable_functions добавляем kill_all_lockers. Способ хороший, но почему-то не всегда срабатывает, непонятно почему.

Вариант 4

Перезапуск PHP-FPM каждые несколько минут. Так себе решение, может подойти только для временного решения проблемы.

Вариант 5

Самый нормальный вариант после обновление PHP. Дело в том, что OPCache не всегда вызывает функцию kill_all_lockers(). Он сначала убивает пулы по очереди, а ели не успевает по таймауту, то грохает сразу всё. Этот самый таймаут установлен в параметре opcache.force_restart_timeout — 180 секунд. Если мы увеличим его, скажем, до бесконечности, то функция kill_all_lockers не будет вызываться.

opcache.force_restart_timeout = 0

Настройки OPCache могут быть не только в файле php.ini, но и в подключаемых отдельных файлах конфигураций.

Теги

 

Похожие материалы

CTF — JWT - Unsecure File Signature

Всем привет, у меня полночь, так что самое время решить задачку на информационную безопасность web-серверов. Сегодня задачка с портала root-me.org, называется "JWT - Unsecure File Signature". За решение задачки дают 25 баллов, ближе к среднему уровню.

Теги