nginx (швейцар у двери)
На пальцах
Представь торговый центр с одним входом. На двери стоит швейцар. Заходит человек: «мне в обувной» — швейцар показывает третий этаж. «Мне в кафе» — второй. Сам он ничего не продаёт и не варит, но без него все стояли бы в дверях и не знали, куда идти. nginx — это такой швейцар на входе в твой сервер: разбирает, кто пришёл за чем, и направляет к нужному сервису.
Что это
Программа, которая стоит на «входной двери» сервера — обычно на портах 80 (обычный HTTP) и 443 (зашифрованный HTTPS) — и решает, кому из внутренних сервисов отдать пришедший запрос. Слово nginx читается «энджин-икс», по-русски иногда пишут латиницей «nginx», иногда — «нгинкс».
Зачем
На сервере (например, у интернет-магазина) обычно крутится несколько отдельных программ: витрина сайта, обработчик заказов, база данных, чат поддержки. У сервера один публичный адрес и одни порты. Если бы каждая программа сама выглядывала в интернет, покупателю пришлось бы вбивать в адрес не «shop.ru», а «shop.ru:3000», «shop.ru:8000» — и браузер не показал бы зелёный замочек безопасности. nginx собирает всё за одной дверью: по домену и по пути в адресе решает, кого звать, сам расшифровывает HTTPS и при необходимости отдаёт картинки и стили сам, не дёргая остальных.
Ещё nginx умеет:
- расшифровать HTTPS (TLS termination — внутрь идёт уже открытый HTTP, и внутренние программы не возятся с шифрованием)
- автоматически получать и обновлять бесплатный сертификат Let's Encrypt (тот самый, что ставит замочек в браузере)
- сжимать ответ (gzip/brotli) — страница летит быстрее
- ограничивать поток запросов (rate limiting) — защита от соседа-скрипта, который долбит сайт тысячу раз в секунду
- вести журнал каждого обращения (access log — кто, когда, откуда, какой ответ получил)
- распределять нагрузку между несколькими копиями одного сервиса (load balancing)
Как устроено
Внутри nginx — не один толстый процесс, а связка: один главный (master) и несколько рабочих (worker). Главный только читает конфигурационный файл nginx.conf и управляет рабочими: запускает, останавливает, просит перечитать настройки. Сами запросы принимают рабочие — они не умирают после каждого посетителя и работают одновременно.
Главный трюк nginx — устройство рабочего. В нём нет отдельной «ветки» (потока, thread) на каждого посетителя. Вместо этого один рабочий держит в голове событийный цикл (event loop): «пока жду ответа от диска — посмотрю, не пришёл ли новый запрос; пока другой запрос ждёт базу — займусь третьим». Это называют асинхронной неблокирующей обработкой. Один рабочий тянет тысячи соединений, потому что почти всё время кто-то из них всё равно ждёт — сети, диска, базы. На каждой современной ОС за этим стоит системный вызов epoll (в Linux) или kqueue (в BSD/macOS) — он будит рабочего только по тем соединениям, по которым реально что-то произошло.
Конфигурация nginx — это текстовый файл с иерархией блоков. Внешний блок http описывает общие правила, внутри — блоки server (по одному на домен или набор), внутри них — блоки location (правила для конкретных путей вроде /api или /static). Каждое правило — это директива: простая (gzip on;) или составная (с фигурными скобками). Когда рабочий получает запрос, он прогоняет его по фазам обработки: сначала читает заголовки, потом подбирает подходящий server и location, считает, не надо ли подменить адрес, проверяет права доступа, потом получает или генерирует содержимое, и в конце записывает строку в журнал. Этих фаз больше десятка, и в нужных местах можно подключить сторонние модули — например, для сложной логики на Lua.
Один важный нюанс: швейцар у двери быстрый именно потому, что не готовит еду сам. nginx тоже не выполняет тяжёлую логику — для этого у него за дверью стоит php-fpm, Python-приложение, Node.js или Go-сервис. nginx занимается тем, в чём силён: быстро принять, решить, куда отправить, и быстро отдать.