Краткая документация по Apache::Registry

  1. Что такое Apache::Registry
  2. Особенности разработки под Apache::Registry
    1. Использование exit()
    2. Использование die()
    3. Использование STDIN, STDOUT и STDERR
    4. Использование print()
    5. Использование __END__ и __DATA__
    6. Переменные окружения $ENV {SERVER_NAME}, $ENV {REMOTE_USER} и др.
    7. Использование массива @INC
    8. Перезагрузка модулей
      1. Перезагрузка сервера
      2. Использование Apache::StatINC
  3. Полезные ссылки

Что такое Apache::Registry

Apache::Registry — это модуль Apache, который позволяет сохранять скомпилированный mod_perl код в памяти для дальнейшего использования.

Дочерний процесс Apache, компилирует код один раз и сохраняет в памяти, где он хранится до его перезагрузки (если скрипт был изменен) или завершения работы процесса. Каждый процесс использует СВОЮ копию скрипта.

При дальнейшем обращении к скрипту, он извлекается из кеша и сразу выполняется. Apache::Registry сохраняет в памяти время последней модификации perl-скрипта. Если исходный код был обновлен, скрипт будет скомпилирован заново.

Настройка Apache::Registry в httpd.conf :

Необходимо отметить, что perl-скрипт будет скомпилирован как подпрограмма, входящая в состав другой, внешней, подпрограммы, и получившийся код будет сильно отличаться от исходного. Данную особенность необходимо учитывать при написании кода, который будет работать под управлением Apache::Registry. Подпрограммы, изменение которых не желательно, следует помещать в модули. Код модулей при их компиляции и выполнении не оборачивается во внешнюю подпрограмму.

Еще одна особенность работы с Apache::Registry: глобальные переменные скрипта сохраняют свои значения между запросами.

Классический пример того, как будет выглядеть исходный код скрипта после обработки Apache::Registry.

Исходный скрипт (/cgi/test.pl):

Что в реальности будет запускаться на выполнение:

Исходный perl-скрипт на выходе выполняется как самостоятельный модуль. Стоит обратить внимание на название пакета: Apache::ROOT::cgi::test_e2pl.

Каждый дочерний процесс Apache сохраняет для себя в памяти «готовые к употреблению» скрипты. Один и тот же скрипт может быть помещен в память несколько раз — для каждого процесса отдельно. Во избежание конфликта имен, Apache::Registry назначает каждому пакету уникальное название, с помощью добавления уникального ключа к имени пакета.

Особенности разработки под Apache::Registry

Использование exit()

Стандартная функция Perl — exit() / CORE::exit() — не может использоваться в разработке под mod_perl. Функция приводит к завершению процесса mod_perl. При этом, будут пропущены этапы логирования и корректного завершения работы процесса. Например, не оборвется соединение с базой данных, созданные хендлеры останутся в памяти. Минимальные возможные последствия: утечки памяти.

Apache::Registry и Apache::PerlRun негласно замещают стандартную функцию exit() функцией Apache::exit(). Поэтому, код с exit(), который работает под управлением данных модулей, можно использовать без изменений.

Если необходимо принудительно завершить дочерний процесс — рекомендуется использовать
Apache::exit (Apache::Constants::DONE). Apache::exit позволит корректно завершить процесс, произведя необходимые записи в логи и соблюдая требования протокола http.

Если необходимо завершить дочерний процесс после того, как завершено выполнение запроса — можно
использовать $r-> child_terminate . Данный метод устанавливает значение для переменной MaxRequestsPerChild равным 1 и присваивает флагу keepalive значение false. После завершения выполнения запроса, родительский процесс инициирует завершение дочернего процесса, если значение MaxRequestsPerChild меньше или равно числу выполненных запросов.

Использование die()

die() / CORE::die() — обычно используется для прерывания выполнения программы в случаях, когда что-то идет не так, как ожидалось.

При срабатывании die(), выполнение кода прерывается, печатается причина прерывания и завершается работа интерпретатора Perl.

При работе с mod_perl, завершение работы процесса не желательно. При вызове die(), mod_perl делает запись о возникшей ошибке в лог, и вызывает Apache::exit() вместо CORE::die().

Использование STDIN, STDOUT и STDERR

Под mod_perl, STDIN и STDOUT привязаны к сокету, из которого принят запрос.

STDERR привязан к файлу, определенному директивой ErrorLog.

Указанные положения исключают возможные конфликты доступа и разделения STDIN, STDOUT и STDERR.

Использование print()

Под mod_perl, CORE::print() автоматически переадресует переданные ему аргументы Apache::print().

В контексте mod_perl, нижеприведенные надписи эквивалентны:

Apache::print() прерывает выполнение и ничего не выводит на печать, если $r->connection->aborted возвращает true. Это происходит в случае прерывания связи клиентом (например, закрытием браузера).

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

Скрипты под Apache::Registry не могут содержать лексемы __END__ и __DATA__ , потому что, во время обработки, исходный код скрипта помещается в код подпрограммы handler().

Если скрипт содержит __END__ или __DATA__ :

то, после обработки и перед запуском, выполняемый код будет иметь вид:

Поскольку Perl игнорирует все, что идет за лексемой __END__ — программа будет выдавать ошибку.

error.log:

Переменные окружения $ENV {SERVER_NAME}, $ENV {REMOTE_USER} и др.

Apache::Registry эмулирует переменные окружения mod_cgi — $ENV {SERVER_NAME}, $ENV {REMOTE_USER} и др.

Отключить данную функциональность можно с помощью конфигурационной директивы PerlSetupEnv Off

Использование массива @INC

Значение массива @INC при работе с mod_perl, можно изменить только один раз — при запуске сервера. После выполнения каждого запроса к серверу, mod_perl возвращает @INC первоначальное значение.

Если mod_perl встретит в скрипте директиву

он внесет изменения в @INC, но действовать они будут только до завершения периода компиляции. После этого @INC примет исходное значение.

Есть два способа изменить @INC при запуске сервера:

  • использовать в конфигурационном файле сервера директивы

    или
  • прописать в startup.pl файле команду:

    и внести изменения в конфигурационный файл сервера, добавив:

Перезагрузка модулей

По-умолчанию, сервер не отслеживает факт модификации модулей, подключенных через use() или require() и считает, будто никаких изменений не производилось. При этом, использует ранее сохраненный в памяти вариант модуля.

На наличие изменений проверяются только perl-скрипты.

Есть несколько способов заставить сервер с mod_perl отслеживать изменения и, при необходимости, перезагружать модули.

Перезагрузка сервера

Простейший вариант — просто перезагружать сервер всякий раз, когда вы вносите изменения в Ваш код.

Использование Apache::StatINC

После подключения файла, с помощью require(), в глобальный хэш %INC вносится новая запись. Ключом записи является имя подключенного файла, значением — путь к нему. Apache::StatINC просматривает %INC и немедленно перезагружает все измененный модули.

Подключить Apache::StatINC можно с помощью добавления директив в конфигурационный файл сервера — httpd.conf:

Примечание:

Если подключается модуль, расположенный в той же директории, что и исходный скрипт, но текущая директория не указана в массиве @INC, в %INC будет внесена запись типа:

Когда Apache::StatINC попытается найти указанный модуль — произойдет ошибка, поскольку он ищет только в директориях, которые указаны в @INC. Решение: заранее указывать все необходимые директории в @INC .

Полезные ссылки

Stas Bekman. Practical mod_perl /By Stas Bekman, Eric Cholet — O’Reilly, 2003. — 924 с.

Writing Apache Modules with Perl and C
What is mod_perl
Использование mod_perl. Бурмистров Андрей