Nginx

Материал из support.qbpro.ru

Глава 14 из книги "Архитектура приложений с открытым исходным кодом", том 2.

Оригинал: The Architecture of Open Source Applications: nginx

Автор: Andrew Alexeev,

Дата публикации: 17 мая 2012 г.

Перевод: А.Кикоть

Дата перевода: 08 апреля 2013 г.

nginx (произносится, как "engine x") - это web-сервер с открытым исходным кодом, написанный российским разработчиком Игорем Сысоевым. С момента опубликования в 2004 году nginx фокусировался на высокой производительности, высокоэффективных параллельных вычислениях и минимизации использования оперативной памяти. Такие дополняющие функции web-сервера возможности, как балансировка нагрузки, кэширование, контроль доступа, контроль пропускной способности и умение эффективно интегрироваться с различными приложениями позволили nginx стать хорошим выбором для web-сайтов с современной архитектурой. В настоящее время nginx занимает второе место среди самых популярных web-серверов с открытым исходным кодом.

14.1. Почему высокоэффективные параллельные вычисления так важны?

В настоящее время Интернет имеет настолько широкое и повсеместное распространение, что сложно себе представить его отсутствие каких-нибудь десять лет назад. Это результат взрывного развития от перехода по ссылкам между текстами с разметкой HTML, основанных на NCSA, а затем и на web-серверах Apache, до 2 миллардов пользователей по всему миру, находящихся всегда на связи. С широким распространением постоянно подключённых к сети персональных компьютеров, мобильных устройств, а теперь и планшетных компьютеров, облик Интернета быстро меняется и целые экономики становятся цифровыми и проводными. Онлайн-сервисы стали более сложными с явным уклоном в сторону мгновенного доступа к постоянно обновляющейся информации и развлечениям. Вопросы обеспечения безопасного ведения бизнеса в Интернете также сильно изменились. Соответственно, web-сайты сейчас гораздо сложнее, чем раньше, и требуют больше инженерных решений для повышения надёжности и масштабируемости.

Одной из самых больших проблем при выборе архитектуры web-сайта всегда был параллелизм. С момента появления web-сервисов необходимость в одновременном выполнении различных операций постоянно растёт. Необходимость одновременного обслуживания популярными web-сайтами сотен тысяч или даже миллионов пользователей - вовсе не редкость. Десятилетие назад главной причиной параллелизма была медленная скорость клиентов, использующих ADSL- или dial-up-соединения. В настоящее время параллелизм обусловлен сочетанием мобильных клиентов и новой архитектуры приложений, которые обычно основываются на поддержании постоянного подключения, что позволяет клиенту получать свежие новости, твиты, новостные ленты друзей и т.п. Ещё одним важным фактором, приведшим к увеличению важности параллелизма, стало изменение поведения современных браузеров, которые открывают от 4 до 6 соединений к web-сайту для ускорения загрузки страницы.

Чтобы проиллюстрировать проблему медленных клиентов представьте себе простой web-сервер на основе Apache, который генерирует относительно короткий ответ размером 100 КБ - web-страницу с текстом или изображением. Генерация страницы и ответ на запрос могут занять доли секунды, но занимают 10 секунд из-за скорости передачи клиенту, имеющему скорость доступа 80 Кбит/с (10 КБ/с). То есть, web-сервер будет сравнительно быстро подготавливать содержимое страницы в 100 КБ и затем оставаться занятым ещё 10 секунд из-за медленной передачи клиенту. А теперь представьте, что у вас есть 1000 подключённых клиентов, которые одновременно запросили получение аналогичных страниц. Если на каждого клиента выделять всего по 1 МБ оперативной памяти, то это привело бы к необходимости выделения 1000 МБ (около 1 ГБ) оперативной памяти для передачи 100 КБ информации. В реальности, типовой web-сервер на базе Apache обычно выделяет более 1 МБ на одно соединение, а эффективная скорость мобильных клиентов, к сожалению, десятки кбит/с. Ситуация с отправкой информации медленным клиентам может быть в какой-то степени улучшена путём увеличения буферов обмена сокетов ядра операционной системы, но это не универсальное решение и может иметь нежелательные побочные эффекты.

С постоянно поддерживаемыми соединениями проблема параллелизма при обработке становится ещё более выраженной, так как клиенты с целью уменьшения времени на подключение не разрывают ранее установленные соединения и web-сервер вынужден для каждого подключённого клиента резервировать определённый объём памяти.

Следовательно, чтобы справиться с возросшей нагрузкой, связанной с увеличивающейся аудиторией и, как следствие, требованиями к параллелизму, а также справляться с этим и далее, web-сайт должен основываться на ряде очень эффективных "строительных" блоков. Другие части этого уравнения, такие как аппаратная часть (ЦПУ, ОЗУ, НЖМД), пропускная способность сети, системное программное обеспечение и архитектура системы хранения, очень важны, но именно программное обеспечение web-сервера принимает и обрабатывает соединения клиентов. То есть, web-сервер должен быть способен к нелинейному масштабированию с ростом числа одновременных соединений и количества запросов в секунду.

Apache не подходит?

Apache - это доминирующий сейчас в Интернете web-сервер, берущий начало в 1990-х годах. Первоначально его архитектура соответствовала операционным системам и аппаратному обеспечению того времени, соответствовала и состоянию Интернета, где было принято для каждого web-сайта выделять физический сервер с единственным экземпляром Apache. К началу 2000-х годов стало очевидно, что модель с выделенным web-сервером не может удовлетворять растущие потребности web-сервисов. Несмотря на прочную основу для будущего развития, заложенную в Apache, его архитектура предусматривала запуск своей копии для каждого нового соединения, что не подходило для нелинейной масштабируемости web-сайта. В итоге Apache стал web-сервером общего назначения и сосредоточился на увеличении количества разнообразных функций и сторонних расширений для обеспечения универсальной применимости к практически любому виду web-разработки. Однако, за всё необходимо платить: столь богатый и универсальный инструментарий в рамках одной программы снижает её возможности к масштабированию из-за увеличенного использования ЦПУ и памяти на каждое соединение.

Таким образом, аппаратная часть сервера, его операционная система и сетевые ресурсы перестали быть основной проблемой для развития web-сайта, что привело web-разработчиков по всему миру к поиску более эффективных средств организации web-серверов. Около десяти лет назад Daniel Kegel, ведущий разработчик программного обеспечения, объявил, что "настало время, когда web-серверы должны обрабатывать десять тысяч клиентских соединений одновременно" и предложил называть всё это облачными сервисами Интернета. Манифест "C10K" Кегеля (Daniel Kegel) обострил проблему оптимизации web-серверов для одновременной поддержки большого числа клиентских соединений и nginx при таком подходе оказался одним из лучших.

С целью преодоления проблемы C10K в 10'000 одновременных соединений в nginx была заложена другая архитектура, подразумевающая лучшую нелинейную масштабируемость, как по числу поддерживаемых одновременных соединений, так и по числу запросов в секунду. nginx основан на событийно-ориентированной модели (event-based), что позволяет ему не порождать новый процесс или поток для каждого запроса web-страницы, как это делает Apache. В результате возрастание нагрузки стало более равномерным, а использование ресурсов памяти и ЦПУ управляемым. nginx мог теперь обрабатывать десятки тысяч одновременных соединений на сервере с обычной аппаратной частью.

С выходом первой версии nginx стало понятно, что он должен применяться совместно с Apache для выдачи поддерживаемой nginx статической информации вроде HTML, CSS, JavaScript и изображений, что позволяло снизить нагрузку и время отклика серверов приложений на базе Apache. В ходе развития в nginx были добавлены интеграция с приложениями с помощью FastCGI, uswgi или SCGI протоколов и системами распределённого кеширования в оперативной памяти, такими как memcached. Также были добавлены другие полезные функции, такие как обратный прокси-сервер с балансировкой и кешированием. Эти дополнительные возможности превратили nginx в эффективный набор инструментов для построения масштабируемой web-инфраструктуры.

В феврале 2012 года был представлен релиз Apache 2.4.x. Несмотря на добавление в эту версию Apache новых модулей с ядром многопоточной обработки и прокси-сервером, направленными на повышение масштабируемости и производительности, ещё прошло слишком мало времени, чтобы говорить о соизмеримых производительности, параллелизме обработки и экономном использовании ресурсов в сравнении с web-сервером, изначально построенным на событийно-ориентированной модели. Было бы очень приятно увидеть лучшую масштабируемость в новой версии сервера приложений Apache, хотя и не понятно, как это поможет устранить узкие места на серверной стороне в типовых web-конфигурациях nginx + Apache.

Есть ли ещё преимущества при использовании nginx?

Обработка большого количества одновременных запросов с обеспечением высокой производительности и эффективности всегда была ключевым преимуществом при внедрении nginx. Однако, есть и другие не менее интересные преимущества.

В последние несколько лет web-архитекторы восприняли идею удаления зависимостей и отделения инфраструктры приложений от web-сервера. Однако, то, что раньше существовало в виде web-сайта, основанного на LAMP (Linux, Apache, MySQL, PHP или Perl), теперь может не только основываться на LEMP ("E" означает "enginx"), но и всё чаще встречается в виде web-сервера с интегрированной инфраструктурой или на том же наборе приложений и баз данных, но взаимодействующих на иных принципах.

nginx очень хорошо подходит для этого, так как обеспечивает весь необходимый функционал: снижение нагрузки при обработке одновременных запросов, снижение времени отклика, поддержка SSL (Secure Socket Layer), работа со статической информацией, сжатие и кеширование, управление отказом обслуживания соединений и запросов и даже HTTP-потоковое вещание мультимедийной информации - всё это делает nginx более эффективным для применения в качестве первого принимающего запорсы web-сервера. Он также реализует непосредственную интеграцию с memcached/Redis или другими NoSQL-решениями для повышения производительности при одновременной обработке большого количества пользователей.

С появлением и широким распроранением различных языков программирования и комплектов разработчика всё большее и большее количество компаний начинает их применять, что приводит к изменению способов разработки и внедрения. nginx стал одним из наиболее важных компонентов этих меняющихся парадигм и уже помог многим компаниям создать и развивать свои web-сервисы быстро и в рамках запланированных бюджетов.

Первая строка исходного кода nginx была написана в 2002 году. В 2004 году он был выпущен под лицензией "BSD 2-Clause License". С тех пор количество пользователей nginx постоянно растёт, предлагаются новые идеи, представляются отчёты об ошибках, формируются предложения и замечания - всё это вместе чрезвычайно полезно и выгодно для всего сообщества.

Исходный код nginx является оригинальным и был полностью написан "с нуля" на языке программирования Си. nginx был портирован на множество архитектур и операционных систем, включая Linux, FreeBSD, Solaris, Mac OS, AIX и Microsoft Windows. nginx основывается на своих собственных библиотеках и стандартных модулях, имеющих очень мало внешних зависимостей помимо библиотеки языка C, за исключением zlib, PCRE и OpenSSL, которые могут быть исключены во время сборки при необходимости или по лицензионным соображениям.

И ещё несколько слов о Windows-версии nginx. nginx работает в среде Windows. Причём Windows-версия nginx больше похожа на доказательство правильно выбранной концепции, а не на полнофункциональную портированную версию. Есть определённые ограничения nginx, связанные с архитектурой ядра Windows и отсутствием на текущее время хорошего взаимодействия с ним. Известные проблемы Windows-версии nginx это: значительно меньшее число поддерживаемых одновременных соединений, более низкая производительность, отсутствие кеширования и отсутствие управления полосой пропускания. Функционал будущих Windows-версий nginx будет более полно соответствовать основной версии.

14.2. Обзор архитектуры Nginx

Традиционные процессно- или потоко-ориентированные модели подразумевают при одновременном обслуживании соединений порождение нового процесса или потока на каждое соединение и его блокирование при сетевых операциях или операциях ввода/вывода. В зависимости от способа применения такие модели могут быть крайне неэффективными с точки зрения использования ЦПУ и оперативной памяти. Порождение нового процесса или потока влечёт за собой подготовку новой среды окружения с выделением в оперативной памяти кучи (heap), стека и нового контекста исполнения. ЦПУ тратит дополнительное время на создание этих объектов, что, в конечном итоге, может привести к снижению производительности из-за частого переключения контекста исполнения. Все перечисленные выше проблемы проявляются в web-серверах со старой архитектурой, таких как Apache. Это компромисс между богатым функционалом и оптимальным использованием ресурсов сервера.

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

nginx для мультиплексирования и извещения о событиях использует один главный процесс, а исполнение конкретных задач назначает отдельным подчинённым процессам. Обработка соединений выполняется в высокоэффективных циклах обработки событий, помещённых в потоки. Такие потоки называются "исполнители" (workers), а их количество ограничено. В рамках каждого "исполнителя" nginx может обрабатывать тысячи одновременных подключений и запросов в секунду.

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

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

Модульная архитектура nginx позволяет разработчикам расширять набор функций без изменения его ядра. Модули nginx подразделяются на несколько типов: модули ядра (core modules), обработчики событий (event modules), обработчики фазы (phase handlers), модули реализации протоколов (protocols), обработчики именованных переменных (variable), фильтры, модули перенаправления запросов на вышестоящие серверы (upstreams) и балансировщики нагрузки (load balancers). В настоящее время nginx не поддерживает динамически загружаемые модули. То есть, модули компилируются вместе с ядром в один исполнимый файл на этапе сборки. Однако, поддержка загружаемых модулей и ABI запланирована на следующие major-релизы. Более подробную информацию о роли различных модулей можно найти в разделе 14.4.

При обработке операций, связанных с приёмом, обработкой и управлением сетевыми подключениями, извлечением данных, а также при дисковых операциях ввода/вывода, nginx для повышения производительности использует специфические механизмы уведомления о событиях, такие как kqueue, epoll и event ports, доступные в операционных системах Linux, Solaris и семействе BSD. Цель состоит в максимальном использовании возможностей операционной системы для обеспечения своевременной обратной связи, по своей природе асинхронной, при обработке входящего/исходящего трафика, дисковых операций, чтения или записи в сокеты, организации тайм-аутов и т.п. Используемые в nginx различные методы мультиплексирования и ускоренного ввода/вывода в значительной степени оптимизированы для каждой Unix-подобной операционной системы, на которой он запускается.

Обзорная схема архитектуры nginx представлена на рисунке 14.1

Рисунок 14.1: Схема архитектуры nginx

Модель исполнителя

Как уже упоминалось ранее, nginx не порождает новый процесс или поток для каждого соединения. Вместо этого исполнители принимают новые запросы из разделяемого прослушиваемого сокета и выполняют их в своих высокоэффективных циклах обработки, что позволяет обрабатывать тысячи соединений на каждого исполнителя. В nginx нет специализированных механизмов управления или перераспределения соединений между исполнителями, так как эта работа выполняется подсистемами ядра операционной системы. После запуска выполняется создание сокетов для приёма соединений. Затем исполнители непрерывно принимают, считывают и записывают в эти сокеты до тех пор пока выполняются обработка HTTP-запросов.

Непрерывный цикл обработки является самой сложной частью исходного кода исполнителя. Здесь широко используются внутренние вызовы и идея асинхронной обработки. Асинхронные операции реализованы с применением модульности, механизма сообщений о событиях, широкого использования функций обратного вызова (callback functions) и великолепно доработанных таймеров. В целом, во всём прослеживается принцип: все операции должны быть неблокирующими настолько, насколько это возможно. Единственная ситуация, когда nginx всё-таки применяет блокировку - это нехватка производительности дисковой подсистемы для исполнителя.

Так как nginx не порождает новый процесс или поток для каждого соединения, использование оперативной памяти очень экономичное и в подавляющем большинстве случаев крайне эффективное. nginx экономно использует ЦПУ в виду отсутствия постоянных созданий и удалений контекстов процесса или потока. Всё что делает nginx, это проверяет состояние сетевого подключения и дисковой подсистемы, инициирует создание новых соединений, переносит их обработку в цикл исполнителя и асинхронно обрабатывает их до завершения, после чего соединение освобождается и удаляется из цикла обработки исполнителя. Сочетание бережного использования вызовов syscall с аккуратной реализацией интерфейсов распределителей памяти pool и slab (pool and slab memory allocators) позволяет nginx достигать от умеренной до низкой загрузки ЦПУ даже при экстремальных нагрузках.

В связи с тем, что nginx использует несколько исполнителей для обработки соединений, он хорошо масштабируется на несколько ядер ЦПУ. В целом, распределение исполнителей по ядрам позволяет полностью использовать многоядерные архитектуры и предотвращает простой потоков и блокировки. В итоге, отсутствует нехватка ресурсов, а механизмы их контроля изолированы каждый в своём потоке исполнителя. Такая модель также позволяет достичь лучшей масштабируемости дисковой подситемы, способствует более эффективному её использованию и позволяет избежать блокировок при операциях ввода/вывода. В результате, ресурсы сервера используются более эффективно с распределением нагрузки между исполнителями.

Для достижения заданных паттернов использования дисковой подсистемы и ЦПУ число исполнителей может быть скорректировано. Для этого есть несколько основных правил, которые системные администраторы должны попробовать для своих рабочих нагрузок. Общие рекомендации могут быть следующими: если предполагается высокая нагрузка на ЦПУ (например, обработка большого количества TCP/IP запросов, обработка SSL или сжатие), то число исполнителей должно совпадать с количеством процессорных ядер; если предполагается высокая нагрузка на дисковую систему ввода/вывода (например, обслуживание запросов на выдачу данных или высоконагруженное проксирование), то число исполнителей должно быть в полтора-два раза больше, чем количество процессорных ядер. Некоторые инженеры выбирают количество исполнителей по количеству систем хранения или дисков, но эффективность такого подхода зависит от типа и конфигурации дисковой подсистемы.

Одной из основных проблем, которую разработчики nginx будут решать в ближайщих версиях, является существенное уменьшение количества блокировок при дисковых операциях ввода/вывода. На данный момент, если одному из исполнителей не хватает производительности дисковой подсистемы, то он может не снять блокировку на дисковый ввод/вывод пока не завершит свою операцию. Однако, существует целый ряд механизмов и директив конфигурационного файла для смягчения сценариев с блокировкой дискового ввода/вывода. В частности, комбинация опций sendfile и AIO обычно обеспечивает достаточный запас по производительности дисковой подсистемы. То есть, развёртывание nginx должно планироваться с учётом типа информации, к которой будет обеспечиваться web-доступ, объёма доступной оперативной памяти и архитектуры системы хранения данных.

Другая проблема в существующей модели исполнителя - это ограниченная поддержка встраиваемых скриптовых сценариев. В стандартной поставке nginx поддерживается встраивание скриптов только на языке Perl. Этому есть простое объяснение: встроенный скрипт может заблокировать выполнение любой операции или неожиданно завершиться. Любой из этих двух вариантов поведения может привести к зависанию исполнителя, что отразится на тысячах одновременных соединений, которые он обслуживал. Планируется проделать большую работу, чтобы сделать встраивание скриптовых языков более простым, надёжным и пригодным для широкого спектра применений.

Назначение процессов nginx

nginx запускает несколько процессов в оперативной памяти: один главный процесс и несколько процессов исполнителей. Также есть несколько специализированных процессов, в частности, загрузчик кеша и диспетчер кеша. В nginx версии 1.1 все процессы однопоточные. Все процессы для взаимодействия между собой используют механизмы разделяемой памяти (shared-memory machanisms). Управляющий процесс nginx (master process) запускается с привелегиями пользователя root. Загрузчик кеша, диспетчер кеша и исполнители запускаются от имени обычного непривелегированного пользователя.

Управляющий процесс отвечает за выполнение следующих задач:

считывание и проверка на корректность файла настроек создание, подключение и удаление сокетов запуск, завершение и поддержание заданного количества исполнителей загрузка новых настроек без остановки работы управление бинарными обновлениями "на лету" (начиная от замены исполнимого файла и заканчивая откатом к предыдущему состоянию при необходимости) повторные открытия лог-файлов трансляция встроенных скриптов на языке Perl Процессы исполнителей принимают, управляют и обрабатывают соединения от клиентов, обеспечивают обратное проксирование и фильтрацию, то есть, делают почти всё, на что спобен nginx. Что касается контроля за работой nginx, то системный администратор должен следить за состоянием процессов исполнителей, так как, фактически, именно они изо дня в день выполняют все операции web-сервера.

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

Диспетчер кеша в основном отвечает за отслеживание истечения срока действия записей и маркирование их как недействительных. Он остаётся в оперативной памяти всё время работы nginx и в случае сбоя перезапускается вместе с главным процессом.

Краткий обзор кеширования в nginx

Кеширование в nginx реализовано в виде иерархически организованного хранилища в файловой системе. Ключи кеша настраиваемые, а информация, попадающая в кеш, может контролироваться с помощью различных специфичных для каждого типа запросов параметров. Кеш ключей и кеш мета-данных хранятся в сегменте разделяемой памяти, к которой могут получить доступ диспетчер кеша и исполнители. В настоящее время кеширование в оперативную память отсутствует, кроме возможной оптимизации с помощью механизма виртуальной файловой ситемы средствами операционных систем. Кеш для каждого запроса располагается в отдельном файле в файловой системе. Иерархией кеша (уровни и способы именования) можно управлять с помощью директив конфигурационного файла nginx. При записи запроса в структуру каталогов кеша путь и имя файла вычисляются с помощью MD5-хеша проксируемого адреса URL.

Процесс размещения данных в кеше происходит следующим образом: при получении ответа от вышестоящего сервера nginx сохраняет его во временный файл вне структуры каталогов кеша. После завершения обработки запроса nginx переименовывает временный файл и перемещает его в каталог с кешем. Если каталог для хранения временных файлов располагается в другой файловой системе, то он будет скопирован. Поэтому рекомендуется размещать каталог для временных файлов и кеш в одной файловой системе. Также вполне безопасно удалять файлы из каталога кеша в случае, когда явно видно, что они должны быть очищены. Также существуют сторонние расширения для nginx, которые позволяют дистанционно контролировать содержимое кеша, и в будущем этот функционал планируется интегрировать в основной дистрибутив.

14.3 Настройки nginx

Вдохновение при создании системы конфигурирования nginx Игорь Сысоев черпал в Apache. Его главная идея состояла в том, что масштабируемая система конфигурации имеет важнейшее значение для web-сервера. Основная проблема масштабируемости проявилась при поддержании больших и сложных конфигураций с большим количеством виртуальных серверов, каталогов, корневых директорий web-сайтов (locations) и наборов данных. В сравнительно больших инсталляциях эта проблема может стать кошмаром, если всё сразу не сделано должным образом, как на уровне приложения, так и на уровне системного инженера.

В результате, в nginx была разработана система конфигурации, упрощающая повседневные операции и обеспечивающая простые средства для дальнейшего расширения настроек web-сервера.

Конфигурационные файлы nginx хранятся в файлах, обычно расположенных в каталоге /usr/local/etc/nginx или /etc/nginx. Основной конфигурационный файл обычно называется nginx.conf. Для достижения лаконичности часть настроек может быть помещена в отдельные файлы, которые будут автоматически объединены с основным на этапе загрузки. Тем не менее, следует отметить, что в настоящее время nginx не поддерживает распределённые конфигурации в стиле Apache (например, файлы .htaccess). Все настройки, определяющие поведение nginx, должны храниться в упорядоченном наборе конфигурационных файлов.

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

Файл настроек nginx может содержать несколько типов блоков директив: основные настройки (main), настройки для http (http), настройки задания виртуальных серверов (server), настройки для указания вышестоящих серверов (upstream), настройки определения местоположения web-сайта (location) и настройки для проксирования электронной почты (mail). Группы настроек никогда не пересекаются. Например, не допускается помещать блок директив location в блок основных настроек main. Кроме того, для исключения двусмысленностей отсутствуют такие настройки, как "глобальный web-сервер". Настройки nginx подразумевают чистоту и логичность, позволяя пользователям поддерживать сложные конфигурационные файлы с тысячами директив. В частной беседе Сысоев сказал: "Locations, directories и другие блоки настроек в общей конфигурации, как это сделано в Apache, мне никогда не нравились и это является причиной, по которой они никогда не появятся в nginx".

Синтаксис, форматирование и определения основываются на так называемом Си-стиле (C-style). Такой приём построения конфигурационных файлов уже используется некоторыми проектами с открытым исходным кодом и коммерческими приложениями. По задумке, Си-стиль хорошо подходит для определения вложенных описаний, являясь логичным и простым для создания, чтения и сопровождения, за что его и полюбили многие инженеры. Также Си-стиль конфигурации nginx легко поддаётся автоматизации.

Хотя некоторые директивы nginx напоминают конфигурацию Apache, настройка nginx - это совсем другой опыт. Например, nginx поддерживает переопределение правил, что в случае с настройкой Apache потребовало бы ручной правки конфигурационных файлов. Реализации способов перезаписи также отличаются.

В целом, настройки nginx поддерживают несколько оригинальных механизмов, которые могут быть очень полезны при конфигурировании web-сервера с минимальными требованиями. Имеет смысл упомянуть именованные переменные (variables) и директиву try_files, которые в некоторой степени уникальны. Именованные переменные были реализованы для обеспечения ещё более мощного механизма управления web-сервером на этапе загрузки конфигурации. Именованные переменные уже пре-компилированы и оптимизированы для быстрого разрешения в значения. Разрешение переменной в значение выполняется по требовнию, то есть значение, как правило, расчитывается один раз и остаётся неизменным в кеше всё время жизни конкретного запроса. Именованные переменные могут использоваться с различными конфигурационными директивами, что обеспечивает дополнительную гибкость при описании реакции на запросы по условию.

Директива try_files изначально была предназначена для постепенной замены условного оператора if, так как более правильно, быстро и эффективно "попробовать-сравнить" чем поддерживать карты соответствия между URI и данными. И в целом, директива try_files работает хорошо, может быть весьма эффективной и полезной. Можно порекомендовать читателю испльзовать директиву try_files там, где это применимо.

Дополнительные материалы