Связка Nginx + Пускач + FastCGI на Perl
Perl — замечательный язык: краткий, ёмкий, широко распространённый, с большой коллекцией готовых модулей, однако в web-разработке он прижился хуже, чем, например, PHP. Скорее всего это связано с тем, что для Perl-разработки под web нет простых и надежных коробочных решений. CGI работает медленно, плохо держит нагрузку; Apache mod_perl или встроенный в Nginx Perl специфичны, лишают свободы выбора web-сервера; FastCGI с модулем FCGI::ProcManager
быстро, но ненадёжно, нужно прописывать настройки (пула процессов и подключения) в коде скрипта и конфигурации web-сервера; Spawn-fcgi малофункциональный, вся настройка выполняется через аргументы командной строки, умеет запускать только один скрипт.
Как вариант готового, простого, как топор, решения предлагается запускать FastCGI скрипты на Perl под управлением Пускача с web-сервером Nginx. Такая связка замечательна тем, что все компоненты соединены унифицированными интерфейсам и заменимы. В качестве web-сервера также подойдет Lighttpd или Apache; FastCGI-скрипт может выполняться в режиме CGI (особенность реализации Perl-модуля CGI::Fast
) и вообще не требовать особого обслуживания. Пускач также может быть заменен на тот же Spawn-fcgi.
Конфигурация Nginx
Конфигурация Nginx вполне стандартная, настраивается один раз, больше редактировать её не придётся. Важные параметры: fastcgi_pass
, указывающая адрес сетевого или UNIX-сокета, который будет слушать Пускач, и переменная SCRIPT_FILENAME
, содержащая путь к скрипту.
- events { }
- http
- {
- server
- {
- listen host:port;
- access_log /usr/home/site_user/logs/access.log;
- error_log /usr/home/site_user/logs/errors.log;
- ssi on;
- root /usr/home/site_user/www;
- index index.html index.html index.fcgi;
- location ~ \.(fpl|fcgi)$
- {
- fastcgi_pass unix:/usr/home/site_user/tmp/puskach.sock;
- }
- fastcgi_index index.fcgi;
- fastcgi_param SCRIPT_FILENAME /usr/home/site_user/www$fastcgi_script_name;
- fastcgi_param DOCUMENT_ROOT /usr/home/site_user/www;
- # Стандартные параметры интерфейса FastCGI, поставляются с Nginx
- include "/usr/local/nginx/conf/fastcgi_params";
- }
- }
Конфигурация Пускача
Пускач является промежуточным звеном между web-сервером и FastCGI-скриптами. Web-сервер видит его как одно FastCGI-приложение, на которое нужно отправлять все запросы. Пускач уже занимается их коммутацией, определяя целевой скрипт по переменной SCRIPT_FILENAME
. Кроме того он управляет пулами рабочих процессов: запускает новые копии для параллельной обработки запросов, останавливает простаивающие, следит за соблюдением таймаутов.
Чтобы не регистрировать каждый скрипт в конфигурационном файле задается описание default_fcgi
, оно будет применяться для скриптов, которые не описаны явно. Для конфигурации по умолчанию рекомендуется задавать более жесткие ограничения, а для редких скриптов, которые в них не укладываются, переопределять в блоке fcgi
. Все параметры конфигурационного файла Пускача и аргументы командной строки описаны в документации.
- req_pool_size 256
- default_fcgi
- {
- unix_socket_prefix "/usr/home/site_user/tmp/f"
- io_timeout 10000
- sleep_timeout 30000
- request_processing_timeout 15000
- max_processes 5
- requests_per_process 1000
- }
- fcgi
- {
- path "/usr/home/site_user/www/upload_file.fcgi"
- unix_socket_prefix "/usr/home/site_user/tmp/f"
- io_timeout 30000
- sleep_timeout 30000
- request_processing_timeout 3600000
- max_processes 25
- requests_per_process 1000
- }
Пример скрипта на Perl
Для написания FastCGI-скриптов рекомендуется использовать модуль CGI::Fast
— это небольшая, но функциональная надстройка над стандартными модулями CGI
и FCGI
; такой скрипт будет поддерживать оба интерфейса, и CGI, и FastCGI. При поступлении нового запроса от web-сервера CGI::Fast->new
вернёт стандартный объект CGI
, с помощью которого можно получить доступ ко всем данным запроса.
- #!/usr/bin/perl
- use strict;
- use CGI::Fast;
- # Инициализация: загрузка ресурсов,
- # установка подключения к БД
- my $counter = 0;
- while (my $q = CGI::Fast->new) {
- $counter++;
- print "Content-Type: text/html\n\n";
- print "Я обработал $counter запросов!\n";
- my %params = $q->Vars;
- while (my ($k, $v) = each %params) {
- print "$k = $v\n";
- }
- }
- # Закрытие ресурсов / подключений