The Apache Modeling Project. Глава 3 (Часть 2)


3.3.4 Фильтры Apache 2

Фильтры в Apache 2 - это обработчики, которые могут модифицировать данные запросов и ответов. Они обладают простым интерфейсом и являются взаимозаменяемыми.

Рисунок 3.6: Фильтры Apache: Цепочки входных/выходных фильтров
Рисунок 3.6: Фильтры Apache: Цепочки входных/выходных фильтров (Полный рисунок)
На рисунке 3.6 изображено два примера цепочек фильтров: Цепочка входных фильтров, которая обрабатывает данные запроса, и цепочка выходных фильтров, обрабатывающая данные ответа (полученных от обработчика контента). Агент “Request Processing” вызывает цепочку входных фильтров при получении запроса.
Для получения безопасного HTTP (HTTPS) соединения в цепочке входных фильтров нужно использовать модуль SSL.
Цепочка выходных фильтров запускается обработчиком контента.

Для улучшения производительности работа фильтров сделана независимой друг от друга. Это достигается путем разбиения обрабатываемых данных на контейнеры (bucket) и бригады (brigades) (см. рисунок 3.7). А вместо передачи всех данных на вход следующему фильтру передаются только ссылки на контейнеры (см. рисунок 3.8). Каждый запрос или ответ разбивается на несколько бригад. Каждая бригада состоит из некоторого количества контейнеров. Один фильтр обрабатывает один контейнер за раз и, когда закончит, передает контейнер следующему фильтру. Причем порядок, в котором работают фильтры, остается неизменным.
Рисунок 3.7: Фильтры Apache: Контейнеры в бригаде
Рисунок 3.7: Фильтры Apache: Контейнеры в бригаде
Рисунок 3.8: Фильтры Apache: Использование бригад для передачи данных между фильтрами
Рисунок 3.8: Фильтры Apache: Использование бригад для передачи данных между фильтрами
Кроме разделения фильтров на входные и выходные, можно выделить еще 3 категории:
1. SET-фильтры ресурсов и контента
Фильтры ресурсов изменяют контент, который проходит через них. Вставки на стороне сервера (SSI) или PHP типичные примеры данного типа фильтров. SET-фильтры изменяют контент в целом, например, сжимают или разжимают его.
2. Фильтры протокола и кодировки
Фильтры протокола используются для реализации протоколов (HTTP, POP и т.п). Такой подход позволяет поддерживать будущие версии HTTP. Фильтры кодировки изменяют кодировку данных запроса или ответа. Например, выходной фильтр разбивает ресурс на части, которые он затем отсылает клиенту по отдельности.
3. Фильтры соединения и сети
Фильтры соединения необходимы для установки и разрыва соединения. Например, установка HTTPS соединения требует специальных соглашений между клиентом и сервером. Они также могут изменять контент. Например - фильтр HTTPS. Фильтры сети отвечают за взаимодействие с операционной системой для установления сетевого соединения. Например, для поддержки протокола отличного от семейства TCP/IP, необходим только модуль с реализацией входного и выходного фильтра для этого протокола.

3.3.5 Предопределенные хуки

Хотя регистрация обработчиков хуков в Apache 2.0 отличаются от Apache 1.3, предопределенные хуки очень похожи в обеих версиях и могут быть разбиты на 3 различных категории по своему предназначению и по порядку выполнения:
  1. Управление конфигурацией.
  2. Запуск, перезагрузка и остановка сервера.
  3. Обработка HTTP запросов.

Хуки управления конфигурацией

При запуске или перезагрузке сервер Apache считывает и обрабатывает файлы конфигурации. Каждый модуль может предоставлять свои директивы конфигурации. Ядро конфигурационного процессора вызывает обработчики директив всякий раз, как встретит директиву, связанную с модулем. Для подготовки структур для хранения своих директив модуль может регистрировать обработчики следующих хуков:
Создание структуры конфигурации сервера
Если модулю необходимо хранить данные конфигурации сервера, то он может использовать обработчик этого хука. Этот хук используется исключительно для выделения и инициализации памяти для структуры конфигурации сервера. Он срабатывает один раз для главного сервера и один раз для каждого виртуального хоста.
Создание структуры конфигурации каталога
В обработчике этого хука модуль может выделять и инициализировать память для хранения данных конфигурации каталогов. Этот обработчик вызывается множество раз. Один раз после того, как будет инициализирована структура конфигурации сервера и по разу для каждой директивы контекста каталога этого модуля.
Обработчики директив
В таблице директив каждый модуль связывает директивы конфигурации с функциями, которые будут обрабатывать их параметры.
Данные конфигурации организованны иерархически. Правила определяют в каких случаях директивы конфигурации одного уровня могут быть переопределены директивами более детального уровня. Для этой задачи используются обработчики хуков объединения.
Объединение структур конфигураций серверов
Если при создании структуры конфигурации виртуального хоста некоторые директивы будут пропущены, то в этом обработчике модуль может заполнить пропущенные директивы данными конфигурации главного сервера. Этот обработчик вызывается один раз для каждого виртуального хоста.
Объединение структур конфигураций каталогов
Этот обработчик используется для объединения данных конфигураций каталогов с данными конфигурации сервера. Если конфигурационные данные для виртуального хоста отличаются от данных для каталога, тогда задача модуля, который вызывает этот обработчик, объеденить данные конфигураций. Этот обработчик вызывается один раз при запуске и каждый раз при обработке запроса. Также обрабатываются файлы .htaccess. Тот факт, что этот обработчик вызывается каждый раз при поступлении запроса, позволяет администраторам веб-сайтов изменять файлы доступа, не перезапуская сервер.
Для получения более детальной информации о конфигурации Apache смотрите разделы 3.2.1 и 4.5

Запуск, перезагрузка и остановка сервера

Apache является многозадачным (многопроцессным) сервером. При запуске и перезагрузке только один процесс производит чтение конфигурации. После этого он запускает дочерние серверные процессы, которые обрабатывают HTTP запросы.
pre_config
Этот хук срабатывает после чтения серверной конфигурации, но перед ее обработкой. Обработчик pre_config выполняется главным процессом сервера и пользуется его полномочиями (если выполняется под администратором).
open_logs
Модулю нужно зарегистрировать обработчик для этого хука, если ему необходимо открыть файлы логов сервера или выполнить запись логов. Некоторые МП-модули (см. раздел 4.3.4) иногда используют этот хук для доступа к некоторым ресурсам, например, к сокетам сервера.
post_config (Apache 1.3: Initializer)
Этот хук запускается главным процессом сервера после чтения и обработки конфигурации сервера. Срабатывает при запуске и в течение цикла перезагрузки.
pre_mpm (внутренний)
Этот внутренний хук включается главным процессом перед запуском дочерних процессов. Так как он лежит в зоне ответственности МП-модуля, то только ядро регистрирует обработчики для него.
Child_init
Любой обработчик, зарегистрированный для этого хука, вызывается один раз для каждого дочернего процесса сразу после его создания (на платформе win32 он запускается только дочерними процессами перед запуском рабочих нитей).
Child_exit (только для Apache 1.3)
В обработчике этого хука модуль может делать все необходимое перед завершением дочернего процесса. Например, можно освободить выделенную для дочернего процесса память.
Для большей информации о многозадачных стратегиях сервера и МП-модулях смотрите раздел 4.3.

Получение и обработка HTTP запросов

Все следующие хуки связаны с обработкой запросов и являются частью цикла ‘запрос-ответ’. Рисунок 3.9 и 3.10 показывает последовательную структуру этого процесса.
Установка соединения и чтение запроса. Рисунок 3.9 показывает поведение Apache в цикле ‘запрос-ответ’. Большинство хуков, показанных тут, не существует в Apache 1.3.
Рисунок 3.9: Цикл 'запрос-ответ' в Apache с включением модулей
Рисунок 3.9: Цикл ‘запрос-ответ’ в Apache с включением модулей (Полный рисунок)
create_connection (внутренний)
Этот внутренний хук передает процесс создание TCP соединения от МП-модуля ядру.
Pre connection
Этот хук позволяет сделать все необходимые настройки не только перед обработкой, но и перед установлением соединения, например, зарегистрировать входные фильтры.
process connection
Хук обработки соединения. По умолчанию это обработчик протокола HTTP, который обрабатывает запросы на соединения. Рисунок 3.9 показывает, что происходит внутри обработчика process connection.
Create request (внутренний)
Подготавливает все ресурсы для чтения запроса и отправки ответа.
post read request
Этот хук срабатывает после чтения запроса.
Обработка запроса и отправка ответа. Рисунок 3.10 показывает как Apache обрабатывает HTTP запрос. Тут не рассмотрены случаи внутренних запросов.
Рисунок 3.10: Обработка запросов сервером с модулями
Рисунок 3.10: Обработка запросов сервером с модулями (Полный рисунок)
quick handler
Этот хук запускается перед обработкой любого запроса и может использоваться для немедленного прекращения обработки. Кеш-модули могут использовать этот хук.
Translate name
Модуль может перевести URI запроса в имя файла или в другое имя ресурса.
map to storage (внутренний)
Определяет конфигурацию для запрошенного ресурса, обычно рассматриваются только секции Directory и Files. Прокси-модули обычно регистрируют обработчики для этого хука.
header parser
В обработчике этого хука модули могут получить доступ к заголовкам и прочитать специфичную информацию, например cookie. Так как подобная задача может быть выполнена в обработчике хука post read request, то он не используется в стандартных модулях Apache.
access checker
Этот хук может использоваться для проверки возможности клиента получить доступ к запрошенному ресурсу. Главным образом этот хук используется для запрета некоторого множества IP адресов. Вызывается всеми модулями.
check_user_id
Этот хук используется для проверки прав доступа клиента. Обычно это означает поиск имени пользователя и пароля в базе пользователей. Только один обработчик допускается для выполнения этой задачи.
auth checker
В обработчике этого хука модуль может проверить имеет ли пользователь, проверенный на предыдущем хуке на правильный пароль, доступ к запрошенному ресурсу. Только один модуль допускается для выполнения этой задачи.
type_checker
Этот хук позволяет обработчику определить или установить MIME тип запрошенного запроса. Результат нужен для выбора обработчика контента. Обработчик или фильтр позже может изменить MIME тип ответа.
fixups
В обработчике этого хука модули получают возможность изменить заголовки ответа перед вызовом обработчика контента.
insert filter
Данный хук позволяет модулям вставлять фильтры в цепочку выходных фильтров.
Handler
Хук для обработчика контента - самый важный в цикле ‘запрос-ответ’. Он генерирует или считывает запрошенный ресурс и отсылает данные ответа клиенту, используя цепочку выходных фильтров.
log transaction
В обработчике этого хука модуль может записать в лог свои сообщения.

3.3.6 Внутри модуля: mod_cgi

Для иллюстрации структуры модулей Apache на примере мы рассмотрим модуль mod_cgi.
Оба дистрибутива и Apache 1.3, и Apache 2.0 содержат можуль mod_cgi. Этот модуль используется для обработки CGI программ, которые могут создавать динамический веб-контент. Из-за архитектурных различий сервера версий 1.3 и 2.0, рассмотренных в предыдущей главе, две версии модуля также имеют некоторые различия.

Mod_cgi в Apache 1.3

Структура модуля. Обычно структура модуля находятся в конце главного файла исходного текста. В Apache 1.3 модуль mod_cgi содержит ссылки на два обработчика:
module MODULE_VAR_EXPORT cgi_module =
{
STANDARD_MODULE_STUFF,
NULL, /* инициализация */
NULL, /* создание конфигурации директории */
NULL, /* слияние конфигураций директорий */
create_cgi_config, /* создание конфигурации сервера */
merge_cgi_config, /* слияние конфигураций */
cgi_cmds, /* таблица директив */
cgi_handlers, /* обработчики */
NULL, /* filename translation */
NULL, /* check_user_id */
NULL, /* check auth */
NULL, /*check access */
NULL, /* type_checker */
NULL, /* fixups */
NULL, /* logger */
NULL, /* header parser */
NULL, /* child_init */
NULL, /* child_exit */
NULL /* post read-request */
};
Первая строка в структуре модуля ссылается на макрос standart_module_stuff, который добавляет данные необходимые каждому модулю. Также в этой структуре есть ссылки на две функции: create_cgi_config и merge_cgi_config. Этим обработчикам соответствуют хуки create server config и merge server config. Если Вы посмотрите на код этих функций, то увидите, что первая выделяет и инициализирует память для структуры конфигурации, а вторая объединяет данные конфигурации каждого виртуального хоста с данными главного сервера.

Таблица директив

static const command_rec cgi_cmds[] =
{
{“ScriptLog”, set_scriptlog, NULL, RSRC_CONF, TAKE1,
“the name of a log for script debugging info”},
{“ScriptLogLength”, set_scriptlog_length, NULL, RSRC_CONF, TAKE1,
“the maximum length (in bytes) of the script debug log”},
{“ScriptLogBuffer”, set_scriptlog_buffer, NULL, RSRC_CONF, TAKE1,
“the maximum size (in bytes) to record of a POST request”},
{NULL}
};
Указатели на таблицу директив и на обработчик контента ссылаются не на функции, а на структуры. Структура таблицы директив содержит ссылки на функции, используемые для обработки директив модуля mod_cgi. Внутри таблицы директив каждая ссылка на функцию имеет дополнительный макрос TAKE1, который сообщает ядру, что директива содержит только один параметр.

Обработчики контента

static const handler_rec cgi_handlers[] =
{
{CGI_MAGIC_TYPE, cgi_handler},
{“cgi-script”, cgi_handler},
{NULL}
};
Данная структура регистрирует обработчик контента cgi_handler для MIME типа CGI, а также для строки “cgi-script”. Функция cgi_handler будет вызываться для обработки контента. Используя эту структуру, модуль может регистрировать функции для нескольких обработчиков.
Когда обработчик type_checker решить, что модулю mod_cgi необходимо обработать поступивший запрос, ядро сервера вызовет соответствующий обработчик контента, то есть функцию cgi_handler.
Функция cgi_handler сперва подготовится для выполнения CGI кода, путем проверки некоторых условий. Затем она создаст дочерний процесс, вызвав ap_bspawn_child, который выполнит CGI программу. Среди других параметров, переданных функции, вызванной внутри процесса, есть структуры cgi_child и cgi_stuff, которые содержат все данные запроса. Структура сhild_cgi нужна, чтобы подготовить интерпретатор для выполнения скрипта, а после вызвать ap_call_exec. После завершения работы скрипта результат будет возвращен обработчику cgi_handler, который отправит данные клиенту.

Mod_cgi в Apache 2.0

Структура модуля. В структуре данных модуля mod_cgi для Apache 2.0 содержится гораздо меньше данных, чем в версии для Apache 1.3. Большинство указателей на обработчики хуков перенесены в функцию register_hooks. Все обработчики, за исключением обработчиков хуков управления конфигурацией, теперь динамически регистрируются внутри этой функции.
module AP_MODULE_DECLARE_DATA cgi_module =
{
STANDARD20_MODULE_STUFF,
NULL, /* Создание конфигурации директории */
NULL, /* Слияние конфигураций директорий*/
create_cgi_config, /* Создание конфигурации сервера*/
merge_cgi_config, /* Слияние конфигураций сервера*/
cgi_cmds, /* Таблица директив */
register_hooks /* Регистрация хуков*/
};
Хотя синтаксис и отличается, смысл функции для работы с конфигурацией остался тот же, что и в Apache 1.3. Посмотрев на код функции register_hooks, можно увидеть пример последовательности выполнения обработчиков при обработке запроса. Функция cgi_post_config вызывается первой при сработывании хука post_config, а cgi_handler будет вызван где-то посередине, когда сработает хук обработки контента.
static void register_hooks(apr_pool_t *p)
{
static const char * const aszPre[] = { “mod_include.c”, NULL };
ap_hook_handler(cgi_handler, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_post_config(cgi_post_config, aszPre, NULL, APR_HOOK_REALLY_FIRST);
}
Обработка запросов с помощью фильтров. В модуле mod_cgi в Apache 2.0, функция cgi_handler является началом выходной цепочки фильтров. Изначально поведение модуля очень похоже на поведение своего аналога в Apache 1.3. Он подготавливает к запуску процесс для выполнения программы CGI. После своего завершения дочерний процесс возвращает данные ответа. Почти вся обработка происходит в функции cgi_child. Затем созданная бригада с данными ответа передается вниз по цепочке фильтров. Это делается с помощью функции ap_pass_brigade. Это позволяет, например, CGI программе сгенерировать SSI директивы, которые будут обработаны соответствующим модулем. SSI модуль также должен зарегистрировать фильтр, чтобы получить данные от mod_cgi. Эта последовательность зависит от конфигурации для соответствующих MIME типов.

3.3.7 Apache API

Apache API предоставляет возможности изменять и расширять функциональность веб-сервера Apache. Весь сервер был спроектирован по модульной архитектуре, поэтому расширение функциональности означает создание нового модуля. В предыдущей главе мы рассмотрели каким образом сервер вызывает модули. А эта глава объясняет как модули выполняют свои задачи.
Сервер предоставляет большой набор функций для модулей. В качестве аргументов эти функции получают сложные структуры данных. Все эти структуры определены в исходных текстах Apache.
И снова вернемся к различиям между двумя основными версиями Apache: Apache 1.3 и Apache 2.0. Версия 2.0 почти полностью содержит API версии 1.3, а также включает Apache Portable Runtime (APR), которая существенно расширяет функциональность.

Управление памятью с помощью пулов

Apache предоставляет функции для различных задач. Одним из главных сервисов, который Apache предоставляет своим модулям - это управление памятью. Управление памятью является сложной задачей в С, а утечки памяти в сервере очень трудно обнаружить. Поэтому Apache берет на себя заботу о освобождении используемой модулем памяти. Для достижения этого вся память выделяется только ядром сервера. Ядро Apache организует память в виде пулов. Каждый пул связывается с некоторой задачей и имеет соответствующее время жизни. Главные пулы это: пулы сервера, соединения и запроса. Пул сервера существует до тех пор пока сервер не завершит свою работу. Пул соединения имеет время жизни соответствующего соединения. А пул запроса создается при поступлении запроса и уничтожается после его обработки. Любой модуль может запросить любой тип памяти из любого пула. Такой подход позволяет ядру сервера знать обо всей используемой памяти. Когда истекает время жизни пула, ядро освободит всю память, находящуюся под контролем этого пула. Если модулю необходима память с меньшим временем жизни, чем предоставляет любой из доступных пулов, то модуль может запросить Apache создать дочерний пул. Модуль может использовать этот пул, как и любой другой. А после того, как пул перестанет быть нужным, модуль может запросить Apache уничтожить его. Достоинства этого метода заключаются в том, что если модуль забудет уничтожить созданный пул, то ядро уничтожит родительский пул, что приведет к автоматическому уничтожению всех его дочерних пулов.
Также Apache предлагает механизмы работы с массивами и таблицами, что делает управление памятью еще более легким. Массивы в Apache могут в любое время менять свои размеры, что делает их похожими на вектора в Java, а таблицы хранят пары ключ/значение, что делает их похожими на хеш-таблицы. Больше информации о пулах можно получить в разделе 4.6.

Типы данных

Apache предоставляет функции, которые в качестве аргументов используют специальные структуры. Рассмотрим подробнее эти типах данных, используемые в Apache API. Большинство полей, содержащиеся в любой из этих структур, не могут быть изменены модулем напрямую. Apache предоставляет функции для изменения этих значений. Эти функции предостерегают от возможных ошибок, а также отвечают за совместимость с другими версиями.
request_rec
Это самая важная структура данных в Apache. Она передается обработчикам модулей в цикле ‘запрос-ответ’. Она содержит всю информацию о запросе, а также ссылки на данные конфигурации главного сервера и виртуального хоста (server_rec) и информацию о успользуемом соединении (connection_rec). Через эту структуру любой модуль может получить доступ к пулу запроса. В ней также содержатся различные форматы URI.
server_rec
Эта структура содержит информацию о сервере, главным образом о его конфигурации. Apache хранит эту структуру для главного сервера и для каждого виртуального хоста. Используя описатели модулей, ядро передает соответствующие серверные структуры каждому модулю. Сама структура содержит поля с такой информацией, как имя сервера, порт, настройки timeout и keep-alive. Через server_rec модуль может получить свои серверные директивы.
connection_rec
Эта структура содержит информацию о текущем соединении. В HTTP 1.1 множественные запросы могут быть переданы через одно соединение. Следовательно, соединение может существовать дольше, чем один запрос. Так как connection_rec имеет свой пул памяти, то любой модуль, работающий с подобными запросами, может хранить данные необходимые в течение всего устойчивого соединения. Также эта структура содержит различные данные пользователя.

Функции API

Кроме управления памятью Apache также предоставляет функции и для других целей. Apache API является независимым от операционной системы. Apache предлагает все необходимые функции для работы с данными сервера. Ядро также может выполнять системные вызовы от имени модуля и использовать все особенности используемой операционной системы. Такой метод позволяет использовать любой модуль в любой операционной системе. Например, Apache API содержит функции для создания процессов, открытия каналов с внешними процессами и отправки данных клиенту. Также Apache предлагает множество функции для работы со строками.
Внутри Apache API функции могут быть разбиты на следующие группы:
  • Управление памятью.
  • Многозадачность (только процессы).
  • Работа с массивами.
  • Работа с таблицами.
  • Работа со строками.
  • Сетевые функции (только соединение с клиентом).
  • Динамическое связывание.
  • Ведение логов.
  • Файловые семафоры.
  • Идентификация и авторизация.

Apache 2.0 и Apache Portable Runtime (APR)

Вторая версия Apache содержит Apache Portable Runtime (APR), которая добавила и расширила функциональность Apache API. В соответствие с APR, Apache может рассматриваться как универсальный сетевой сервер, которому можно добавить любую функциональность. Включая следующие независимые от платформы особенности:
  • Операции с файлами и каналами.
  • Расширенное управление памятью.
  • Семафоры и блокировки, асинхронные сигналы.
  • Работа с сетью.
  • Многозадачность (процессы и нити).
  • Динамическое связывание (DSO).
  • Время.
  • Авторизация.
Цель APR - это предоставить простую среду для сетевых серверов. Любой сервер, обрабатывающий запросы, может быть реализован с помощью ядра Apache и APR.

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • News2.ru
  • NewsLand.ru
  • del.icio.us
  • BobrDobr.ru
  • Ma.gnolia
  • Digg
  • Reddit
  • Technorati
  • Slashdot
  • Netscape
  • DZone
  • ThisNext
  • Furl
  • YahooMyWeb
Опубликовано в: Архитектура Март 12, 2006

3 Комментариев »

  1. Спасибо!! Еще одна классная и нужная статья!! РЕСПЕКТ!!
    ______________________
    http://www.wzstyle.net/

    Комментарий от андрюха — Август 30, 2008 @ 11:26 pm

  2. Спасибо!! Еще одна классная и нужная статья!! РЕСПЕКТ!!
    ______________________
    http://www.radwarez.ru/

    Комментарий от андрюха — Август 30, 2008 @ 11:37 pm

  3. А где предыдущая глава ?

    Комментарий от ДПСник — Март 5, 2009 @ 8:36 pm

Оставить комментарий

You must be logged in to post a comment.

Работает на WordPress