Pull to refresh

Ограничение времени исполнения PHP скриптов из-под Apache

Предыстория: с некоторых пор на сайте Х стали накапливаться процессы apache в состоянии отправки ответа, в логах никакого криминала не было обнаружено. Доблестные админы пытались спасти ситуацию тюнингом конфигов apache\nginx\mysql и всего что было связано с сайтом Х. Никаких результатов это не дало. Был реализован план Б, в забиксе был добавлен скрипт рестарта apache при накоплении более 100 процессов apache.

Такая ситуация меня очень заинтересовала, так как все это время я верил в миф про настройки всевозможных таймаутов, и думал что проблема плевая и решить её возможно с помощью правильно приготовленного конфига. Небольшие исследование привели к факту полного отсутствия возможностей как в PHP так и в Apache ограничения времени обработки самого запроса, да у Apache есть таймауты на операции ввода\вывода но они срабатывают до и после самой обработки запроса. Пресловутая настройка max_execution_time весьма синтетическая, так как контроль этого параметра происходит при обработки оп кодов PHP, как и вариант с register_tick_function. Тоесть если в PHP скрипте есть зависшая операция ввода\вывода (mysql сервер во время обработки запроса сбойнул и не прислал ответа, да бывает и такое), команда sleep, и прочие неизвестные полтергейст которых полно в больших проектах писаные несколькими поколениями разработчиков, то процесс apache будет висеть в памяти бесконечно долго и не будет обрабатывать входящие запросы.

По результатам исследования, вырисовывалось два варианта, первый: перевести проект на php-fpm у которого есть возможность контролировать время исполнения PHP скрипта, и второй: написать свой модуль для php только под линукс системы, который будет использовать стандартную возможность завести таймер и выполнится посредством сигнала прервав тем самым работу скрипта, сделать запись в лог stacktrace, отдать адекватный ответ и завершить текущий процесс ( так как PHP интерпретатор совершено не готов к такому развитию событий, либо не удалось его правильно приготовить ). Причина почему при реализации этого варианта приходится завершать процесс — при использовании PHP функции exit внутри сигнального обработчика приводит к падению процесса.

Плюсы и минусы:

Первый вариант:

плюсы — решение из коробки не страшно пускать в продакшен

минусы — перестройка проекта ( переделка .htaccess'ов под nginx либо прикручивание к apache fastcgi модуля),
не возможность узнать где произошло зависание

Второй вариант:

плюсы — информация о точном месте в коде где происходит зависание, полная управляемость включением такого таймера,
никаких глобальных переделок в проекте, всего один include и один вызов функции в корневом index.php

минусы — модуль хоть и примитивный ( пару функций ), может себя крайне интересно и непредсказуемо повести в продакшене

модуль на github'e

Итог: на одном из бекенд серверов будет использован второй вариант.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.