[Перевод] Nginx для проектов с открытым исходным кодом

сервер Apache Nginx Программа перевода самородков

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

14.1 Почему высокий параллелизм так важен?

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

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

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

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

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

Апач неуместен?

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

Поэтому, когда серверное оборудование, операционная система и сетевые условия стали узким местом для роста сайта, веб-инженеры всего мира начали искать более эффективный способ. Около десяти лет назад блестящий инженер по имени Даниэль Кегель заявил: «Пришло время для веб-сервисов поддерживать параллелизм 10 000». Как только возникла проблема c10k, было представлено множество решений для оптимизации высокого параллелизма в реальном времени. nginx стал одним из лучших решений.

Чтобы решить проблему 10 000 соединений в реальном времени в задаче C10k, nginx использует другую архитектуру, которая больше подходит для одновременной обработки большого количества соединений и выполнения нескольких запросов во второй среде, масштаб проблемы , Рост нелинейный. Nginx основан на событиях, поэтому ему не требуется процесс или поток для каждого веб-запроса, как это делает Apache. В результате, даже если нагрузка увеличивается, память и ЦП все еще находятся под контролем. В настоящее время Nginx может обрабатывать десятки тысяч одновременно на обычной машине.

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

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

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

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

За последние несколько лет в архитектуре веб-сайтов появилось разделение и отделение некоторых основных компонентов от веб-сервера. Однако те базовые компоненты, которые изначально существовали в веб-сайтах на основе LAMP, в веб-сайтах на основе LEMP (E означает произношение Nginx), могут сделать веб-сервер базовыми компонентами и интегрировать их по-другому, новое или улучшенное приложение и базу данных. инструменты.

nginx отлично подходит для этого, потому что он может легко обеспечить эффективный уровень поддержки параллелизма, отложенную обработку времени ожидания, поддержку SSL, поддержку статических файлов, сжатие и кэширование и даже потоковую передачу по http, которые изначально находятся на уровне приложения. Nginx также может напрямую интегрировать некоторые NoSQL, такие как Redis/memcached, для оптимизации сценариев с большим объемом пользователей.

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

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

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

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

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

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

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

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

Структура кода Структура кода

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

Модульная архитектура nginx позволяет разработчикам добавлять некоторые пользовательские расширения без изменения основного кода. Модули nginx немного отличаются, например модули ядра, модули событий, обработчики этапов, протоколы, обработчики переменных, фильтры, восходящий поток и балансировка нагрузки. В настоящее время nginx больше не поддерживает динамическую загрузку модулей. Модули компилируются на этапе сборки nginx. Однако в будущем nginx будет предоставлять загружаемые модули и ABI для основных выпусков. Для получения дополнительной информации о различных модулях см.Section 14.4.

nginx использует механизм уведомления о событиях и некоторые оптимизации дискового ввода-вывода операционной системы (Linux, Solaris и BSD) при работе с сетевым приемом, обработкой и управлением, а также извлечением контента, например:kqueue, epoll, and event ports. Цель состоит в том, чтобы предоставить ОС как можно больше подсказок для получения своевременной асинхронной обратной связи для входящего и исходящего трафика, операций с дисками, операций чтения и записи сокетов, тайм-аутов и т. д. Существует множество оптимизаций с использованием различных методов мультиплексирования и расширенных операций ввода-вывода для каждой Unix-подобной операционной системы, на которой работает nginx.

Более подробный обзор архитектуры nginx см.Figure 14.1.

Figure 14.1: Diagram of nginx's architecture

Модель рабочих

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

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

Поскольку nginx не будет открывать новый процесс или поток для каждого соединения, использование памяти во многих сценариях не будет высоким. Nginx экономит использование ЦП, поскольку не создает и не уничтожает потоки процесса. Все, что делает nginx, — это проверяет сеть и хранилище, создает новые подключения, добавляет новые подключения в опрос и обрабатывает их асинхронно, пока не закончит. nginx осторожно использует некоторые системные вызовы, такие как объединение ресурсов и выделение памяти, чтобы в крайних случаях не было высокой загрузки ЦП.

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

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

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

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

роли процесса nginx

nginx запускает в памяти несколько процессов, есть главный процесс и несколько рабочих процессов. Есть также несколько процессов специального назначения, в частности, загрузчик кеша и менеджер кеша. Все процессы в версии 1.x являются однопоточными. Все процессы в основном используют механизм разделяемой памяти для межпроцессного взаимодействия. Основной процесс выполняется от имени пользователя root. Загрузчик кеша, менеджер кеша и рабочие процессы запускаются как непривилегированные пользователи.

Основной процесс в основном имеет следующие задачи

  • Чтение и проверка файлов конфигурации
  • Создание, привязка и закрытие сокетов
  • Запускать, завершать и поддерживать настроенное количество рабочих процессов
  • Перезагружать конфигурацию без перерыва
  • Контроль горячих обновлений (запуск с бинарника и откат при необходимости)
  • Открыть файл журнала
  • Компилировать встроенные perl-скрипты

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

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

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

обзор кеша nginx

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

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

14.3. Конфигурация nginx

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

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

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

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

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

Синтаксис, формат и определения файла конфигурации следуют так называемым соглашениям стиля C. Этот конкретный метод создания файлов конфигурации использовался различными программными приложениями с открытым исходным кодом и коммерческими приложениями. Конфигурации в стиле C отлично подходят для вложенных описаний, они логичны, их легко создавать, читать и поддерживать, и они нравятся многим инженерам. Конфигурацию nginx в стиле c также легко автоматизировать.

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

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

Директива «try_files» изначально предназначалась для постепенной замены условных операторов конфигурации «if» более подходящим способом, она была разработана для быстрой и эффективной попытки/сопоставления различных сопоставлений uri-to-content. В целом,try_filesДирективы работают просто отлично, они очень эффективны и полезны. Для получения более подробной информации читателям рекомендуетсяtry_files directive

14.4 Внутреннее устройство nginx

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

Внутри nginx обрабатывает соединения через конвейер или цепочку модулей, состоящую из модулей. Другими словами, для каждой операции существует модуль, выполняющий связанную работу, например сжатие, изменение содержимого, выполнение на стороне сервера, взаимодействие с вышестоящими серверами приложений через протоколы FastCGI или uwsgi или взаимодействие с memcached.

Есть несколько модулей nginx, которые находятся между ядром и реальными «функциональными» модулями. Эти модулиhttpиmail. Эти два модуля обеспечивают дополнительный уровень абстракции между компонентами ядра и нижнего уровня. В этих модулях реализована обработка последовательностей событий, связанных с соответствующими протоколами прикладного уровня, такими как HTTP, SMTP или IMAP. В сочетании с ядром nginx эти модули верхнего уровня отвечают за поддержание правильной последовательности вызовов для каждого функционального модуля. Хотя протокол HTTP в настоящее времяhttpЧасть модуля реализована, но в будущем планируется разделить на функциональные модули из-за необходимости поддержки других протоколов, таких как SPDY. Дополнительные сведения о протоколе SPDY см.SPDY: An experimental protocol for a faster web

Функциональные модули можно разделить на модули событий, обработчики этапов, выходные фильтры, обработчики переменных, протоколы, восходящие потоки и балансировщики нагрузки. Большинство этих модулей дополняют функциональность HTTP nginx, но модули событий и протоколы также используются дляmail. Модуль событий предоставляет определенные механизмы уведомления о событиях, зависящие от ОС, такие какkqueueилиepoll. Модуль событий, используемый nginx, зависит от возможностей операционной системы и конфигурации сборки. Модуль протокола позволяет nginx взаимодействовать через HTTPS, TLS/SSL, SMTP, POP3 и IMAP.

Типичный цикл обработки HTTP-запроса показан ниже.

  1. Клиент отправляет http-запрос.
  2. Ядро nginx выбирает соответствующий процессор этапа на основе местоположения в файле конфигурации.
  3. Если конфигурация действует, балансировщик нагрузки выберет прокси-сервер восходящего потока.
  4. Обработчик этапа выполняет задачу и передает содержимое буфера первому фильтру.
  5. Первый фильтр передает содержимое второму фильтру.
  6. Второй фильтр передается третьему (итеративно выполняется)
  7. Отправьте окончательный ответ клиенту.

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

В следующий список можно добавить модули:

  • Перед чтением и обработкой файлов конфигурации
  • где появляется каждый сервер, а файл конфигурации указывает на
  • Когда основная конфигурация инициализирована
  • при инициализации сервера
  • Когда конфигурация сервера объединена с основной конфигурацией
  • Когда конфигурация расположения инициализируется или объединяется с конфигурацией родительского сервера
  • Когда главный процесс запускается или существует
  • Когда новый рабочий процесс запускается или существует
  • при обработке запроса
  • При фильтрации заголовков и тел запросов
  • Когда запрос перенаправляется на вышестоящий сервер
  • Когда сервер отвечает
  • При завершении взаимодействия с вышестоящим сервером

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

  1. запускатьngx_worker_process_cycle().
  2. Используйте специфичные для операционной системы механизмы для обработки событий (например,epoll or kqueue)
  3. Получение событий и отправка связанных действий
  4. Заголовки и тела запроса процесса/прокси
  5. Сгенерируйте содержимое ответа (заголовок, тело) и передайте его клиенту
  6. завершить запрос
  7. перезапустить таймеры, события

Сам опрос (шаги 5 и 6) гарантирует, что ответы постепенно генерируются и передаются клиенту.

Более подробный процесс обработки HTTP-запроса может выглядеть следующим образом.

  1. Инициализировать обработку запроса
  2. обрабатывать заголовки
  3. тело процесса
  4. Вызвать соответствующий обработчик nginx
  5. Выполнить каждый этап обработки

Это подводит нас к каждому этапу. Когда nginx обрабатывает HTTP-запрос, он проходит через несколько этапов обработки. На каждом этапе есть обработчики, которые можно вызывать. Обычно обработчики этапов обрабатывают запросы и генерируют соответствующие выходные данные. Обработчики этапов присоединяются к местам, определенным в файле конфигурации.

Обработчики этапов обычно делают четыре вещи: получают конфигурацию местоположения, генерируют соответствующий ответ, отправляют заголовки и отправляют тело. Обработчик имеет один параметр: определенную структуру, описывающую запрос. Структура запроса содержит много полезной информации о запросе клиента, например метод запроса, URI и заголовки.

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

  1. Этап перезаписи сервера
  2. этап локации
  3. фаза перезаписи местоположения (возврат запроса к предыдущей фазе)
  4. этап контроля соединения
  5. стадия try_files
  6. фаза регистрации

Чтобы сгенерировать необходимый контент в ответ на запрос, nginx передает запрос соответствующему обработчику контента. В зависимости от точной конфигурации местоположения, nginx может сначала попробовать так называемые безусловные обработчики, такие какperl,proxy_pass,flv,mp4Ждать. Если запрос не соответствует ни одному из вышеперечисленных обработчиков контента, он выбирается одним из следующих обработчиков в следующем порядке:random index,index,autoindex,gzip_static,static.

Подробную информацию о модулях индексации можно найти в документации nginx, но это модули, которые обрабатывают запросы с косой чертой в конце. если что-то вродеmp4илиautoindexТакие специализированные модули не подходят, содержимое считается просто файлом или каталогом на диске (т.е. статическим) иstaticОбработчик контента предоставляет услугу. Для каталогов он автоматически переписывает URI так, чтобы косая черта всегда присутствовала в конце (а затем выполняет перенаправление HTTP).

Затем передайте содержимое обработчика содержимого для фильтрации. Фильтр также привязан к местоположению, и для местоположения можно настроить несколько фильтров. filter выполняет задачу манипулирования выводом, сгенерированным обработчиком. Для предопределенных готовых фильтров порядок выполнения определяется во время компиляции. Для сторонних фильтров его можно настроить на этапе сборки. В существующей реализации nginx фильтры могут вносить только исходящие изменения, и в настоящее время нет механизма для написания и прикрепления фильтров для преобразования входного содержимого. Фильтрация ввода появится в будущей версии nginx.

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

Есть также фильтр заголовка и фильтр тела; nginx будет использовать соответствующий фильтр для добавления данных в соответствующий заголовок и тело соответственно.

Фильтр заголовков в основном состоит из следующих трех шагов.

  1. решить, следует ли действовать в соответствии с этим ответом
  2. Манипулировать этим ответом
  3. вызвать следующий фильтр

фильтр тела изменяет сгенерированные данные, ниже приведены некоторые случаи фильтра тела

  • сервер включает
  • XSLT-фильтрация
  • Фильтрация изображений (например, изменение размера изображения)
  • Изменить код
  • gzipкомпрессия
  • chunked encoding

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

Подзапросы — очень важный механизм обработки запроса/ответа. Подзапросы также являются одним из самых мощных аспектов nginx. Для подзапросов nginx может возвращать результаты с URL-адреса, отличного от того, который изначально запросил клиент. Некоторые веб-фреймворки называют это внутренним перенаправлением. Однако nginx идет еще дальше — фильтры могут не только выполнять несколько подзапросов и объединять выходные данные в один ответ, но и подзапросы могут быть вложенными и многоуровневыми. Подзапросы могут выполнять свои собственные подподзапросы, а подподзапросы могут инициировать подподподзапросы. Подзапросы могут быть сопоставлены с файлами на жестком диске, другими обработчиками или вышестоящими серверами. Подзапросы полезны для вставки дополнительного содержимого на основе данных исходного ответа. Например, модуль SSI (Server Side Include) использует фильтр для анализа содержимого возвращенного документа, а затем заменяет директиву «include» содержимым указанного URL-адреса. В качестве альтернативы это может быть фильтр, который обрабатывает все содержимое документа как URL-адрес для извлечения и добавляет новый документ к самому URL-адресу.

upstream и балансировщики нагрузки также заслуживают краткого описания. восходящий поток используется для реализаций, которые можно идентифицировать как обратные прокси (proxy_passСодержимое обработчика. Восходящий модуль в первую очередь готовится к отправке запросов на восходящие серверы (или «бэкенды») и получению ответов. Выходной фильтр здесь не вызывается. Что точно делает вышестоящий модуль, так это устанавливает обратный вызов, который будет вызываться, когда вышестоящий сервер готов к записи и чтению с него. Существуют обратные вызовы, которые реализуют следующие функции:

  • Созданный буфер запросов отправляется на вышестоящий сервер.
  • Переподключитесь к вышестоящему серверу (до того, как будет сделан запрос)
  • Обработайте содержимое ответа вышестоящего сервера и сохраните указатель на содержимое с вышестоящего сервера.
  • Отказ от запроса (в основном, когда клиент преждевременно отключается)
  • Завершите запрос после чтения содержимого с вышестоящего сервера.
  • Очистите тело ответа (например, удалите трейлер ответа http)

Модуль балансировки нагрузки подключен кproxy_passОбработчик, обеспечивающий возможность выбора вышестоящего сервера, когда допустимо несколько вышестоящих серверов. Регистрация балансировщика нагрузки позволяет использовать директивы файла конфигурации, предоставляет дополнительные функции инициализации восходящего потока (для разрешения имен восходящего потока в DNS и т. д.), инициализирует структуры соединений, решает, куда направлять запросы, и обновляет статистику. В настоящее время nginx поддерживает два стандартных правила балансировки нагрузки вышестоящих серверов: round robin и ip-hash.

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

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

Механизм выделения памяти, реализованный в одном воркере nginx, несколько вдохновлен Apache. Общий обзор управления памятью nginx выглядит следующим образом: для каждого соединения необходимые буферы памяти динамически выделяются, связываются, используются для хранения и управления заголовками и телами запросов и ответов, а затем освобождаются при освобождении соединения. Стоит отметить, что nginx старается максимально избегать копирования данных в память, и большая часть данных передается по значению указателя, а не через вызовmemcpy.

Идя немного глубже, когда модуль генерирует ответ, он помещает полученное содержимое в буфер памяти, который затем добавляется в ссылку цепочки буферов. Последующая обработка также применяется к этому звену цепочки буферов. Цепочки буферов в nginx очень сложны, потому что существует несколько схем обработки, которые различаются в зависимости от типа модуля. Например, точное управление буферами при реализации модуля фильтрации тела может оказаться сложным. Такой модуль может работать только с одним буфером (связью ссылок) одновременно, и он должен решить, следует ли перезаписать входной буфер, заменить буфер вновь выделенным буфером или вставить до или после рассматриваемого буфера новый буфер. Ситуация усложняется тем, что иногда модуль получает несколько буферов, поэтому у него должна быть неполная цепочка буферов. Однако на данный момент nginx предоставляет только низкоуровневый API для управления цепочками буферов, поэтому сторонние разработчики модулей должны освоиться с этой загадочной частью nginx, прежде чем приступать к реальной реализации.

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

Задачу управления выделением памяти выполняет распределитель пула nginx. Область общей памяти используется для приема мьютексов, метаданных кэша, кэша сеанса SSL и информации, связанной с контролем пропускной способности и управлением ею (регулированием). Распределитель slab реализован в nginx для управления распределением общей памяти. Для одновременного безопасного использования разделяемой памяти можно использовать множество механизмов блокировки (мьютексы и семафоры). Для организации сложных структур данных в nginx также предусмотрена реализация красно-черного дерева. Красно-черные деревья используются для хранения метаданных кэша в разделяемой памяти, отслеживания определений расположения нерегулярных выражений и ряда других задач.

К сожалению, все вышеперечисленное так и не было описано последовательно и просто, поэтому работа по разработке сторонних расширений к nginx очень сложна. Хотя существует некоторая хорошая документация по внутреннему устройству nginx — например, созданная Эваном Миллером — она требует большой работы по реверс-инжинирингу, а реализация модулей nginx для многих все еще является хаком.

Несмотря на определенные трудности, связанные с разработкой сторонних модулей, сообщество пользователей nginx в последнее время стало свидетелем множества полезных сторонних модулей. Например, есть встроенный модуль интерпретатора Lua для nginx, дополнительные модули для балансировки нагрузки, полная поддержка WebDAV, расширенный контроль кэша и другие интересные сторонние разработки, которые авторы этой главы поощряют и будут поддерживать в будущем. (См. Open Resty — примечание переводчика)

14.5 Сбор урожая

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

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

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

Но стоит отметить, что хотя сообщество разработчиков nginx не очень велико, сторонние модули и расширения nginx всегда были важной частью его популярности. Работа, проделанная Эваном Миллером, Петром Сикорой, Валерием Холодковым, Чжаном Ичунем (китайское имя агента: Чжан Ичунь) и другими талантливыми инженерами-программистами, высоко оценена сообществом пользователей nginx и его первоначальными разработчиками.


This work is made available under the Creative Commons Attribution 3.0 Unported license. Please see the full description of the license for details.

Если вы обнаружите ошибки в переводе или в других областях, требующих доработки, добро пожаловать наПрограмма перевода самородковВы также можете получить соответствующие бонусные баллы за доработку перевода и PR. начало статьиПостоянная ссылка на эту статьюЭто ссылка MarkDown этой статьи на GitHub.


Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.