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


Главный цикл сервера

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

Рисунок 4.9: Главный серверный цикл
Рисунок 4.9: Главный серверный цикл (Полный рисунок)
Цикл перезагрузки находится внутри ядра сервера в функции main(), а главный цикл сервера расположен внутри соответствующего МП-модуля (для prefork находится в функции ap_mpm_run()). (В apache 1.3 он находится в процедуре standalone_main() в файле http_main.c)

На рисунке 4.9 этот цикл изображен более детально. Верхняя часть рисунка отвечает за реакцию при завершении дочернего процесса и за специальные действия при ‘мягкой’ перезагрузке. Нижняя часть называется “обработка простоя сервера”. На ней изображен цикл, внутри которого главный сервер подсчитывает количество простаивающих дочерних серверов и получает список свободных строк в таблице. Он сравнивает количество простаивающих серверов (idle_count) с ограничениями, установленными в конфигурации (ap_deamons_max_free и ap_daemons_min_free). Если простаивающих серверов слишком много, то он завершает один из них (последний простаивающий процесс в таблице). А если количество простаивающих серверов слишком мало, тогда главный сервер создает столько дочерних серверов, сколько необходимо для достижения нижнего лимита (см. режим ниже).
‘Мягкая’ перезагрузка. Реакция на завершение дочерних серверов. По этому вопросу дадим следующие пояснения:
  • Установка rem.child2start: Переменная remaining_children_to_start используется только в случае ‘мягкой’ перезагрузки. Она хранит количество серверов, которое необходимо запустить после перезагрузки. Обратите внимание, что главный сервер не использует процедуру startup_children. Пока выполняется вызов функции wait(), главный сервер получает уведомления от каждого простаивающего дочернего сервера, которые он завершил. Так как начальное количество могло быть изменено в конфигурации, то его нельзя использовать при создании новых дочерних серверов, поэтому главный сервер для контроля количества использует переменную remainig_children_to_start.
  • pid := wait или timeout: Вызов системной функции wait() используется для ожидания завершения дочернего процесса, созданного с помощью функции fork(). После истечения заданного интервала времени, главный сервер продолжает выполнение главного цикла сервера, даже если он не получил уведомление о завершении.
  • wait() выполнилось успешно (pid установлен):
    • process_child_status: Обработка причины завершения дочернего процесса.
    • find_child_by_pid: Поиск дочернего сервера в таблице серверов.
    • сервер найден: установка статуса сервера в SERVER DEAD. Если remaining_children_to_start не нулевое, создать новый дочерний сервер для замены завершенного.
    • сервер не найден: Проверить, не является ли данный дочерний процесс “другим” (reap_other_child(), см. ниже). Если ни в “других” процессах, ни в таблице процесс не был найден и если установлен ‘мягкий’ режим перезагрузки, тогда должна произойти следующая ситуация:
      Администратор уменьшает количество разрешенных дочерних серверов и выполняет ‘мягкую’ перезагрузку. Этот дочерний процесс теперь превышает допустимые пределы процессов. Он завершается, без внесения записи в таблицу.
  • time-out: Если после восстановления всех завершенных процессов remaining_children_to_start не равно нулю, то создаются дополнительные дочерние серверы. Это делается с помощью процедуры startup_children().
Обработка простоя сервера. Нижняя часть рисунка 4.9 показывает работу процедуры perform_idle_server_maintenance(), которая вызывается всякий раз после истечения тайм-аута и по завершению ‘мягкой’ перезагрузки.
Главный сервер подсчитывает число простаивающих серверов и количество записей в таблице и сравнивает их с тремя ограничениями, установленными в конфигурации:
ap_daemons_limit - максимальное число дочерних серверов. Сумма рабочих и простаивающих дочерних серверов и свободных строк или только количество строк в таблице.
ap_daemons_max_free - максимальное число простаивающих дочерних серверов. Если количество простаивающих серверов слишком высоко, один дочерний сервер удаляется в каждом цикле.
ap_daemons_min_free - минимальное количество простаивающих дочерних серверов. Если количество простаивающих серверов слишком мало, главный сервер создает новые дочерние серверы. Если не осталось свободных строк в таблице (так как достигнут ap_daemons_limit), в лог-файл пишется предупреждение.
Экспоненциальный режим: Некоторые операционные системы могут сильно снизить производительность, если в короткий период будут созданы слишком много дочерних процессов. Поэтому главный сервер не создает за раз требуемое количество дочерних серверов процедурой make_child(). Он создает один сервер в первом цикле, два - во втором, 4 - в третьем и т.д. В переменной idle_spawn_rate хранится количество дочерних серверов, которые необходимо создать в следующем цикле. Значение этой переменной увеличивается каждый раз, пока количество созданных дочерних серверов не превышает верхнего предела.
Пример: ap_daemons_min_free имеет значение 5, но остается только 1 простаивающий сервер. Главный сервер создает один дочерний сервер при первом проходе. Два свободных дочерних сервера все еще недостаточно, поэтому главный сервер создает еще 2 сервера и снова ждет. Тем временем, новый запрос забирает один из простаивающих дочерних серверов. Теперь остается только 3 свободных дочерних сервера, и главный сервер создает еще 4. После тайм-аута он находит 7 свободных серверов и сбрасывает idle_spawn_rate в 1.

Дочерние сервера (рабочие)

Рабочий режим дочерних серверов является сердцем HTTP сервера, так как он предназначен для обработки запросов. Многозадачная архитектура не отвечает за обработку запросов, она предназначена для создания дочерних серверов, их инициализации и обработки, а также передачи им входящих соединений.
Инициализация, конфигурация и перезагрузка сервера. Главный сервер создает дочерние серверные процессы, используя вызов системной функции fork(). Процессы имеют отдельную память, которая недоступна для чтения и записи другим процессам. Конфигурация обрабатывается один раз главным сервером, а не каждым дочерним сервером отдельно. Поэтому конфигурация должна быть сохранена в общей памяти, которая доступна для чтения каждому дочернему серверному процессу. Так как не каждая платформа предоставляет разделяемую память, поэтому главный сервер обрабатывает конфигурационные файлы перед тем, как он создает дочерние процессы. Дочерние серверные процессы копируют главный процесс и поэтому обладают такими же конфигурационными данными, которые они больше не изменяют.
Каждый раз, когда администратор хочет применить изменения в серверной конфигурации, он заставляет главный сервер перечитать и обработать новые конфигурационные данные. Созданные дочерние процессы обладают старой конфигурацией и должны быть заменены новыми процессами. Для избежания прерывания обработки HTTP запросов, Apache предоставляет режим ‘мягкой’ перезагрузки (см. раздел 4.3.3), который позволяет дочерним серверам использовать старую конфигурацию до тех пор, пока они не завершат обрабатывать свои запросы.
Инициализация дочернего сервера находится в соответствующем МП-модуле (Prefork: child_main(). Apache 1.3: child_main()). Она состоит из следующих шагов (см. также рисунок 4.13):
  • Установка доступа к ресурсам: Дочерний процесс только что создан главным сервером с помощью вызова fork(). В это время дочерний процесс имеет те же права, что и главный. Это наиболее важно, если Apache был запущен супер пользователем (root). Перед тем как дочерний сервер установит свой User ID в непривилегированный статус, он должен получить доступ к общим ресурсам:
    • Собственная память (ap_make_sub_pool())
    • Таблица серверов (может быть реализована как общая память или как файл)
    • Разрешающий семафор (зависит от реализации)
  • Переинициализировать модули (ap_init_child_modules()): Каждый модуль ранее был инициализирован главным сервером. Новая инициализация необходима, если модулю требуется получить системные ресурсы или он зависит от ID процесса (например, для соединения с БД).
  • Установка обработки тайм-аута: Для избежания бесконечного блокирования дочернего сервера при обработке запросов Apache использует тайм-ауты. Для реализации тайм-аутов сервер использует ‘предупреждения’ - сущности, наподобие сигналов. Это похоже на установку будильника на определенное время - когда будильник сработает, обработка запроса останавливается.
  • Внутри цикла, существуют два этапа инициализации:
    • Очистка тайм-аута: сброс таймера.
    • Очистка временных пулов: Любая память, выделенная внутри цикла ‘запрос-ответ’ помещается во временный пул. В начале цикла пул очищается.
  • Установка поля status в таблице в значение ready, за исключением ситуации после объявления нового поколения.
Установка соединений. Архитектура prefork использует разрешающий семафор для распределения входящих соединений между дочерними серверами. Разрешающий семафор позволяет быть уверенным в том, что только один дочерний процесс ожидает TCP запроса (используя системную функцию accept()) - т. е выполняет роль прослушивателя. Разрешающий семафор управляет доступом к сервису TCP/IP. Он используется для гарантии того, что в любое время, только один процесс ожидает запроса на TCP/IP соединение.
Для различных операционных систем существуют различные реализации разрешающего семафора. В некоторых системах необходима специальная фаза инициализации для каждого дочернего сервера. Вот как она выглядит:
  • Вызов процедуры accept_mutex_on(): получение семафора или блокировка процесса пока семафор недоступен.
  • Вызов процедуры accept_mutex_off(): освобождение семафора.
После получения соединения, дочерний сервер освобождает разрешающий семафор и обрабатывает запрос - он становиться рабочим, это позволяет следующему процессу ожидать новый запрос. Обычно это называется шаблон ‘Лидер - последователи’: прослушиватель - лидер, простаивающие процессы - последователи (см. рисунок 4.5). Так как Apache использует технику семафоров, зависимую от операционной системы, то возможна такая ситуация, что все заблокированные дочерние серверы ‘проснутся’, когда один из дочерних серверов после получения соединения вернет семафор. Такое поведение не самое оптимальное, так как после того, как один из ‘разбуженных’ дочерних серверов получит семафор, другие вновь будут заблокированы и начнут простаивать. Эта проблема решается с помощью МП-модуля Leader, где последователи организованны таким образом, что только один из них разблокируется при возвращении разрешающего семафора.
Область ответственности многозадачной архитектуры заканчивается после того, как дочерний сервер получает соединение. Далее дочерний сервер вызывает шаблон обработки запросов, который одинаков для любой многозадачной архитектуры.
Разрешающий семафор и select(). В сервере inetd (см. раздел 4.3.1) только один процесс ожидал запроса на TCP/IP соединение. Внутри сервера Apache, вполне возможна ситуация, когда сотни простаивающих дочерних серверов одновременно ожидают запроса на соединение на более чем одном порту. На некоторых операционных системах это может привести к серьезным проблемам.
Пример: Apache сконфигурирован для прослушивания портов 80, 1080 и 8080. 10 простаивающих дочерних процессов ожидают входящих TCP/IP соединений, используя систему блокировки, вызывая select() (они неактивны, пока не поменяется статус одного из портов). Поступает запрос на соединение на порт 1080. 10 дочерних процессов ‘просыпаются’, проверяют порт, который их ‘разбудил’ и пытаются установить соединение с помощью функции accept(). Один из них делает это успешно и начинает обрабатывать запрос, а остальные 9 продолжают ожидать соединений на порте 1080 и не одного на 80 и 8080 портах! (Этот наихудший сценарий возможен только при блокирующей accept()).
Следовательно, в сценарии, где множество дочерних серверов прослушивают множество портов, связка select() - accept() не достаточна для реализации взаимного исключения между множеством процессов. Следовательно, в архитектуре prefork необходимо использовать разрешающий семафор.
Вообще, расходовать ресурсы операционной системы для обработки совместной работы является не самой лучшей идеей. Так как некоторые операционные системы не могут создавать очередь дочерних процессов, ожидающих запрос на соединение, то Apache сам реализует этот механизм.

4.3.4 Многозадачные архитектуры Apache и МП-модули

Главная задача многопроцессой архитектуры - это предоставить быстрый сервер, который оптимально использует возможности операционной системы. Почти каждая многозадачная архитектура выбирает между стабильностью работы и производительностью.
В случае с HTTP сервером, многозадачная архитектура определяет стратегию создания и управления рабочими задачами, а также получения ими запросов для обработки.
Первый аспект - это задачи: в зависимости от платформы, для реализации задач сервер может использовать процессы или нити, или и то и другое. Процессы имеют больший контекст (например, память процесса), который влияет на время, необходимое на переключение между процессами. Нити более ‘легки’, потому что они используют большую часть контекста совместно, но, к сожалению, некачественный код может испортить данные других нитей или, что еще более хуже, ‘обрушить’ все нити процесса.
Следующий аспект - это взаимодействие задач (межзадачное взаимодействие). В общем случае, это может быть сделано с помощью общей памяти, сигналов или событий, семафоров или каналов.
Так как все МП-модули используют стратегию пула задач, необходимо чтобы все неактивные задачи были приостановлены, а при поступлении запроса один из них должен быть разбужен. Для этого используется механизм операционной системы, например, условная переменная или семафор.
Серверные сокеты - ресурс ограниченный, следовательно, должен существовать только один прослушиватель на сокет, либо один прослушиватель на все сокеты. Для этого назначаются прослушивающие задачи, которые передают данные запроса рабочим задачам, или все серверные задачи играют обе роли: простаивающий рабочий процесс сперва становится прослушивателем, потом получает запрос и становится рабочим процессом, обрабатывающим запрос.
Последний аспект - это контролирование пула задач, путем удерживания числа простаивающих задач внутри заданного интервала.
Apache включает различные многозадачные архитектуры. Первоначально Apache использовал различные архитектуры только для поддержки разных операционных систем. Apache 1.3 имеет две главные архитектуры, которые задаются во время сборки сервера, используя переменные окружения. Эти переменные используются перед компиляцией для выполнения макросов, которые возвращают выбранные участки кода для используемой операционной системы:
  • Архитектура prefork для UNIX.
  • Архитектура ‘Очередь заданий’ для Windows.
Полностью многопроцессная реализация появилась в Apache версии 2.0, после введения МП-модулей. Эти модули являются взаимозаменяемыми и полностью содержат в себе мультипроцессную архитектуру. Структура МП-модуля такая же, как и структура стандартного модуля. МП-модули не могут быть динамически включены в сервер, и поэтому задаются при компиляции сервера из исходников. В соответствии с природой многозадачной архитектуры, только один МП-модуль может использоваться в сервере в некоторый момент времени.
Ответственность МП-модуля распространяется на главные циклы Apache. Перед вызовом процедуры ap_mpm_run(), используемой для передачи управления МП-модулю, главный сервер полностью производит инициализацию и обработку конфигурации.
Рисунок 4.10: Зона ответственности МП-модуля в Apache 2.0
Рисунок 4.10: Зона ответственности МП-модуля в Apache 2.0 (Полный рисунок)
МП-модуль отвечает за старт нитей и/или процессов. МП-модуль также ответственен за прослушивание сокетов сервера. При поступлении запросов, МП-модуль распределяет их между созданными нитями и/или процессами. После этого они выполняют стандартные процедуры обработки запросов. При перезагрузки или завершении работы сервера, МП-модуль возвращает управление главному серверу. Так как вся серверная функциональность одинакова для любого МП-модуля, то мультипроцессный модуль заменяем. Рисунок 4.10 показывает зону ответственности МП-модуля Apache (см. также рисунок 4.7). Пунктирная линия выделяет этапы, за которые отвечает МП-модуль.
Версия Apache 2.0 включает следующие МП-модули:
  • Prefork и Netware - МП-модули, имеющие функциональность архитектуры prefork в Apache 1.3.
  • WinNT - похож на Apache 1.3 для Win32, однако, МП-модуль WinNT расширен за счет концепции операционной системы - IOCP.
  • Worker - новый МП-модуль, который заставляет использовать и процессы, и нити, и делает это лучше, чем в prefork.
  • Leader и PerChild - два МП-модуля до сих пор находящиеся в статусе экспериментальных, как альтернатива prefork и Worker для систем, основанных на Linux.

4.3.5 МП-модули Win32/WinNT

Многозадачная архитектура для Windows имеет несколько серьезных отличий от архитектуры prefork. Она использует нити вместо процессов и количество дочерних серверов не переменное, а постоянное. Используются именно нити, потому что они гораздо производительней процессов Windows. В этой многозадачной архитектуре существуют два процесса: рабочий процесс (процесс дочернего сервера), состоящий из нитей, которые обрабатывают HTTP запросы и главный процесс, который следит за тем, чтобы рабочий процесс работал корректно. Для распределения соединений между рабочими процессами используется очередь заданий. На платформе Windows NT МП-модуль Apache 2.0 вместо очереди заданий использует концепцию Windows NT названную ‘завершающий порт ввода/вывода’ (IOCP). Эта архитектура для Apache 1.3, также как и Win32-версия Apache 2.0, для получения соединений использует одну прослушивающую нить. МП-модуль для Windows NT использует по одному прослушивателю на каждый порт, который слушает сервер.
Рисунок 4.11 показывает структуру сервера, использующую МП-модуль WinNT: Главный процесс сервера создает дочерний серверный процесс, а затем следит за его работой.

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

Процедура инициализации в многозадачной архитектуре Win32 сильно походит на описанную выше в архитектуре prefork. Все шаги инициализации одинаковы до того момента, где вызывается МП-модуль prefork или где сервер (Apache 1.3) начинает создавать дочерние процессы.
Обе версии (1.3 и 2.0) используют главный процесс сервера в качестве контролирующего процесса. Также он создает второй процесс, который содержит все рабочие нити. Когда рабочий процесс стартует, он содержит только одну главную нить, которая затем порождает фиксированное число рабочих нитей. Они соответствуют дочерним серверам в архитектуре prefork. Версия многозадачной архитектуры для Windows использует фиксированное количество нитей для улучшения производительности. Поэтому то количество нитей, которое выбрано для оптимальной производительности стартуют немедленно. Теперь сервер может использовать свои максимальные возможности без дополнительных нагрузок при динамическом создании новых процессов. Обе многозадачные архитектуры Windows поддерживают только ‘мягкую’ перезагрузку или завершение.

Межпроцессное/нитивое взаимодействие (события и ‘Флаг завершения’)

В этой многозадачной архитектуре используются разнообразные механизмы межпроцессного взаимодействия. Так как Windows не поддерживает сигналы, то для взаимодействия между главным процессом сервера и рабочими процессами используется концепция Windows - события.
Рисунок 4.11: Обработка запросов
Рисунок 4.11: МП-модуль WinNT сервера Apache 2.0 (Полный рисунок)
Сигнализация использует следующие события:
  • Главный процесс сервера сигнализирует рабочему процессу, что происходит ‘мягкая’ перезагрузка или остановка сервера.
  • Рабочие процессы могут сигнализировать главному процессу, что они нуждаются в перезагрузке или, что произошла серьезная ошибка, которая требует перезагрузки сервера.
Рабочий процесс также использует различные средства для взаимодействия с прослушивателями и рабочими нитями. При остановке сервера главная нить отправляет “мертвые” задания в очередь заданий или использует IOCP. Тем самым, приостанавливая рабочие нити, а те рабочие нити, которые заняты обработкой запроса, завершают обработку запроса и после этого завершаются сами.
Очередь заданий/IOCP также используются прослушивателями для передачи поступающих соединений рабочим нитям для обработки запросов.

Главный процесс сервера

Главный процесс сервера при входе в цикл перезагрузки называется контролирующим процессом. Он содержит только одну нить и используется для наблюдения за вторым процессом (рабочим) для возможности перезагрузки в случае возникновения ошибок. Пользователь может взаимодействовать с этим специальным процессом, используя утилиту, имеющуюся в Windows. Эта утилита посылает события серверу, которые сигнализируют ‘перезагрузку’ или остановку сервера. Также Apache использует параметры командной строки, которые также могут быть использованы для сигнализирования.

Дочерний процесс: Прослушиватели и очередь заданий

Рабочий процесс содержит три вида нитей: Одну главную нить, фиксированное число рабочих нитей и одну или несколько прослушивающих нитей. Главная нить создает одну или несколько прослушивающих нитей, которые принимают запросы на соединения и отправляют данные соединений в очередь заданий. Рабочие нити получают данные соединений из очереди, и затем получают и обрабатывают запросы при помощи функций ядра обработки запросов, которое используется всеми многозадачными архитектурами. Взаимодействие между главной и рабочими нитями также происходит через очередь заданий. Если главная нить захочет уменьшить количество рабочих нитей при завершении или ‘перезагрузке’ - она отправляет в очередь ‘мертвые’ работы.
Вместо очереди заданий, МП-модуль версии 2.0 для Windows NT платформ использует IOCP. Преимущество IOCP заключается в том, что он позволяет серверу определять верхнюю границу активных нитей. Все рабочие нити регистрируются для IOCP и приостанавливаются, если зарегистрированы в очереди заданий. При возникновении любого события, IOCP отвечает за ‘пробуждение’ одной рабочей нити для обработки этого события (в Apache это может быть только новый входящий запрос на соединение). Однако если граница активных нитей будет превышена, нити не будут активизироваться для обработки новых запросов, пока другой блок нитей не будет перерегистрирован для IOCP. Эта техника используется для предотвращения чрезмерного переключения контекста большого числа активных нитей.

Дочерний процесс: рабочие нити

В данной модели архитектуры рабочие нити достаточно просты. Так как они могут использовать любые данные родительского процесса (рабочего процесса), они не нуждаются в инициализации большого объема данных. Все что им необходимо поддерживать - это счетчик запросов, которые обработала нить. А в версии с МП-модулем также хранится переменная, содержащая версию текущей операционной системы, в зависимости от которой, при поступлении соединения, выбирается либо очередь заданий, либо IOCP. Как видите процесс инициализации очень короткий.
После инициализации рабочие нити, для получения соединения, регистрируются для IOCP или очереди заданий. После получения соединения, нить вызывает функции ядра обработки запросов. Этот цикл продолжается до тех пор, пока нить не получит ‘мертвую’ работу из очереди, что приведет к ее завершению.

4.3.6 МП-модуль Worker

МП-модуль Worker - это многопроцессная модель для операционных систем Linux/Unix. В отличие от моделей Prefork и WinNT, данный МП-модуль использует сочетание многопроцессной и многонитиевой модели: Он использует переменное число процессов, которые включают фиксированное число нитей (см. рисунок 4.12). Модель prefork на уровне процессов расширяется с помощью очереди заданий на уровне нитей.
Рисунок 4.12: МП-модуль Worker сервера Apache 2.0
Рисунок 4.12: МП-модуль Worker сервера Apache 2.0 (Полный рисунок)
Главный процесс сервера управляет количеством простаивающих процессов внутри заданного диапазона, основываясь на загруженности сервера и на директивах конфигурации: max_child, max_idle и min_idle. Каждый дочерний процесс включает нить прослушивания, которая прослушивает все используемые сервером порты. Избежание одновременного множественного использования процессов, а следовательно и множества прослушивающих нитей, происходит за счет использования разрешающего семафора, как и в архитектуре prefork.

Дочерний сервер (рабочий)

В данной архитектуре инициализация дочернего сервера является более сложной задачей, так как он обладает более сложной структурой. Сперва главный сервер создает дочерний процесс, который в свою очередь создает “запускающую” нить, которая создает все рабочие нити и одну прослушивающую нить. Это поведение отражено на рисунке 4.12.
Внутри каждого дочернего процесса, взаимодействие между прослушивателем и всеми рабочими нитями организовано с помощью двух очередей, очередью заданий и очередью простоя. Нить прослушивателя применяется только при разрешающем семафоре, если в очереди простоя есть токен, показывающий, что, по крайней мере, одна свободная рабочая нить ожидает обработки запроса. Если прослушиватель получает семафор, он ожидает поступление нового запроса, а после поступления оного передает данные о запросе в очередь, после чего освобождает разрешающий семафор. Таким образом, это дает гарантию, что входящий запрос будет обслужен немедленно.
После завершения обработки запроса или соединения со множеством запросов (см. раздел 2.3.4), рабочая нить обозначается как свободная, путем положения токена в очередь простоя, и вновь начинает ожидать новых запросов в очереди заданий.
Достоинствами этого подхода является то, что он совмещает стабильную концепцию многопроцессности и более производительную концепцию многонитеевости. В случае возникновения ошибки, она отразится только на одном процессе. А в многонитеевой модели ошибка в нити может повлиять на все нити, относящиеся к этому родительскому процессу. Однако нити гораздо более легковесны и поэтому требуют меньше ресурсов при запуске и используют меньше памяти при работе.

4.3.7 Другие МП-модули

Упомянутые выше МП-модули используются наиболее часто. Дополнительно существует еще несколько МП-модулей. Однако большинство из них находятся в стадии экспериментов и редко используются в производственных целях.

МП-модуль Leader

Этот МП-модуль использует модель prefork (’Лидер - последователи’, см. рисунок 4.5) на обоих уровнях: и на процессном, и на нитевом. Также используется сложный механизм для работы с очередью последователей.
Как в МП-модуле Worker, каждый дочерний процесс имеет фиксированное количество нитей. Однако нити не разделяются на рабочие и на прослушивающие. Свободные нити помещаются в стек. Самая верхняя нить делается прослушивателем и, как только получит соединение, сразу же становится рабочей, обрабатывающей это соединение. Нить в стеке, следующая за ней, становится новым прослушивателем и обрабатывает следующий запрос. После завершения запроса рабочая нить возвращается на вершину стека.
Данный подход имеет два плюса в производительности. Первый - отсутствие задержки при обработке соединения различными задачами, так как каждая нить просто обрабатывает соединение, которое она получила. И второе, так как нити организованны в стек, только одна нить ‘пробуждается’, когда место прослушивателя становиться свободным.
Нить, возвращенная в стек, помещается на его вершину. Очевидно, что нить, находящаяся на вершине, обработает больше запросов, чем нить внизу стека. Это происходит по аналогии со страничной техникой виртуальной памяти, используемой в большинстве операционных системах, где вероятность страницы памяти быть записанной на жесткий диск понижается тем больше, чем чаще ее используют.

МП-модуль Per-Child

Основанный на МП-модуле Worker, экспериментальный МП-модуль Per-Child использует фиксированное количество процессов, которые используют переменное количество нитей. Этот МП-модуль также использует модель prefork как на процессном уровне, так и на нитевом. Достоинство данного подхода в том, что новые процессы не запускаются или не завершаются при различной нагрузке.
Достоинство этого МП-модуля: Каждый процесс имеет отдельный UserID, который связан с различными правами выполнения программ и доступа к файлам. Это используется для реализации виртуальных хостов с различными правами для множества пользователей. Каждый виртуальный хост должен иметь свой собственный процесс, который наделяется правами, соответствующими правам его пользователя, но при этом у сервера остается возможность реагировать на изменения нагрузки на сервер с помощью создания или удаления рабочих нитей.

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

1 комментарий »

  1. Слов нет! Статья такую еще поискать надо!!!
    СУПЕР!
    _________________________
    http://truemaika.ru/

    Комментарий от андрюха — Сентябрь 2, 2008 @ 4:04 pm

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

You must be logged in to post a comment.

Работает на WordPress