Гостевая
Форум
Разделы
Главная страница
Js скрипты
Php скрипты
Html шаблоны
Книги по Web дизайну
Статьи


Главная страница статей --> Хитрости при программировании php, заметки по базам данных

Использование mod_perl

Источник: realcoding.net

Mod_perl — это С модуль Apache, реализующий Perl интерпретатор + набор Perl модулей, предоставляющих следующие интересные возможности:

1. Кэширование откомпилированых cgi скриптов (Apache::Registry.pm)
2. Perl интерфейс к C API Apache

Большинство разработчиков используют mod_perl чтобы увеличить производительность своих скриптов — Apache не запускает новый процесс при каждом запросе к script.pl, т.к. имеет теперь свой Perl интерпретатор, и не компилирует script.pl при каждом запросе, т.к. Apache::Registry.pm хранит ваши откомпилированые скрипты в кэше. Perl интерфейс к C API Apache используется разработчиками не так часто.


Как это выглядит — типичное использование mod_perl.
Мы скомпилировали Apache с поддержкой mod_perl, у нас есть script.pl:

#!/usr/bin/perl
use strict;
use
CGI qw(:cgi);
print
header (), ’Hi, people!;

и мы хотим, чтобы скрипт выполнялся интерпретатором mod_perl и кэшировался. Для этого мы изменяем httpd.conf:

# Это мы закомментируем
#### ScriptAlias /cgi-bin/ «/home/my-project.ru/cgi-bin/»
# А это добавим
PerlModule Apache::Registry
<Location /cgi-bin>SetHandler perl-script PerlHandler Apache::Registry
Options ExecCGI
allow from all
</Location>

Перезапустим Apache и убедимся, что всё работает.

Конфигурирование mod_perl.


Разберёмся с тем, что мы написали в httpd.conf.
Mod_perl определяет Apache handler с именем "perl-script". Следующая запись:

<Location /cgi-bin>SetHandler perl-script</Location>

означает, что запросы к /cgi-bin будет обрабатывать код mod_perl.
Mod_perl определяет также несколько директив:

PerlModule Some::Module Other::Module

— директива загружает указаные Perl модули. Скрипты, выполняемые под mod_perl, могут их использовать, не включая функцией use(). С точки зрения скрипта, использование PerlModule отличается от use() тем, что в скрипт не импортируются имена модуля. Модуль, загруженый PerlModule, может также использоваться как обработчик какой-либо фазы обработки запроса, см. ниже.

Perl*Handler Some::Module

— Apache обрабатывает запрос в несколько фаз — (Post-Read-Request, URI Translation, Header Parsing, Access Control, Authentication, Authorization, MIME type checking, FixUp, Response(!), Logging, Cleanup). Директива Perl*Handler регестрирует модуль-обработчик для какой-либо из этих фаз. Наиболее часто используется директива PerlHandler, устанавливающая обработчик для фазы Response. Остальные Perl*Handler директивы (PerlPostReadRequestHandler, PerlTransHandler, PerlHeaderParserHandler, PerlAccessHandler, PerlAuthenHandler, …) используются реже.

В нашем httpd.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 {
print
«Content-type: text/htmlnn»;
print
«Hi people! enjoy this response!»;
return
OK; # We must return a status to mod_perl
}
1;

MyOwnResponseGenerator.pm положим там, где мod_perl сможет его найти (perl -e ’print join "n"e;, @INC’). Отредактируем httpd.conf:

PerlModule MyOwnResponseGenerator
<Location /somelocation>
SetHandler perl-script PerlHandler MyOwnResponseGenerator
PerlSendHeader On
</Location>

Перезапустим Apache, наберём http://my-project.ru/somelocation.Работает!
Подробно о конфигурировании mod_perl:
http://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 … . Как правило на сервере работают несколько дочерних процессов httpd, каждый из них имеет свою копию вашего скрипта и соответственно свою копию $i.
Команда httpd -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!);

достаточно одному пользователю указать верные login-password, и все остальные смогут заходить просто так :).


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, они некорректно работают из кэша из-за описаных выше проблем, и вам лень их адаптировать. Используйте Apache::PerlRun вместо Apache::Registry. Скрипты не будут кэшироваться, однако по прежнему будут выполняться встроеным Perl интерпретатором.

Подробно о работе скриптов под mod_perl:
http://perl.apache.org/docs/1.0/guide/porting.html

Производительность


Оценим ради интереса выигрыш в производительности, который даёт mod_perl:
1. time lwp-request http://my-project.ru/cgi-bin/script.pl —запустим несколько раз и оценим среднее время выполнения lwp-request. Наш script.pl здесь работает под Apache::Registry.
2. time lwp-request http://my-project.ru/cgi-bin/script.pl — сделаем то же самое, но script.pl работает без mod_perl.
3. time lwp-request http://my-project.ru/little_page.html — так мы оценим время, которое в предидущих двух случаях тратилось на компиляцию lwp-request(ибо он на Perl), на передачу запроса и ответа по сети и т.д. вообщем на всё, не касающееся script.pl.

На моём 300Celeron результаты следующие: 774, 1039, 768 миллисекунд соответственно. Т.е. под mod_perl скрипт выполнился за 6мс (774–768), без mod_perl — за 71мс (1039–768). В 12 раз возросла прозводительность, однако! Для реальных скриптов эта цифра будет меньше, конечно.

Пора закругляться


Где взять
http://perl.apache.org/dist/mod_perl-1.0-current.tar.gz
http://perl.apache.org/docs/1.0/api/index.html
Документация
http://perl.apache.org/docs/1.0/index.html
Кто использует
http://slashdot.org/
http://search.cpan.org/
http://www.wired.com/



Похожие статьи:
- Класс для создания меню навигации на сайте
- Drag & Drop на AJAX
- Интернет-раскрутка: с чего начинать?
- Защита сайта от спамеров с использованием PHP. Практическое применение кода подтверждения с картинки
- PHP5 - Новые возможности PHP5-Zend Engine 2_0
- Введение в PHP5
- Создание гостевой книги
- Постраничный вывод из MySQL
- Защита сайта с помощью .htaccess и .htpasswd
- Риски при поисковой оптимизации интернет-сайта
- Как стать неудачником, или Десятка самых надежных способов гарантировать провал своей маркетинговой
- Как нельзя раскручивать сайты
- Использование SSI в построении сайта


Оглавление | Обсудить на форуме | Главная страница сайта | Карта сайта |
[0.001]