The Apache Modeling Project. Глава 4 (Часть 1)


4 Внутри сервера Apache

4.1 Введение

Данная глава целиком посвящена внутренней реализации сервера Apache. Вам следует ее прочитать, если:
  • Вам интересна внутренняя структура сетевого сервера;
  • Вы намереваетесь работать или модифицировать Apache.
Некоторые разделы содержат описание исходного кода сервера. В течение первого года проекта мы исследовали Apache версии 1.3.17 и сравнивали полученные результаты с Apache 2.0, исследованного во втором году.

Чтобы качественно усвоить материал этой главы, Вам необходимо знать концепции HTTP сервера, описанные в главе 2, и быть знакомыми с характеристиками Apache, описанными в главе 3. Кроме того, Вам необходимо понимать код на языке С.
В разделе 4.2 показан первый шаг исследования исходного кода: приведено изображение структуры кода сервера Apache.

Основная задача сетевого сервера - это обработка одновременных событий. Раздел 4.3 сперва познакомит Вас с простым путем реализации многозадачного сервера, а затем сравнит его с подходом, использованным в Apache.
На рисунке 4.8 показано поведения сервера Apache. На нем также изображена реакция сервера на команды администратора (перезагрузка и завершение работы).
Главный цикл сервера, описанный в разделе 4.3.3, более развернуто демонстрирует многозадачную модель сервера Apache.
Цикл ‘запрос-ответ’ в разделе 4.4 является сердцем каждого HTTP сервера и поэтому похож на поведение простого HTTP сервера, изображенного на рисунке 2.2. Также в этом разделе вы сможете найти “другую сторону” callback-функций модулей, описанных в разделе 3.3.
Остальные разделы этой главы посвящены деталям реализации различных концепций сервера Apache.

4.2 Структура исходного кода сервера

4.2.1 Исходный код Apache 1.3.17

Рисунок 4.1: Структура каталогов исходного кода Apache 1.3.17
Рисунок 4.1: Структура каталогов исходного кода Apache 1.3.17 (Полный рисунок)
Исходный код Apache версии 1.3.17 состоит из 780 файлов в 44 каталогах; 235 файлов содержат код на языке С. Рисунок 4.1 показывает структуру каталогов поставки Apache версии 1.3.17. Наиболее важным каталогом является src. Он содержит подкаталоги со всеми исходными файлами сервера Apache и большинства модулей. Наиболее интересными для нас каталогами являются main и modules, так как они содержат основной исходный код, который необходим для изучения концепций работы Apache.

4.2.2 Исходный код Apache 2.0.45

Рисунок 4.2: Структура каталогов исходного кода Apache 2.0.45
Рисунок 4.2: Структура каталогов исходного кода Apache 2.0.45 (Полный рисунок)
По сравнению с версией 1.3, код Apache 2.0 стал намного больше. Исходный код Apache 2.0.45 состоит из 2165 файлов в 183 подкаталогах; 704 файла содержат исходный код на языке С (примерно 280 000 строк, включая комментарии). Структура каталогов исходного кода также претерпела значительные изменения. Однако наиболее важные части для нас все еще находятся в нескольких центральных каталогах. Файлы ядра сервера находятся в каталоге server, файлы МП-модулей находятся в каталоге mpm. Каталог module всё также содержит подкаталоги со всеми модулями, включенными в исходный код.

4.3 Многозадачные архитектуры сервера

Наиболее важным фактором при создании многозадачной архитектуры является используемая операционная система. У каждой операционной системы есть собственное окружение и характеристики производительности. Поэтому некоторые многозадачные архитектуры несовместимы или не работают полноценно на определенных операционных системах. Другим важным фактором является используемый сценарий работы сервера. В зависимости от того, сколько времени требует обработка одного запроса, сколько запросов сервер будет обрабатывать и будут ли запросы логически зависеть друг от друга, определенные архитектуры могут быть более подходящими, чем другие.
Раздел 4.3.1 объясняет, как работает простая многозадачная архитектура сетевого сервера, а также объясняет недостатки использования ее для HTTP сервера. Архитектура сервера Apache будет рассмотрена в разделе 4.3.2.

4.3.1 Inetd: Простая многозадачная архитектура

Главный сервер в качестве “сторожа”

Сетевые серверы, обрабатывающие одновременные запросы, обычно используют многозадачную архитектуру. Сейчас мы рассмотрим вариант использования процессов для обеспечения многозадачности (Apache не использует этот метод), который работает следующим образом:
Главный процесс сервера ожидает входящих запросов. Всякий раз, когда от клиента поступает запрос, главный процесс устанавливает соединение с клиентом, а затем создает дочерний серверный процесс, тем самым, распараллеливая самого себя. Дочерний процесс обрабатывает запрос(ы) клиента, в то время как главный серверный процесс возвращается в состояние ожидания запросов.
Рисунок 4.3: Многозадачная архитектура сервера: inetd
Рисунок 4.3: Многозадачная архитектура сервера: inetd (Полный рисунок)
На рисунке 4.3 изображена структура многозадачного сервера данного типа. В верхней части рисунка один или несколько клиентов отправляют запросы (R) серверу. Коммуникационный сервис TCP/IP операционной системы получает эти запросы. Главный серверный процесс регистрирует себя в качестве ответственного за все поступающие запросы. Следовательно, он запускается коммуникационным сервисом при поступлении запроса. После того как главный серверный процесс принял запрос на соединение, коммуникационный сервис может установить TCP/IP соединение и создать новую структуру данных сокета.
Главный серверный процесс создает дочерний процесс, вызывая системную функцию fork(). На рисунке 4.3 это изображено стрелкой от главного процесса к области, ограниченной пунктирной линией. Дочерний сервер знает о соединении, так как он знает сокет соединения. Теперь он может взаимодействовать с клиентом до тех пор, пока один из них не закроет это соединение. Тем временем главный процесс сервера ожидает получения новых запросов.
По спецификации TCP/IP конечная точка соединения идентифицируется по IP адресу машины и по номеру порта (например, порт для HTTP запросов имеет номер 80). Главный серверный процесс регистрирует себя для прослушивания порта (который становится серверным портом). Заметьте, что запрос на соединение приходит на серверный порт когда соединение уже установлено. Основное различие между портом сервера и портом соединения заключается в том, что порт сервера используется для принятия соединений от всех клиентов. А порт соединения использует такой же номер порта TCP/IP, но он связан с одним конкретным соединением и, следовательно, с одним коммуникационным партнером. Порты соединения используются для передачи данных, а порт сервера может оставаться открытым для следующих запросов на соединение.
Рисунок 4.4: Поведение многозадачного сервера
Рисунок 4.4: Поведение многозадачного сервера (Полный рисунок)
Поведение сервера показано на рисунке 4.4. Система вызывает accept() или select(), блокируя главный серверный процесс, пока не поступит запрос. accept() ожидает запросов на один серверный порт, тогда как select() прослушивает сразу несколько портов. После получения коммуникационным сервисом TCP/IP запроса, главный серверный процесс устанавливает соединения с помощью системного вызова accept(). После этого он создает новый процесс с помощью fork(). Если запрос нуждается в обработке внешней программы, то она загружается и выполняется функцией exec().

INETD

INETD - это сервер, использующий многозадачную архитектуру, описанную выше. Он ожидает запросы на множество портов, определенных в конфигурационном файле /etc/inetd.conf. Когда приходит запрос, inetd запускает серверную (дочернюю) программу, также определенную в конфигурационном файле. Затем эта программа обрабатывает запрос.
Apache также предоставляет режим работы, использующий архитектуру inetd. В этом случае, inetd прослушивает HTTP порт (80) и запускает Apache всякий раз, когда приходит HTTP запрос. Apache отвечает на запрос и завершает работу.

Недостатки

Данная многозадачная архитектура полезна, если обработка запросов клиента занимает некоторое время или состояние сессии соединения необходимо хранить на (дочернем) сервере, в случае если обмен данными между клиентом и сервером не завершается после ответа на первый запрос.
Тем не менее, протокол HTTP не сохраняет сессию. Никакой информации о сессии не хранится на сервере - ему надо только ответить на один запрос и тут же может забыть о нем. HTTP сервер, основанный на архитектуре inetd - неэффективен. Главному серверу необходимо создавать новый процесс для каждого HTTP соединения, который затем обрабатывает это соединение и завершается. Пока главный сервер создает процесс, он не может принимать входящие запросы. Хотя создание процесса и не занимает много времени на современных операционных системах, данная функция главного сервера является “узким местом” для всего сервера в целом.

4.3.2 Обзор: Многозадачные архитектуры Apache

Все многозадачные архитектуры Apache основаны на концепции пула задач. При запуске Apache создает некоторое количество задач (процессов и/или нитей), большинство из которых неактивны. Поступивший запрос обрабатывается одной из задач пула, поэтому нет необходимости создавать задачу для обработки запроса так, как это описано в разделе 4.3.1 для inetd.
Другой общий компонент - это главный сервер, задача которого контролировать пул задач или же перезапускать сервер, когда что-нибудь пойдет не так. Главный сервер также предоставляет интерфейс контроля для администратора.
Следующая архитектура, которую мы рассмотрим, является архитектура prefork. Она является первой из наиболее важных архитектур для unix систем. Затем мы рассмотрим несколько других многозадачных архитектур Apache и подробней остановимся на их отличиях от архитектуры prefork.

4.3.3 Многозадачная архитектура prefork

Шаблон ‘Лидер - последователи’

Архитектура prefork основана на пуле задач (процессов или нитей), которые играют три различные роли:
  • ожидание запросов (прослушиватель)
  • обработка запросов (рабочий)
  • постановка в очередь и ожидание на прослушивание (приостановленный)
Рисунок 4.5: Шаблон 'Лидер - последователи' в архитектуре prefork
Рисунок 4.5: Шаблон ‘Лидер - последователи’ в архитектуре prefork (Полный рисунок)
Рисунок 4.5 показывает структуру системы. Прослушиватель является лидером. Только одна задача может ожидать запросы на подключение. После того, как прослушиватель получает запрос, он передает свое право прослушивать другой задаче и переключается в режим обработки. Это означает, что он обрабатывает запрос, используя соединение, которое он установил в качестве прослушивателя. Если он закончил обработку запроса, он закрывает соединение и переходит в состояние ожидания. Что означает, что он помещается в очередь ожидания стать прослушивателем. Обычно задачи в этом режиме приостанавливаются.
В чем разница между стратегией, описанной в разделе 4.3.1, и стратегией ‘Лидер - последователи’? Во-первых, поступивший запрос обрабатывается незамедлительно прослушивающей задачей - не надо создавать новые задачи. С другой же стороны, необходимо всегда держать приостановленные задачи, чтобы всегда иметь возможность прослушать запросы. Во-вторых, нет необходимости передавать информацию о запросе между задачами, так как прослушиватель просто переключает свой режим, а информация сохраняется.
Пул задач должен быть создан при запуске сервера. Для уверенности в быстром ответе сервера, число задач в пуле должно быть достаточно большим, однако ресурсы компьютера ограничены. Решением этой проблемы является контроль количества задач в пуле некоторым агентом - главным сервером.

Архитектура prefork

Архитектура prefork была первой многозадачной архитектурой в Apache. В Apache версии 2.0 она является базовой МП-архитектурой (модулем) для Unix. МП-модуль Netware по функциональности очень близко походит на prefork, за исключением того, что он использует нити Netware вместо процессов unix. Архитектура prefork в Apache использует в качестве дочерних серверов процессы. Это делает данную архитектуру более стабильной, но при этом несколько снижает производительность.
Рисунок 4.6: МП-модуль prefork в Apache 2.0
Рисунок 4.6: МП-модуль prefork в Apache 2.0 (Полный рисунок)
Диаграмма на рисунке 4.6 показывает структуру архитектуры prefork в Apache 2.0, также она важна для понимания поведения Apache. На ней видно, какие компоненты могут взаимодействовать, а также какие хранилища могут быть прочитаны, а какие изменены. Блочная диаграмма МП-модуля Apache 2.0 архитектуры prefork очень похожа на диаграмму, используемую в Apache 1.3, однако есть одно важное отличие: главный сервер для завершения дочерних серверов при перезагрузке вместо сигналов использует ‘канал смерти’ (pipe of death).
На первый взгляд архитектура prefork, показанная на рисунке 4.6, выглядит очень похожей на архитектуру inetd на рисунке 4.3. Как и в inetd, существует один главный сервер и множество дочерних серверов. Однако есть одно большое отличие, которое состоит в том, что дочерние процессы существуют еще до того, как поступят запросы. Так как для создания процессов главный сервер использует вызов системной функции fork() и делает это до поступления первого запроса, то архитектура получила название prefork. Главный сервер вообще не ожидает входящих запросов - их ожидают созданные дочерние сервера , а затем обрабатывают запросы напрямую.
Главный сервер создает множество приостановленных процессов дочерних серверов, которые для получения запроса регистрируются в коммуникационном сервисе TCP/IP. Первый дочерний сервер получает запрос на соединение, отправляет ответ на него и ожидает следующего запроса. Главный же сервер регулирует количество дочерних процессов в заданных границах.

Основная схема поведения

На рисунке 4.7 изображено полное поведение сервера, включая поведение главного сервера и дочерних серверов.
Рисунок 4.7: Обзор: Поведение Apache
Рисунок 4.7: Обзор: Поведение Apache (Полный рисунок)
Независимо от лежащей в основе многозадачной архитектуры, поведение Apache состоит из последовательности следующих частей, которые будут рассмотрены отдельно для каждой архитектуры:
  • Первоначальная инициализация:
    Выделение ресурсов, чтение и проверка конфигурации, запуск демона.
  • Цикл перезагрузки:
    Перечитывание конфигурации, создание пула задач для запуска дочерних процессов и вход в главный цикл сервера.
  • Главный цикл сервера:
    Контролирование количества ожидающих дочерних процессов и пуле задач.
  • Цикл ‘запрос-ответ’ (только для дочернего сервера)
    Ожидание первой позиции, ожидание запроса на соединение, переход в режим обработки и вход в цикл keep-alive.
  • Цикл keep-alive (только для дочернего сервера)
    Обработка HTTP запросов
  • Освобождение ресурсов перед выходом (главный и дочерние серверы)
Рисунок 4.8 показывает поведение Apache использующего архитектуру prefork более подробно.
Все многозадачные архитектуры отличается друг от друга механизмом создания и организации дочерних процессов. Поведение различных многозадачных архитектур также отличается. Основное отличие находится в процессе создания дочерних процессов (рабочих) в цикле перезагрузки и в главном цикле сервера.

Инициализация и цикл перезагрузки

Инициализация. Серверная структура, показанная на рисунке 4.6, устанавливается при запуске Apache (запуск процессов, создание сокетов и каналов, выделение памяти) и уничтожается по завершению работы сервера. Этот процесс называется активацией и деактивацией.
Существуют три типа инициализации:
  1. Первая активация Apache
  2. Каждый раз при запуске цикла перезагрузки
  3. Каждый раз при создании дочернего сервера
Сервер Apache 2.0 запускается в функции main(). После входа в цикл перезагрузки, он вызывает заданный МП-модуль, используя функцию ap_mpm_run(). (Apache 1.3 запускает prefork архитектуру с помощью процедуры REALMAIN()). Следующие пояснения объясняют операции изображенные на рисунке 4.8:
  • Создание статичных пулов: Apache инициализирует блоки памяти для собственного механизма управления памятью (управление пулами, см. раздел 4.6).
  • Регистрация информации о скомпонованных модулях: большая часть функциональности сервера Apache располагается в модулях (см. раздел 3.3). Модули могут быть либо включены в бинарники Apache, либо подгружены динамически при запуске. Даже если они включены в бинарники (скомпонованы), они все равно должны быть зарегистрированы.
  • Чтение командной строки и установка параметров: администратор может переопределить установки сервера или указать другой конфигурационный файл с помощью параметров командной строки. Так параметр командной строки -X принуждает включить режим одного процесса и может быть использован для отладки сервера. Он предотвращает создание дочерних процессов. Если не создан ни один дочерний процесс, то нет необходимости и в главном сервере, так как один созданный процесс входит в цикл ‘запрос-ответ’ и ведет себя как дочерний сервер.
Рисунок 4.8: Детали поведения Apache
Рисунок 4.8: Детали поведения Apache (Полный рисунок)
  • Чтение серверной конфигурации: главный сервер читает конфигурационные файлы и объединяет информацию с собственными конфигурационными данными. Конфигурационные данные также содержат информацию о загружаемых модулях. Заметьте, что данные конфигурации будут прочитаны второй раз во время цикла перезагрузки! “Серверная конфигурация” объединяет все статичные конфигурационные данные в отличие от данных конфигурации в файлах .htaccess, называемых конфигурацией запроса.
  • graceful_mode := false: в этот момент существует процесс только главного сервера, поэтому нет смысла использовать режим graceful (’мягкой’ перезагрузки). (В этом режиме - см. раздел 4.3.3 - Apache выполняет перезагрузку, оставляя активные дочерние серверы нетронутыми).
  • Отсоединение процесса: каждый процесс обычно является дочерним процесса, который его создал. Родительский процесс, например, может быть процессом командной оболочки. Если оболочка завершает работу, то все дочерние процессы оболочки также завершаются. К тому же, все входящие и исходящие потоки дочернего процесса (STDIN, STDOUT, STDERR) присоединяются к оболочке.Apache выполняет отсоединение после того, как он считал данные конфигурации и попытался инициализировать модули. После отсоединения ни одно сообщение об ошибке не выводится в оболочке, потому что главный сервер отсоединился от нее и начал исполнятся в качестве фоновой задачи.
    Процесс отсоединения состоит из следующих действий:
    1. Создание клона текущего процесса, используя функцию fork().
    2. Немедленное прекращение родительского процесса.
    3. Копирование отсоединенных от оболочки входных и выходных потоков.
    4. Клон устанавливает свой group ID в group ID процесса с номером 1 (init). Это запрещает любые связи с настоящими родительскими процессами и с этого момента он только зависит от процесса системной инициализации.
Режим одного процесса полезен для отладки. Apache пропускает операцию отсоединения от оболочки и остается доступным для отладчика.
Цикл перезагрузки. Каждый раз, когда администратор вызывает перезагрузку сервера, он запускает цикл перезагрузки, который находится в функции main() (в Apache 1.3 цикл перезагрузки расположен в процедуре standalone_main()). После чтения конфигурации, сервер вызывает функцию ap_mpm_run МП-модуля prefork.
Этот цикл содержит следующие части:
  1. Инициализация и подготовка ресурсов для новых дочерних серверов, чтение и обработка файлов конфигурации.
  2. Создание дочерних серверов.
  3. Главный сервер: наблюдение за дочерними серверами (Главный цикл сервера, см. раздел 4.3.3).
    Дочерние серверы: обработка HTTP запросов (Цикл ‘запрос-ответ’, см. раздел 4.4).
  4. Завершение дочерних серверов (’мягкая’ перезагрузка: завершение только приостановленных дочерних серверов).
Конфигурационные файлы читаются только главным сервером. Дочерние сервера получают свои конфигурационные данные при создании их главным сервером. Если администратор хочет применить изменение конфигурации для сервера, то он вызывает перезагрузку. ‘Мягкая’ перезагрузка позволяет дочерним процессам завершить обработку текущих запросов перед тем, как они будут заменены процессами нового поколения. Каждый дочерний сервер обновляет свой статус в специальной таблице (общая область памяти) и сравнивает свой собственный ID поколения с глобальным ID поколения всякий раз, когда он завершает обработку запроса.
  • Чтение серверной конфигурации: главный сервер читает и обрабатывает конфигурационные файлы. В это время существует только главный сервер (также может быть несколько рабочих дочерних серверов прошлого поколения).
  • Установка сокетов сервера на прослушивание: Apache может прослушивать несколько портов. Важно, чтобы при перезагрузке серверные порты не закрывались.
  • Инициализация таблицы серверов: В случае ‘мягкой’ перезагрузки, записи таблицы указывают дочерним серверам, чтобы они не завершались. В случае, когда таблица не содержит записей о дочерних серверах, она инициализируется.
  • Режим одного процесса: Этот режим используется для отладки. Главный сервер становится дочерним сервером и входит в цикл ‘запрос-ответ’.
  • Запуск дочерних серверов и регистрация их в таблице: Главный сервер создает дочерние серверные процессы с помощью процедуры startup_children(). Для этого используется вызов системной функции fork(). Как следствие, все дочерние процессы получают копию памяти главного сервера и его системных ресурсов. Следовательно, они знают конфигурационные данные и имеют доступ к TCP/IP сокетам и лог-файлам.
    Если Apache запускается супер пользователем (root), главный серверный процесс является единственным процессом использующий User ID - root. Дочерние процессы, запускаясь, устанавливают свои User ID со значением непривилегированной учетной записи, как, например, “nobody” или “wwwrun” и входят в цикл ‘запрос-ответ’. Главный сервер создает запись в таблице для каждого дочернего сервера, включающая ID процесса и ID поколения.
  • restart/shutdown_pending := false: Главный сервер входит в главный цикл сервера. Он выходит из этого цикла, только если одна из этих глобальных переменных устанавливается в true обработчиком сигналов.
  • Главный цикл сервера (см. раздел 4.3.3 и рисунок 4.9): В начале цикла главный сервер либо приостанавливается на определенное время, либо получает уведомление, что дочерний сервер завершился. Затем он подсчитывает количество свободных дочерних процессов и регулирует их число, создавая или завершая дочерние процессы.
  • Создание нового поколения: Каждый раз, когда главный сервер выполняет цикл перезагрузки, он увеличивает значение ID поколения. Все дочерние сервера, которые он создает, имеют это значение ID поколения в таблице дочерних серверов. Когда же дочерний сервер завершает обработку запроса, он сверяет свой ID поколения со значением глобального ID поколения. Если они не совпадают, он выходит из цикла ‘запрос-ответ’ и завершается. Такое поведение необходимо для ‘мягкой’ перезагрузки.
  • Завершение свободных/всех дочерних процессов: И завершение работы сервера, и перезагрузка в результате приводят к завершению всех дочерних серверов. Когда администратор выполняет ‘мягкую’ перезагрузку, завершаются только свободные дочерние процессы.
  • Освобождение ресурсов: Apache освобождает занятые ресурсы: память, TCP/IP порты и файловые указатели.

Межпроцессное взаимодействие (Сигналы и канал ‘смерти’ (Pipe of Death))

Apache управляется сигналами. Сигналы - это вид программных прерываний. Они могут происходить в любое время выполнения программы. Процессор приостанавливает нормальное выполнение программы и выполняет процедуру обработки сигнала. Если в текущей программе не определена такая процедура, то используется стандартный обработчик, который обычно завершает программу. После выполнения процедуры обработки сигнала процессор продолжает нормальное выполнение, за исключением случая, когда программа была завершена сигналом.
Управлением главного сервера занимается администратор. Администратор может посылать сигналы напрямую (используя kill в командной оболочке) или с помощью скриптов. Главный сервер обрабатывает три сигнала:
  • SIGTERM: завершение работы сервера (установка shutdown_pending := true).
  • SIGHUP: перезагрузка сервера (установка restart_pending := true и graceful_mode := false).
  • SIGUSR1: ‘мягкая’ перезагрузка сервера (установка restart_pending := true и graceful_mode := true).
Обработчики сигналов главного сервера регистрируются в процедуре set_signals(). Она регистрирует следующие функции обработки сигналов: sig_term() и restart().
В верхнем правом углу рисунка 4.8 находится небольшая сеть Петри, описывающая поведение обработчика сигналов главного сервера. Apache активирует и деактивирует обработку сигналов в определенных местах во время инициализации и во время цикла перезагрузки. Это не показано на рисунке 4.8.
Главный сервер управляет дочерними серверами. Администратор может управлять главным сервером только с помощью сигналов, а главный сервер для управления количеством дочерних серверов использует либо сигналы, либо канал ‘смерти’ (Apache 1.3 использует только сигналы).
Для завершения работы или перезагрузки (не ‘мягкой’) главный сервер посылает сигнал SIGHUP процессной группе. Операционная система распределяет сигналы для всех дочерних процессов, принадлежащих данной группе (все дочерние процессы, созданные главным серверным процессом). После этого главный сервер получает уведомление о завершении всех дочерних серверов. Если не все дочерние процессы завершились, то главный сервер повторяет попытки завершить процессы.
‘Мягкая’ перезагрузка влияет сперва на простаивающие дочерние процессы. Apache 1.3 посылает сигнал SUGUSR1 процессной группе, а Apache 2.0 посылает ‘символы смерти (”Char of Death” items) в ‘канал смерти’.

Таблица 4.1: Нормальная и ‘мягкая’ перезагрузка
нормальная перезагрузка ‘мягкая’ перезагрузка
посылка SIGHUP процессной группе использование ‘канала смерти’ для завершения простаивающих дочерних серверов (Apache 1.3 посылает SIGUSR1 процессной группе)
все дочерние сервера завершаются все простаивающие дочерние сервера получают ‘символ смерти’ через ‘канал смерти’ и завершаются, а занятые дочерние сервера проверяют ID поколения в таблице, устанавливают die_now:=true и позже завершаются. (Apache 1.3: Простаивающие процессы завершаются, а занятые устанавливают deferred_die:= true и позже завершаются)
получение от всех дочерних процессов уведомления о завершении - (см. главный цикл сервера)
инициализация таблицы сохранение таблицы
запуск дочерних серверов -
главный цикл сервера: нормальное функционирование главный цикл сервера: создание дочернего сервера при каждом уведомлении о завершении
Рабочие дочерние серверы проверяют ‘канал смерти’ после обработки запроса и перед проверкой своего ID поколения. В обоих случаях они устанавливают флаг die_now и завершаются перед началом новой итерации в цикле ‘запрос-ответ’. Таблица 4.1. показывает различия между нормальной и ‘мягкой’ перезагрузкой.
‘Канал смерти’ (PoD). Главный сервер в Apache 2.0 использует ‘канал смерти’ в межпроцессном взаимодействии с дочерними серверами для завершения лишних процессов и при ‘мягкой’ перезагрузке. Все дочерние сервера одного поколения используют один канал.
Главный сервер ставит ‘символ смерти’ в очередь, используя ap_mpm_pod_signal() или посылает ‘CoD’ всем дочерним процессам с помощью ap_mpm_pod_killpg(). Эти процедуры также создают запрос на соединение на прослушиваемый порт, используя процедуру dummy_connection() и немедленно завершают соединение. Дочерний сервер ожидает новых входящих запросов на соединение (прослушиватель), принимает запрос и пропускает обработку запроса, как будто соединение завершается клиентом. После этого сервер проверяет ‘PoD’, который заставляет его завершиться. Занятые дочерние сервера могут продолжать обработку их текущего соединения без остановки.

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
Опубликовано в: Архитектура Март 5, 2006

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

  1. Отличная статья ! Достойное продолжение!!! ОЧЕНЬ РАД что существует такой сайт! РЕСПЕКТ
    _____________________
    http://ne-kurim.ru/

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

  2. >> Поведение сервера показано на рисунке 4.4. Система вызывает accept() или select>> >> (), блокируя главный серверный процесс, пока не поступит запрос. accept() ожидает >> запросов на один серверный порт, тогда как select() прослушивает сразу несколько >> портов.
    В данном случае явно опечатка. не accept() и select(), a listen() и select(). Тогда как accept() ничего не слушает, а лишь отвечает за установление соединения.

    Комментарий от verm666 — Февраль 2, 2009 @ 11:52 pm

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

You must be logged in to post a comment.

Работает на WordPress