Фальстарт

Связка 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, содержащая путь к скрипту.

  1. events { }
  2. http
  3. {
  4. server
  5. {
  6. listen host:port;
  7. access_log /usr/home/site_user/logs/access.log;
  8. error_log /usr/home/site_user/logs/errors.log;
  9. ssi on;
  10. root /usr/home/site_user/www;
  11. index index.html index.html index.fcgi;
  12. location ~ \.(fpl|fcgi)$
  13. {
  14. fastcgi_pass unix:/usr/home/site_user/tmp/puskach.sock;
  15. }
  16. fastcgi_index index.fcgi;
  17. fastcgi_param SCRIPT_FILENAME /usr/home/site_user/www$fastcgi_script_name;
  18. fastcgi_param DOCUMENT_ROOT /usr/home/site_user/www;
  19. # Стандартные параметры интерфейса FastCGI, поставляются с Nginx
  20. include "/usr/local/nginx/conf/fastcgi_params";
  21. }
  22. }

Конфигурация Пускача

Пускач является промежуточным звеном между web-сервером и FastCGI-скриптами. Web-сервер видит его как одно FastCGI-приложение, на которое нужно отправлять все запросы. Пускач уже занимается их коммутацией, определяя целевой скрипт по переменной SCRIPT_FILENAME. Кроме того он управляет пулами рабочих процессов: запускает новые копии для параллельной обработки запросов, останавливает простаивающие, следит за соблюдением таймаутов.

Чтобы не регистрировать каждый скрипт в конфигурационном файле задается описание default_fcgi, оно будет применяться для скриптов, которые не описаны явно. Для конфигурации по умолчанию рекомендуется задавать более жесткие ограничения, а для редких скриптов, которые в них не укладываются, переопределять в блоке fcgi. Все параметры конфигурационного файла Пускача и аргументы командной строки описаны в документации.

  1. req_pool_size 256
  2. default_fcgi
  3. {
  4. unix_socket_prefix "/usr/home/site_user/tmp/f"
  5. io_timeout 10000
  6. sleep_timeout 30000
  7. request_processing_timeout 15000
  8. max_processes 5
  9. requests_per_process 1000
  10. }
  11. fcgi
  12. {
  13. path "/usr/home/site_user/www/upload_file.fcgi"
  14. unix_socket_prefix "/usr/home/site_user/tmp/f"
  15. io_timeout 30000
  16. sleep_timeout 30000
  17. request_processing_timeout 3600000
  18. max_processes 25
  19. requests_per_process 1000
  20. }

Пример скрипта на Perl

Для написания FastCGI-скриптов рекомендуется использовать модуль CGI::Fast — это небольшая, но функциональная надстройка над стандартными модулями CGI и FCGI; такой скрипт будет поддерживать оба интерфейса, и CGI, и FastCGI. При поступлении нового запроса от web-сервера CGI::Fast->new вернёт стандартный объект CGI, с помощью которого можно получить доступ ко всем данным запроса.

  1. #!/usr/bin/perl
  2. use strict;
  3. use CGI::Fast;
  4. # Инициализация: загрузка ресурсов,
  5. # установка подключения к БД
  6. my $counter = 0;
  7. while (my $q = CGI::Fast->new) {
  8. $counter++;
  9. print "Content-Type: text/html\n\n";
  10. print "Я обработал $counter запросов!\n";
  11. my %params = $q->Vars;
  12. while (my ($k, $v) = each %params) {
  13. print "$k = $v\n";
  14. }
  15. }
  16. # Закрытие ресурсов / подключений