Некотрое время назад, в компании, в которой я сейчас работаю, было принято решение оптимизировать работу серверных приложений. Изначально они использовались в связке nginx+apache+mod_fastcgi или mod_fcgid. Однако, хотелось избавиться от apache, учитывая что nginx сам умеет работать с FastCGI приложениями.
В процессе решения данной задачи мною был написан модуль-наследник от модуля FCGI::ProcManager. В него был добавлен функционал по контролю над количеством рабочих процессов в зависимости от нагрузки и ограничение времени жизни рабочих процессов определенным количеством запросов.
Последняя возможность уже есть реализованной в том числе и автором FCGI::ProcManager, но гибкого управления количеством процессов я не нашел. Поэтому я и решил добавить функциональности в вышеуказанный модуль.
Модуль FCGI::ProcManager::Dynamic реализует описанный расширенный функционал по управлению FastCGI процессами. Для мониторинга количества рабочих процессов главным процессом используется их взаимодействие через каналы сообщений в общей памяти.
Поддерживаются следующие расширенные параметры:
max_nproc — максимальное количество рабочих процессов;
min_nproc — минимальное количество рабочих процессов;
delta_proc — «шаг» при изменении общего количества процессов;
delta_time — время, прошедшее после последнего изменения количества процессов, по истечении которого при низкой нагрузке будет произведено снижение количества рабочих процессов. Такое снижение происходит только если в течении всего этого периода не было занято одновременно количество процессов превышающее новое количество процессов после его уменьшения. Это нужно для того, что-бы избежать преждевременного снижения количества процессов в высоконагруженном приложении при флуктуациях нагрузки.
max_requests — максимальное количество запросов для одного рабочего процесса. После его превышения рабочий процесс корректно завершается (см. ниже) и менеджер процессов создает вместо него новый рабочий процесс.
В связи с вводом ограничения на количество запросов для рабочего процесса хотелось-бы что-бы была возможность корректно завершить рабочий цикл FastCGI приложения, например, что-бы закрыть коннекты к БД. Для этого была создана дополнительная функция pm_loop. При ее использовании выход из рабочего цикла FastCGI приложения производиться обычным образом и выполняется весь код, расположенный за этим циклом. Пример использования есть в документации:
$proc_manager->pm_manage(); while ($proc_manager->pm_loop() && (my $cgi = CGI::Fast->new())) { $proc_manager->pm_pre_dispatch(); # ... handle the request here ... $proc_manager->pm_post_dispatch(); }; # ... здесь все завершающие действия ...
Данный модуль уже работает на продакшн серверах примерно две недели. Срок, конечно, небольшой, но учитывая достаточно большую нагрузку и отсутствие сбоев, можно сказать что пока он справляется.
Модуль доступен в CPAN. Замечания, советы и доработки приветствуются.
Хотелось-бы выразить благодарность читательу Kavkaz, т.к., в немалой степени, именно его статья сподвигла меня на создание данного модуля.
Автор: UncleAndy