WebScript.Ru
C:\   главная  ::   о сайте  ::  каталог скриптов  ::  гнездо  ::  форум  ::   авторам  :: Новостройки ::   ХОСТИНГ  ::

|| разделы::
|| поиск по сайту::

|| реклама::
|| новости почтой::
Рассылки Subscribe.Ru ::



Новости сайта WebScript.Ru
Популярные статьи

Hot 5 Stories

|| рекомендуем::




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


Прислал: Бурмистров Андрей [ 17.01.2003 @ 14:12 ]
Раздел:: [ Статьи по Perl ]


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 и кэшировался. Для этого мы изменяем http2d.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.

Разберёмся с тем, что мы написали в http2d.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, …) используются реже.

В нашем 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 {
print «Content-type: text/html\n\n»;
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’). Отредактируем http2d.conf:
PerlModule MyOwnResponseGenerator
<Location /somelocation>
SetHandler perl-script
PerlHandler MyOwnResponseGenerator
PerlSendHeader On
</Location>
Перезапустим Apache, наберём //my-project.ru/somelocation. Работает!
Подробно о конфигурировании 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!’);
достаточно одному пользователю указать верные 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:
//perl.apache.org/docs/1.0/guide/porting.html



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

Оценим ради интереса выигрыш в производительности, который даёт mod_perl:
1. time lwp-request //my-project.ru/cgi-bin/script.pl — запустим несколько раз и оценим среднее время выполнения lwp-request. Наш script.pl здесь работает под Apache::Registry.
2. time lwp-request //my-project.ru/cgi-bin/script.pl — сделаем то же самое, но script.pl работает без mod_perl.
3. time lwp-request //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 раз возросла прозводительность, однако! Для реальных скриптов эта цифра будет меньше, конечно.



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

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



 :::::  Ilya Martynov пишет 19.01.2003 @ 18:13 
> В 12 раз возросла прозводительность, однако! Для реальных скриптов эта цифра будет меньше, конечно.

Совсем необязательно эта цифра будет меньше. Если скрипт, например, использует много модулей, то CGI будет тратить на каждом запросе время на их загрузку, и разница в производительности может быть гораздо больше.

Или другой пример: некоторые SQL сервера имеют очень большие издержки на создание соединения. Соотв. пока CGI будет ждать в DBI->connect, mod_perl'овый вариант давно уже возмет $dbh из pool'а и отработает запрос.

 :::::  Бурмистров Андрей пишет 20.01.2003 @ 11:27 
Да, совершенно справедливое замечание, спасибо.
Пожалуй мне стоило ещё про Apache::DBI написать, который кэширует $dbh... но теперь поздно уже, заметка опубликована.
Так что man Apache::DBI :)
 :::::  Макс пишет 20.01.2003 @ 20:32 
Кстати про Apache::DBI
Можете из опыта сказать, нет ли в нем проблем как в php с persistent-connections ?
(просто интересно, я mod_perl только недавно начал изучать, проверить это не могу)
 :::::  Ilya Martynov пишет 20.01.2003 @ 23:51 
А какие проблемы с persistent-connections в php?

Я, лично, никаких проблем с Apache::DBI не встречал (с MySQL, PostgreSQL и Oracle).
 :::::  Бурмистров Андрей пишет 21.01.2003 @ 12:39 
проблема, общая для любых persistent-connections - следующая ситуация:
Кол-во различных соединениий с DB из ваших скриптов x Кол-во процессов httpd больше, чем максимально допустимое число соединений вашей DB. У меня было подобное с PostgreSQL.
Других проблем не было.
 :::::  Макс пишет 21.01.2003 @ 23:07 
> проблема, общая для любых persistent-connections
Спасибо, буду знать
 :::::  Роман пишет 22.01.2003 @ 17:57 
Интересная статья но хотедось бы поподробнее с примерами и.т.д
 :::::  Некто пишет 12.09.2003 @ 14:56 
Неибацца пецдатая статья. Побольше бы таких...
 :::::  RubinLion пишет 19.04.2010 @ 12:03 
Есть на продажу (если в Москве - то в тот же день из рук в руки) несколько новеньких экземпляров книги "mod_perl 2 User's Guide" от "Backman & Brandt" по цене 1300 руб. Весьма полезное и исчерпывающее руководство для Perl-программиста высоконагруженных СОВРЕМЕННЫХ приложений.
Подробности:
http://modperl2book.org/

Email для связи:
tollanin@yandex.ru

Андрей.
Имя:
Email:
URL

Введите сумму двух чисел девять и одинн (девять+одинн=?)
Запомнить мою информацию

* Html запрещен* Ваш E-mail опубликован не будет.

Copyright © 2000-2001 WebScript.Ru nas@webscript.ru
Design © 2001 by Parallax Design Studio (aka Spectator.ru)
Все торговые марки и авторские права на эту страницу принадлежат их соответствующим владельцам.
Сгенерировано за: 0.0348480