Хотя многие веб-серверы и серверы приложений используют простую многопоточную модель, NGINX выделяется из толпы своей нетривиальной архитектурой, основанной на событиях, которая позволяет ему легко масштабироваться до сотен тысяч одновременных подключений.
Инфографика Внутри НГИНКС Познакомит вас сверху вниз с основами проектирования процессов и проиллюстрирует, как NGINX обрабатывает несколько соединений в одном процессе.
В этой статье все это будет рассмотрено немного подробнее.
Подготовка почвы: модель процесса NGINX
Чтобы лучше понять устройство, сначала нужно понять, как работает NGINX. NGINX имеет один главный процесс (который выполняет такие операции, как чтение конфигурации и открытие портов от имени суперпользователя), а также ряд рабочих и вспомогательных процессов.
На 4-ядерном сервере главный процесс NGINX создает 4 рабочих процесса и пару вспомогательных процессов кеша, которые управляют содержимым кеша на жестком диске.# service nginx restart * Restarting nginx # ps -ef --forest | grep nginx root 32475 1 0 13:36 ? 00:00:00 nginx: master process /usr/sbin/nginx \ -c /etc/nginx/nginx.conf nginx 32476 32475 0 13:36 ? 00:00:00 \_ nginx: worker process nginx 32477 32475 0 13:36 ? 00:00:00 \_ nginx: worker process nginx 32479 32475 0 13:36 ? 00:00:00 \_ nginx: worker process nginx 32480 32475 0 13:36 ? 00:00:00 \_ nginx: worker process nginx 32481 32475 0 13:36 ? 00:00:00 \_ nginx: cache manager process nginx 32482 32475 0 13:36 ? 00:00:00 \_ nginx: cache loader process
Почему архитектура все еще важна?
Одной из фундаментальных основ любого приложения Unix является процесс или поток (с точки зрения ядра Linux процессы и потоки — это практически одно и то же — единственная разница — разделение адресного пространства).Процесс или поток — это автономный набор инструкций, выполнение которых операционная система может запланировать на ядре процессора.
Большинство сложных приложений запускают множество процессов или потоков параллельно по двум причинам:
- Одновременно использовать больше вычислительных ядер;
- Процессы и потоки упрощают выполнение параллельных операций (например, одновременную обработку нескольких соединений).
Каждый такой процесс или поток потребляет определенный объем памяти, а кроме того они постоянно заменяют друг друга на процессоре (так называемое переключение контекста).
Современные серверы могут обрабатывать сотни активных процессов и потоков, но производительность сильно снижается, как только заканчивается память или огромное количество операций ввода-вывода приводит к слишком частому изменению контекста.
Наиболее типичный подход к созданию сетевого приложения — выделение отдельного процесса или потока для каждого соединения.
Эту архитектуру легко понять и реализовать, но она плохо масштабируется, когда приложение должно работать с тысячами соединений одновременно.
Как работает Nginx?
NGINX использует модель фиксированного процесса, которая позволяет максимально эффективно использовать доступные системные ресурсы:- Один главный процесс выполняет операции, требующие повышенных прав, такие как чтение конфигурации и открытие портов, а затем порождает небольшое количество дочерних процессов (следующие три типа).
- Загрузчик кэша запускается при запуске для загрузки данных кэша, расположенных на диске, в оперативную память, а затем завершает работу.
Его работа спланирована так, чтобы не потреблять много ресурсов.
- Менеджер кэша периодически просыпается и удаляет объекты кэша с жесткого диска, чтобы поддерживать его емкость в пределах указанного предела.
- Рабочие процессы делают всю работу.
Они обрабатывают сетевые подключения, читают и записывают данные с диска и взаимодействуют с внутренними серверами.
Установить этот режим можно с помощью директивы worker_processes авто в файле конфигурации: worker_processes auto;
Когда NGINX находится под нагрузкой, он в основном занят рабочими процессами.
Каждый из них обрабатывает несколько соединений неблокирующим образом, сводя к минимуму количество переключений контекста.
Каждый рабочий процесс является однопоточным и работает независимо, принимая новые соединения и обрабатывая их.
Процессы взаимодействуют друг с другом, используя общую память для кэширования данных, сеансов и других общих ресурсов.
Внутри рабочего процесса
Каждый рабочий процесс NGINX инициализируется с заданной конфигурацией и набором прослушивающих сокетов, унаследованных от главного процесса.
Рабочие процессы начинаются с ожидания событий в прослушиваемых сокетах (см.
также принять_мьютекс И общие сокеты ).
События уведомляют вас о новых соединениях.
Эти связи попадают в Государственный аппарат — наиболее часто используемый — для обработки HTTP, но NGINX также содержит конечные автоматы для обработки потоков TCP-трафика (модуль транслировать ) и ряд протоколов электронной почты ( SMTP , IMAP И POP3 ).
Конечный автомат в NGINX — это, по сути, набор инструкций для обработки запроса.
Большинство веб-серверов выполняют одну и ту же функцию, но разница заключается в реализации.
Устройство конечного автомата
Конечный автомат можно рассматривать как правила игры в шахматы.Каждая HTTP-транзакция — это шахматная партия.
На одной стороне шахматной доски веб-сервер — гроссмейстер, который очень быстро принимает решения.
С другой стороны — удаленный клиент, браузер, который запрашивает сайт или приложение по относительно медленной сети.
Однако правила игры могут быть очень сложными.
Например, веб-серверу может потребоваться взаимодействовать с другими ресурсами (прокси-запросы к серверной части) или связаться с сервером аутентификации.
Сторонние модули могут еще больше усложнить обработку.
Блокирующий конечный автомат
Вспомните наше определение процесса или потока как автономного набора инструкций, выполнение которых операционная система может назначить определенному ядру процессора.Большинство веб-серверов и веб-приложений используют модель, в которой они играют в шахматы с одним процессом или потоком на одно соединение.
Каждый процесс или поток содержит инструкции, необходимые для завершения одной игры.
Все это время процесс, запущенный на сервере, большую часть времени проводит заблокированным, ожидая следующего шага от клиента.
- Процесс веб-сервера ожидает новых подключений (новых пакетов, инициированных клиентами) на прослушиваемых сокетах.
- Получив новое соединение, он играет в игру, блокируясь после каждого хода, ожидая ответа от клиента.
- Во время игры процесс веб-сервера может ожидать, пока клиент начнет следующую игру (это соответствует долгоживущим соединениям поддержки активности).
Если соединение закрыто (клиент вышел из соединения или истекло время ожидания), процесс возвращается к встрече с новыми клиентами в прослушиваемых сокетах.
Эта архитектура проста и легко расширяется с помощью сторонних модулей (новых «правил»).
Однако существует огромный дисбаланс: достаточно легкое HTTP-соединение, представленное файловым дескриптором и небольшим объемом памяти, связано с отдельным процессом или потоком — достаточно тяжелым объектом в операционной системе.
Это удобно для программирования, но очень расточительно.
NGINX как настоящий гроссмейстер
Вы, наверное, слышали об одновременных играх, когда один гроссмейстер играет на нескольких шахматных полях одновременно с десятками соперников?Кирил Георгиев сыграл параллельно 360 партий на турнире в Болгарии.
Его окончательный результат составил: 284 победы, 70 ничьих и 6 поражений.
Точно так же рабочий процесс NGINX играет в шахматы.
Каждый рабочий процесс (помните, обычно только один на ядро) — это гроссмейстер, способный одновременно играть в сотни (фактически, сотни тысяч) игр.
- Рабочий процесс прослушивает события в прослушиваемых сокетах и сокетах подключения.
- События происходят в сокетах и процесс их обрабатывает:
- Событие в сокете прослушивания означает, что прибыл новый клиент для запуска игры.
Рабочий процесс создает новый сокет подключения.
- Событие в сокете подключения сигнализирует о том, что клиент сделал ход. Рабочий процесс реагирует на него мгновенно.
- Событие в сокете прослушивания означает, что прибыл новый клиент для запуска игры.
После того, как процесс сделал свой ход, он сразу же перемещается на другие доски, где игроки ждут хода, или встречает новых у дверей.
Почему это быстрее, чем блокирующая многопоточная архитектура?
Каждое новое соединение создает файловый дескриптор и потребляет небольшой объем памяти рабочего процесса.Это очень низкие затраты на соединение.
Процессы NGINX могут оставаться привязанными к конкретным ядрам процессора.
Переключение контекста происходит довольно редко и в основном тогда, когда больше нечего делать.
Блокирующий подход с отдельным процессом для каждого соединения требует относительно большого количества дополнительных ресурсов, а переключение контекста с одного процесса на другой происходит гораздо чаще.
Дополнительную информацию по теме можно также найти в статьи об архитектуре NGINX от Андрея Алексеева, вице-президента по развитию и сооснователя компании НГИНКС, Инк.
С адекватная настройка системы NGINX хорошо масштабируется до многих сотен тысяч одновременных HTTP-соединений на один рабочий процесс и уверенно поглощает всплески трафика (толпы новых игроков).
Обновление конфигурации и исполняемого кода
Архитектура NGINX с низким энергопотреблением позволяет ему достаточно эффективно обновлять свою конфигурацию и даже собственный исполняемый код на лету.
Обновление конфигурации NGINX — очень простая, легкая и надежная процедура.
Он состоит из простой отправки сигнала SIGHUP главному процессу.
Когда рабочий процесс получает SIGHUP, он выполняет несколько операций:
- Перезагружает конфигурацию и запускает новый набор рабочих процессов.
Эти новые рабочие процессы немедленно начинают принимать соединения и обрабатывать трафик (с использованием новых настроек).
- Сигнализирует о том, что старые рабочие процессы должны завершиться достойно.
Они перестают принимать новые связи.
Как только текущие HTTP-запросы завершаются, соединения закрываются (никаких сохраняющихся соединений поддержания активности).
Как только все соединения закрыты, рабочий процесс завершается.
Вы можете перезагружать конфигурацию несколько раз в секунду (и таких пользователей NGINX довольно много).
В редких случаях могут возникнуть проблемы, когда слишком много поколений рабочих процессов NGINX ожидают закрытия соединений, но они быстро решаются.
Обновление исполняемого кода NGINX — это Святой Грааль высокой доступности сервисов.
Вы можете обновлять сервер на лету, без потери соединения, простоя ресурсов или каких-либо перерывов в обслуживании клиентов.
В процессе обновления исполняемого кода используется аналогичный подход к перезагрузке конфигурации.
Новый главный процесс NGINX работает параллельно со старым и получает от него дескрипторы прослушиваемых сокетов.
Оба процесса заняты, а их рабочие процессы обрабатывают трафик.
Затем вы можете дать команду старому главному процессу корректно завершить работу.
Вся процедура подробно описано в документации.
Давайте подведем итоги
Мы дали краткий обзор того, как работает NGINX. За этими простыми описаниями скрывается более чем десятилетний опыт разработки и оптимизации, который позволяет NGINX обеспечивать выдающуюся производительность на широком спектре оборудования и реальных рабочих нагрузок, оставаясь при этом надежными и безопасными, как того требуют современные веб-приложения.Если вы хотите узнать больше по этой теме, рекомендуем прочитать:
- Установка и настройка NGINX для повышения производительности (вебинар; слайды на акустической панели)
- Настройка NGINX для повышения производительности
- Архитектура приложений с открытым исходным кодом – NGINX
- Несколько сокетов в NGINX 1.9.1 (с использованием опции SO_REUSEPORT)
-
Выбирайте Java С Умом…
19 Oct, 24 -
Что Такое Itsp-Сорсинг?
19 Oct, 24 -
Монголия
19 Oct, 24 -
Систематизация Процесса Графического Дизайна
19 Oct, 24 -
Тип Темперамента. Кто Ты?
19 Oct, 24 -
Recs Компенсирует Перерывы В Работе
19 Oct, 24 -
Многопользовательская Онлайн-Игра От Рбк
19 Oct, 24