Содержание


У истоков Apache. Часть 3: История и обзор архитектуры

Comments

Серия контента:

Этот контент является частью # из серии # статей:

Следите за выходом новых статей этой серии.

Этот контент является частью серии:

Следите за выходом новых статей этой серии.

1. История Apache

Apache ведет свою историю от веб-сервера NCSA httpd, написанного в свое время Rob McCool. NCSA в свою очередь был развитием CERN httpd. CERN имел более широкий функционал, в то время как NCSA был менее масштабен и более легок. NCSA появился после CERN в тот момент, когда возникла потребность в небольшом и быстром веб-сервере. Позднее к проекту подключились другие авторы, которые стали накладывать свои патчи.

В 1995 году Brian Behlendorf объединил эти патчи и создал список рассылки, на основе которого сформировалась группа разработчиков, выпустивших первую версию Apache.

Имя Apache — это сокращенное "a patchy server".

Первая версия имела номер 0.6.2. Один из участников — Robert Thau — разработал новую серверную архитектуру, которая появилась в версии 0.8.8. В декабре 1995 года вышел релиз Apache 1.0. Популярность к Apache пришла через год. В следующие годы группа разработчиков расширялась, и Apache был портирован на различные операционные системы.

В 1998 году появилась версия 1.3. В 1999 году была создана некоммерческая организация Apache Software Foundation.

В марте 2000 года состоялась первая конференция для разработчиков под названием ApacheCon. На ней была представлена версия Apache 2.0. В ней была переработана предыдущая серверная архитектура. Это дало широкие возможности для написания разнообразных модулей.

Не далее как 22 сентября 2010 года был зафиксирован 1-миллионный коммит.

Юбилейное изменение в репозитории было сделано Йоником Силеем (Yonik Seelay), разработчиком проекта Apache Lucene. Всего сейчас в сообществе Apache более 300 индивидуальных участников и 2300 коммитеров.

На сегодняшний день мирно сосуществуют 2 ветки Apache — 1.3 и 2.0. Обе версии на сегодняшний день поддерживаются. Они широко представлены и занимают половину серверного рынка в мире. Основной причиной успеха Apache является широкий спектр его функциональных возможностей. Apache может обслуживать одновременно большое количество клиентов. Он легко настраивается с помощью текстовых конфигурационных файлов и может быть на ходу переконфигурирован. Для разработки модулей имеется хорошо документированное API. Использование скриптовых языков позволяет использовать Apache в связке с базами данных и серверами приложений. Обе версии поддерживают протокол HTTP 1.1.

2. Модульная архитектура Apache

Ядро Apache включает в себя основные функциональные возможности, такие как обработка конфигурационных файлов, протокол HTTP и система загрузки модулей. Ядро (в отличие от модулей) полностью разрабатывается Apache Software Foundation, без участия сторонних программистов. Запускается Apache от рутового пользователя, а все последующие операции выполняет от лица непривилегированного пользователя.

Модули представляют из себя код, расширяющий функционал Apache. Модули могут быть статически слинкованы с ядром, либо загружаться динамически. В первом случае они собираются на этапе компиляции самого Apache. Во втором случае они загружаются при загрузке Apache, для этого есть дополнительный встроенный модуль mod_so.

Кроме того, имеется набор библиотек — Apache Portable Runtime (APR), который реализует кросс-платформенную поддержку системных функций.

Специальный модуль системного уровня — Multi-Processing Module (MPM) — дает возможность оптимизировать Apache в условиях конкретной операционной системы, предоставляя еще один вариант доступа к системным сервисам.

Модульная архитектура Apache
Модульная архитектура Apache

После стартовой начальной инициализации ядро передает управление модулю MPM, который поддерживает пул рабочих процессов/потоков, реализует интерфейс между сервером и данной операционной системой, оптимизируя работу сервера. MPM появился тогда, когда Apache был перенесен на Windows.

MPM имеет 2 основных режима работы:

  1. Prefork — это традиционный non-threaded вариант, присущий версии 1.3.
  2. Worker — многопоточный вариант, которому присущ меньший расход памяти.

Модуль взаимодействует с ядром с помощью простого интерфейса: в ядре регистрируется обработчик (handler), который потом может быть вызван. Также модуль может взаимодействовать с ядром с помощью специальных Apache API, которые позволяют модулям работать со структурами данных ядра.

Существует 4 основных типа обработчиков:

  1. Обработчики-переключатели.
  2. Конфигурационные обработчики.
  3. Фильтры.
  4. Функции-опции.

Обработчики-переключатели занимаются переключением обработчиков, выполняя роль событийного триггера. Такой обработчик имеет префикс ap_run_HOOKNAME. Они бывают двух типов:

  • RUN_ALL/VOID — вызываются всегда, независимо от статуса выполняемой задачи;
  • RUN_FIRST — вызываются до тех пор, пока задача не выполнена.

Модуль регистрирует в первую очередь обработчики этого типа. Вообще регистрация обработчиков отличается в первом и во втором Apache. В первом все обработчики регистрируются автоматически при старте. Во втором модуль регистрирует 4 обработчика-переключателя, остальные регистрируются потом с помощью функции ap_run_xxx.

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

Фильтры и функции-опции появились во втором Apache. Функции-опции похожи на обработчики.

3. Базовые концепции и структуры

В архитектуре Apache можно выделить следующие базовые объекты:

  1. Сервер.
  2. Коннект.
  3. Запрос.
  4. Процесс.

Каждый из этих объектов представлен соответствующей структурой в заголовочном файле httpd.h.

Помимо этих 4-х основных объектов в архитектуре Apache нужно отметить еще два объекта.

Первый объект — это пулы. Управлением ресурсов в Apache занимаются пулы — APR pools (apr_pool_t). Любой ресурс, выделяемый динамически, если он привязан к пулу, будет удален автоматически после использования. Пул привязывает ресурсы к жизненному циклу основных объектов, о которых мы сказали выше. Второй объект — это конфигурационный массив ap_conf_vector_t, причем каждому модулю в нем отводится свое место.

Массив хранит как глобальные конфигурационные данные, так и локальные.

В переводе на язык си основные четыре объекта представлены структурами:

	request_rec
	server_rec
	conn_rec
	process_rec

Более всего используются первые две. Каждый раз, когда на сервер приходит клиентский запрос, создается объект структуры request_rec, который передается в качестве параметра в любой обработчик, занятый обработкой запроса. Структура содержит не только стандартную информацию о HTTP-запросе, но и внутреннюю служебную информацию: пул запросов, массив глобальных и массив локальных конфигурационных записей, таблицы HTTP-заголовков, таблицу переменных окружения, указатели на сервер, коннект, фильтры, URL и его трансляцию, и т. д. Определение находится в httpd.h:

struct request_rec 
{
    apr_pool_t *pool;
    conn_rec *connection;
    server_rec *server;
		request_rec *next;
		request_rec *prev;
		request_rec *main;
		...
};

Структура server_rec представляет веб-сервер. Для каждого виртуального хоста имеется свой собственный экземпляр server_rec. Этот объект живет на протяжении всей жизни сервера. Ресурсы он берет из пула процессов. После структуры request_rec это вторая наиболее важная структура в Apache:

struct server_rec 
{
    process_rec *process;
    server_rec *next;
    const char *defn_name;
		char *server_admin;
		char *server_hostname;
		apr_port_t port;
		...
};

Структура conn_rec представляет TCP-коннект, создается при открытии коннекта и удаляется при его закрытии. Один коннект может породить несколько запросов. Запрос — это производный объект от коннекта:

struct conn_rec 
{
    apr_pool_t *pool;
    server_rec *base_server;
    void *vhost_lookup_data;
    apr_sockaddr_t *local_addr;
    apr_sockaddr_t *remote_addr;
		...
};

Структура process_rec имеет более непосредственное отношение к операционной системе, нежели к архитектуре самого сервера. Пул процессов можно получить через нее посредством

server_rec -> process_rec -> pool.

Другие структуры Apache разнесены по разным хидерам, из которых можно выделить следующие группы:

  1. ap_ — хидеры с таким префиксом генерируют низко-уровневое API и напрямую, как правило, не используются.
  2. http_ — в этих хидерах находится API, представляющее наибольший интерес для разработчиков.
  3. util_ — эти хидеры аналогичны первой группе.
  4. mod_ — здесь находятся определения для модулей.
  5. apr_ — APR API.

Для разработчиков наибольший интерес представляют следующие заголовки:

	http_config.h
	http_connection.h
	http_core.h
	http_log.h
	http_main.h
	http_protocol.h
	http_request.h
	http_vhost.h
    httpd.h
	util_filter.h
    ap_provider.h
    mod_dbd.h
	util_ldap.h
	util_script.h

4. Обработка запросов

Большинство модулей Apache имеют непосредственное отношение к обработке клиентских запросов, участвуя в этом процессе в определенной последовательности. Такой подход позволяет каждому модулю сфокусироваться на узком аспекте обработки.

Веб-сервер возвращает клиенту ответ, формируемый генератором контента. Любой модуль может зарегистрировать свой генератор с помощью директив SetHandler или AddHandler в файле httpd.conf. Если такой регистрации нет, то генератор по умолчанию просто возвращает файл, получаемый напрямую из запроса. Модули, которые реализуют свои собственные генераторы, называются контент-генераторами. Такой генератор в принципе может управлять всеми функциями. Например, CGI программа, получившая запрос, генерирует ответ, полностью контролируя этот процесс.

Apache разбивает запрос на несколько фаз, например, проверяет авторизацию пользователя. Непосредственно самой генерации предшествуют несколько стадий, например:

  1. URL проверяется на предмет наличия для него предопределенного конфигурационного генератора контента.
  2. URL транслируется на файловую систему, результатом чего может быть статичный файл, CGI-скрипт.
  3. Может быть включен модуль mod_negotiation для определения версии ресурса.
  4. Может происходить проверка доступа.
  5. Модули mod_alias или mod_rewrite могут изменить текущий URL.

Запрос может быть обработан нестандартным образом в силу следующих причин:

  1. Может быть сгенерирован дополнительный вложенный запрос или выдан документ с ошибкой.
  2. Могут быть добавлены дополнительные фазы обработки запроса.
  3. Хук (hook) quick_handler может быть запущен модулем кеширования.

Для изменения процесса обработки запроса существует механизм хуков. К ним в первую очередь относятся:

  1. post_read_request — этот хук может быть запущен на ранней стадии обработки запроса.
  2. translate_name — трансляция URL.
  3. map_to_storage — читает опции конфигурации.
  4. header_parser — запускается в начале обработки для чтения заголовков.
  5. access_checker — этот хук может заменить стандартную логику проверки прав доступа.
  6. check_user_id — назначает аутентификацию.
  7. type_checker — назначает обработчик контента.
  8. fixups — применяется непосредственно перед генерацией контента для его окончательной корректировки, один из наиболее часто используемых хуков.
  9. handler — отсылает контент клиенту.

Модуль может использовать хуки в любой точке обработки запроса. В дополнение к этим стандартным хукам модуль может определить свои собственные хуки.

Главным отличием второго Apache является появление фильтров. Фильтры бывают входящими и выходящими. Когда стоит дилемма в выборе между хуком и фильтром, фильтр нужно реализовывать случае, если модуль обрабатывает входные и выходные данные и используется во многих приложениях.

Примеры модулей, реализованных как фильтры:

  1. mod_include — подключает скрипты.
  2. mod_ssl — реализует защищенный протокол.
  3. обработка картинок.
  4. mod_form, mod_upload — обработка форм и загрузок.
  5. mod_deflate — сжатие данных.

Обычно каждый модуль Apache декларирует набор данных и функций:

module AP_MODULE_DECLARE_DATA my_module = 
{
    STANDARD20_MODULE_STUFF,  /* версионность */
    my_dir_conf,              /* локальная конфигурация */
    my_dir_merge,             
    my_server_conf,           /* генеральная конфигурация */
    my_server_merge,          
    my_cmds,                  /* директивы конфигурации */
    my_hooks                  /* обработчики, регистрируемые в ядре */
};

Функция для обработки запроса:

static void my_hooks(apr_pool_t *pool) 
{
	...
}

Хук для генератора контента:

	ap_hook_handler(my_handler, NULL, NULL, APR_HOOK_MIDDLE);

Когда начнется генерация контента, будет вызван my_handler:

static int my_handler(request_rec *r) 
{
	...
}

5. Фильтры

В первом Apache обработчик контента работает по стандартной схеме. Вначале вызывается обработчик type_checker для определения типа контента, после чего ядро вызывает нужный обработчик для отсылки контента. Недостатком обработки контента в первом Apache является то, что если контент имеет комплексный тип и для его обработки требуется не один, а несколько обработчиков, то контент отсылается по очереди, и каждый последующий обработчик никак не может повлиять на то, что отсылается клиенту до него или после него.

Во втором Apache обработчик контента расширен путем добавления фильтров, которые могут манипулировать данными, посылаемыми клиенту. И несколько модулей могут параллельно обрабатывать один клиентский запрос. Фильтры могут быть назначены еще на этапе определения типа контента.

Фильтры бывают входящими (input filters) и исходящими (output filters).

Фильтры Apache
Фильтры Apache

Обрабатываемые данные разбиваются на секции (brigade), которые в свою очередь разбиваются на сегменты (bucket). Один фильтр обрабатывает один сегмент, после чего передает его по цепочке на следующий фильтр.

Кроме деления на входящие и исходящие, фильтры можно разбить еще на три категории:

  1. Контент-фильтры.
  2. Протокольно-кодировочные фильтры.
  3. Сетевые фильтры.

6. Конфигурация Apache

Для конфигурации Apache есть 4 основных подхода:

  1. Компиляция / инсталляция: сборка из исходников позволяет выбрать необходимые модули, установить нужные флаги, пути и т. д.
  2. Параметры командной строки: позволяют конфигурировать Apache при запуске.
  3. Глобальные конфигурационные файлы: главный файл по умолчанию называется httpd.conf.
  4. Локальные конфигурационные файлы: использование .htaccess.

Конфигурационные директивы в файле httpd.conf можно разбить на 3 категории:

  1. Директивы, контролирующие общий процесс работы.
  2. Директивы виртуальных хостов.
  3. Настройки виртуальных хостов.

К директивам первой группы относятся <Directory>, <DirectoryMatch>, <Files>, <FilesMatch>, <Location>, <LocationMatch>.

Они применяются в привязке к конкретной файловой структуре либо к URL. В первом случае это <Directory>, во втором — <Location>. Apache может обслуживать одновременно несколько веб-сайтов с различными именами, реализуя виртуальный хостинг, что делается на основе директивы <VirtualHost>. Для того, чтобы изменения в главном конфиге вступили в силу, сервер должен быть перезапущен.

Локальная конфигурация реализована на основе .htaccess. Имя этого файла можно изменить в секции AccessFileName. Изменения в файле .htaccess вступают в силу немедленно, без перезапуска, его действие распространяется на каталог, в котором он лежит, со всеми вложенными подкаталогами. Избыточное использование .htaccess может повлиять на производительность сервера.

Содержимое основного конфига httpd.conf можно разделить на 5 секций:

  1. Глобальные директивы.
  2. <VirtualHost> — применимы к выиртуальным серверам.
  3. <Directory>, <DirectoryMatch> — применимы к каталогам.
  4. <Files>, <FilesMatch> — применимы к файлам.
  5. <Location>, <LocationMatch> — применимы к URL.

Директива может иметь несколько параметров, тип параметров может различаться.

Каждая директива обрабатывается определенным модулем.

Например, директива

	LoadModule foo_module modules/mod_foo.so

будет обработана mod_so, в этой команде 2 аргумента — имя загружаемого модуля и имя файла.

Следующая директива будет обработана ядром:

	DocumentRoot /usr/local/apache/htdocs

Следующая директива будет обработана модулем mod_env, будет установлена переменная окружения:

	SetEnv hello ”Hello, World!”

Контейнер — специальная форма директивы с использованием скобок, которая имеет свой внутренний контекст. Например, контейнер <VirtualHost>:

<VirtualHost 10.31.2.139>
  ServerName www.example.com
  DocumentRoot /usr/www/example
  ServerAdmin webmaster@example.com
  CustomLog /var/log/www/example.log
</VirtualHost>

Содержимое локального файла .htaccess можно разделить также на 5 секций:

  1. AuthConfig — контроль авторизации.
  2. Limits — контроль доступа.
  3. Options — конкретные настройки каталогов.
  4. FileInfo — установка атрибутов для документов.
  5. Indexes — индексация каталогов.

7. Apache API

Apache API включает в себя все возможности веб-сервера. Модульная архитектура позволяет встраивать новые модули на основе этого функционала. Ядро дает любому модулю большой выбор в вызове функций. Эти функции могут быть вызваны со специальными структурами в качестве параметров и могут возвращать специальные структуры. Базовые структуры заранее определены.

Вторая версия Apache уже включает в себя весь существующий функционал первой версии Apache, плюс имеется новый функционал в форме Apache Portable Runtime (APR).

Ядро управляет распределением памяти и следит за ее освобождением после того, как модуль закончил свою работу. Вся память выделяется в ядре. Память организована в форме пула (pool), каждый пул привязан к определенной задаче и имеет свой жизненный цикл. Имеется 3 главных пула — серверный пул, пул коннектов, пул запросов. Любой модуль может создать свой пул произвольного формата. Модуль может попросить ядро в любой момент создать пул и в любой момент его удалить.

Apache также управляет выделением памяти под массивы и управляющую хеш-таблицу.

Функции, с которыми работают модули, имеют параметры и структуры предопределенного типа, тип этот модули менять не имеют права. Наиболее важные внутренние типы данных Apache:

  1. request_rec — одна из наиболее важных структур, включает информацию о запросе. В этой структуре находится ссылка на пул запросов, а также другая структура с различными форматами URL для их трансляции.
  2. server_rec – в основном содержатся конфигурационные данные, а также имя сервера, порт, таймаут и т.д.
  3. connection_rec — содержится информация о коннекте. На один коннект может приходиться несколько запросов. Время жизни коннекта может превышать время жизни запроса. Здесь также хранится информация о клиенте.

Функции дают возможность модулям манипулировать своими структурами данных. Системные вызовы находятся в компетенции ядра. Имеются функции для создания процессов, открытия коммуникационных каналов для внешних процессов, отсылки данных клиенту, прикладные функции типа работы со строками и т. д.

Все функции можно разбить по категориям:

  1. Управление памятью.
  2. Управления процессами.
  3. Управление массивами.
  4. Управление таблицами.
  5. Управление строками.
  6. Управление сетью.
  7. Динамическая линковка.
  8. Логирование.
  9. Управление мьютексами.
  10. Авторизация.

Во второй версии Apache появился Apache Portable Runtime — дополнительный API функционал. Он включает:

  1. File I/O + Pipes.
  2. Дополнительное обслуживание памяти.
  3. Mutex + Locks, Asynchronous Signals.
  4. Network I/O.
  5. Многозадачность, в том числе потоки (threads).
  6. Dynamic Linking (DSO).
  7. Time.
  8. Authentication.

APR — это по сути целый новый фреймворк для веб-сервера.

Заключение

Apache обладает широким спектром возможностей, может обслуживать одновременно большое количество клиентов, легко настраивается с помощью текстовых конфигурационных файлов и может быть на ходу переконфигурирован. Для разработки модулей имеется хорошо документированное API. Использование скриптовых языков позволяет использовать Apache в связке с базами данных и серверами приложений.


Ресурсы для скачивания


Похожие темы


Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Open source, Linux
ArticleID=620073
ArticleTitle=У истоков Apache. Часть 3: История и обзор архитектуры
publish-date=01272011