Использование mod_perl( http://webscript.ru///perl.apache.org/ ) Mod_perl это С модуль Apache, реализующий Perl интерпретатор + набор Perl модулей, предоставляющих следующие интересные возможности:
Как это выглядит типичное использование mod_perl.Мы скомпилировали Apache с поддержкой mod_perl, у нас есть script.pl:#!/usr/bin/perl use strict; use CGI qw(:cgi); print header (), Hi, people!;и мы хотим, чтобы скрипт выполнялся интерпретатором mod_perl и кэшировался. Для этого мы изменяем http2d.conf: # Это мы закомментируем #### ScriptAliasПерезапустим Apache и убедимся, что всё работает. Конфигурирование mod_perl.Разберёмся с тем, что мы написали в http2d.conf.Mod_perl определяет Apache handler ( http://webscript.ru///http2d.apache.org/docs/handler.html ) с именем <Locationозначает, что запросы к Mod_perl определяет также несколько директив: PerlModule Some::Module Other::Module директива загружает указаные Perl модули. Скрипты, выполняемые под mod_perl, могут их использовать, не включая функцией use(). С точки зрения скрипта, использование PerlModule отличается от use() тем, что в скрипт не импортируются имена модуля. Модуль, загруженый PerlModule, может также использоваться как обработчик Perl*Handler Some::Module Apache обрабатывает запрос в несколько фаз В нашем http2d.conf мы указали Apache::Registry.pm как обработчик фазы Response. Когда мы запрашиваем script.pl у сервера, Apache::Registry.pm берёт откомпилированую версию скрипта из своего кэша и запускает. Apache::Registry.pm отслеживает изменения script.pl на диске и при необходимости перекомпилирует его. Однако изменения в модулях, включаемых script.pl не отслеживаются это долго. Так что если вы изменили Вы, разумеется, не обязаны использовать Apache::Registry.pm, как делают большинство разработчиков. Напишите ради интереса свой обработчик фазы Response: package MyOwnResponseGenerator; use strict; use Apache::Constants qw(:common); sub handler { printMyOwnResponseGenerator.pm положим там, где мod_perl сможет его найти (perl -e print join "\n"e;, @INC). Отредактируем http2d.conf: PerlModule MyOwnResponseGenerator <Location /somelocation> SetHandlerПерезапустим Apache, наберём Подробно о конфигурировании mod_perl: //perl.apache.org/docs/1.0/guide/config.html Особенности работы скриптов под Apache::RegistryДве главные особенности работы кэшируемых скриптов, способные испортить много нервов разработчику, если он о них не знает:1. Глобальные переменные скрипта сохраняют свои значения между запросами: #!/usr/bin/perl use strict; use CGI qw(:cgi); use vars qw($i); print header (), ++$i;запросим этот скрипт несколько раз подряд и получим: 1 2 3 4 5 … без Apache::Registry картина была бы такой, разумеется: 1 1 1 1 1 … Не удивляйтесь, если открыв новое окошко IE и повторив процедуру вы снова получите: 1 2 3 4 5 … вместо 6 7 8 9 10 … . Как правило на сервере работают несколько дочерних процессов http2d, каждый из них имеет свою копию вашего скрипта и соответственно свою копию $i. Команда http2d -x запустит сервер с одним дочерним процессом удобно для отладки. Ниже следует пример того, как писать НЕ НАДО: #!/usr/bin/perl use CGI qw(:cgi); use MySecurity qw(:check_user); use vars qw($allow); $allow = 1 if check_user (param(login), param(password)); print header (); print (($allow) ? Some secret data : Cool hacker? Go away!);достаточно одному пользователю указать верные 2. Определённые в вашем скрипте функции становятся вложенными во внешнюю функцию. Вот во что Apache::Registry превращает script1.pl: package Apache::ROOT::perl::script1_2epl; use Apache qw(exit); sub handler { BEGIN { $^W = 1; }; $^W = 1; ### Original begin of script1.pl use strict; use CGI qw(:cgi); my $var = a; sub show_var { "Var was $var and now is " . ++$var } print header(), show_var (); ### Original end of script1.pl }наша show_var() оказалась определённой внутри handler(), т.е. вложеной. Чем нам это грозит? show_var() не может теперь корректно работать с внешними my() переменными, в нашем случае с my $var. Запустив скрипт несколько раз получим: Var was a and now is b, Var was b and now is c, Var was c and now is d и т.д. Функция show_var() видит тот экземпляр my $var, который она видела при первом выполнении handler(). Подробно эта проблема описана здесь: Scoped Variable in NestedSubroutines. Нас же интересуют её возможные решения: 1. определять функции не в скрипте, а в модуле. Код ваших модулей не обарачивается ни в какие функции, и данная проблема не возникнет. 2. или просто не обращатся из функций к внешним my() переменным. Предположим, вы пересадили свои скрипты на mod_perl, они некорректно работают из кэша Подробно о работе скриптов под mod_perl: //perl.apache.org/docs/1.0/guide/porting.html ПроизводительностьОценим ради интереса выигрыш в производительности, который даёт mod_perl:1. time 2. time 3. time На моём 300Celeron результаты следующие: 774, 1039, 768 миллисекунд соответственно. Т.е. под mod_perl скрипт выполнился за 6мс (774768), без mod_perl за 71мс (1039768). В 12 раз возросла прозводительность, однако! Для реальных скриптов эта цифра будет меньше, конечно. Пора закругляться
|