Метрики и мониторинг Nginx

Рейтинг: 71.7% · 16 голосов
Самый подробный курс по Nginx - от первого конфига до production API-gateway. Архитектура и event loop, контексты и location, виртуальные хосты, статика, reverse proxy и upstream-балансировка, кэширование, HTTPS и TLS (post-quantum), HTTP/2 и HTTP/3 QUIC, безопасность и rate limiting, realip, JSON-логи и сквозная трассировка, метрики, тюнинг и траблшутинг. Плюс OpenResty (Lua, фазы, JWT, динамика) и Angie (нативные Prometheus, ACME, dynamic upstream). На основе эталонного gateway и лучших практик. Для новичков и SRE/DevOps. Актуально на 2026 (nginx 1.30/1.31, Angie, ingress-nginx EOL -> Gateway API).
Ответить
Аватара пользователя
Igor_NgINX
Сообщения: 44
Зарегистрирован: 11 май 2026, 05:31

Метрики и мониторинг Nginx

Сообщение Igor_NgINX »

Оглавление курса (44)
  1. Что такое Nginx и почему он захватил веб
  2. Установка Nginx, Angie и OpenResty: пакеты, версии, Docker
  3. Первый конфиг с нуля: минимальный сервер за 5 минут
  4. Архитектура процессов: master, worker и event loop
  5. Анатомия конфигурации: контексты, наследование и модульность
  6. Виртуальные хосты: server и server_name
  7. Директива location: матчинг и приоритеты по шагам
  8. Раздача статики: root, alias, try_files, sendfile
  9. Переменные, map и блок if
  10. rewrite, return и канонизация URL
  11. Работа с заголовками: add_header и proxy_set_header
  12. Модель доверия прокси-заголовков: realip и защита от спуфинга
  13. Сжатие: gzip, brotli и zstd
  14. Reverse proxy: proxy_pass и проброс запроса
  15. upstream и балансировка нагрузки
  16. Таймауты, повторы и устойчивость прокси
  17. FastCGI и PHP: nginx + PHP-FPM (и uwsgi/scgi)
  18. WebSocket, gRPC и стриминг через Nginx
  19. Кэширование ответов: proxy_cache и микрокэш
  20. HTTPS и TLS: сертификаты, протоколы, шифры (2026)
  21. Let's Encrypt и ACME: certbot, acme.sh, нативный ACME Angie
  22. HTTP/2 и HTTP/3 (QUIC) в 2026
  23. Безопасность: заголовки, скрытие версии, ограничения
  24. Rate limiting и защита от перегрузки
  25. Контроль доступа: allow/deny, auth_basic, auth_request и mTLS
  26. Логирование: access_log, форматы и структурированный JSON
  27. Сквозная трассировка запросов и OpenTelemetry
  28. Метрики и мониторинг Nginx (вы здесь)
  29. Производительность и тюнинг под нагрузку
  30. Траблшутинг: 502, 504, 403, 404 и debug-лог
  31. OpenResty: Nginx как платформа на LuaJIT
  32. Фазы обработки запроса и Lua-хуки
  33. Lua API: ngx.*, shared dict, cosocket и lua-resty-core
  34. Практика OpenResty: авторизация, JWT, кэш, Redis
  35. Angie: современный форк Nginx 2026
  36. Динамическая конфигурация и service discovery
  37. Nginx как API-gateway и Kubernetes Gateway API
  38. Динамические модули, njs и WAF
  39. Stream-модуль: проксирование TCP и UDP
  40. Деплой, перезагрузка и конфиг как код
  41. Сценарий: статика, SPA и кэширование за CDN
  42. Сценарий: микросервисный gateway по образцу ngx-trace-gateway
  43. Капстоун: собираем production-gateway с нуля
  44. Чек-лист безопасности, CVE 2026 и аудит конфигурации
Пять утра, телефон разрывается от алертов, прод лежит. Ты лезешь в SSH, делаешь top, видишь nginx-воркеры на 100% CPU и... всё. Дальше тишина. Сколько активных соединений? Какой апстрим тормозит? p95 latency взлетел или это единичный выброс? Cache hit ratio упал? Без цифр ты гадаешь, а гадание в инциденте - это потерянные минуты, которые стоят денег. Этот урок про то, как сделать так, чтобы nginx сам рассказывал тебе о своём здоровье - в реальном времени, на дашборде, и чтобы будил тебя по делу, а не по паранойе.

Сразу обозначу развилку 2026 года, потому что от неё зависит весь твой стек мониторинга. Ванильный nginx из коробки отдаёт смешные семь цифр через stub_status - и всё. Чтобы получить нормальные nginx метрики, тебе нужна обвязка: экспортер, который парсит эту страничку и переводит в формат Prometheus. А вот Angie (форк nginx от бывшей команды разработки) отдаёт детальные метрики НАТИВНО - REST API с JSON, готовый Prometheus-эндпоинт и визуальную панель. Это не маркетинг, это реально меняет архитектуру наблюдаемости. Разберём оба пути.

nginx stub_status: семь цифр, которые надо понимать

Модуль ngx_http_stub_status_module собран в любой стандартной сборке nginx. Включается одной директивой stub_status внутри location. В нашем эталонном проекте ngx-trace-gateway это вынесено в отдельный служебный сервер на порту 8080 - и это правильный паттерн, который ты должен копировать. Вот глобальный конфиг метрик из эталона:

Код: Выделить всё

server {
    listen 0.0.0.0:8080;
    server_name localhost;

    access_log off;
    error_log  /var/log/nginx/metrics.error.log;

    location = /nginx_status {
        stub_status;
        access_log off;

        allow 127.0.0.1;
        allow 10.0.0.0/8;
        allow 172.16.0.0/12;
        allow 192.168.0.0/16;
        deny  all;
    }
}
Почему отдельный сервер на 8080, а не location в основном :443? Три причины. Первая - изоляция доступа: внутренние метрики не должны торчать наружу, поэтому порт 8080 не пробрасывается за пределы docker-сети, а allow/deny пускают только приватные подсети. Вторая - чистота логов: access_log off на обоих уровнях, чтобы тысячи скрейпов Prometheus каждые 15 секунд не засоряли структурированный лог запросов. Третья - метрики не должны мешать продовому трафику и не должны зависеть от него (отдельный server проще диагностировать).

Теперь сам вывод. Дёрнем страницу:

Код: Выделить всё

$ curl -s http://127.0.0.1:8080/nginx_status
Active connections: 291
server accepts handled requests
 16630948 16630948 31070465
Reading: 6 Writing: 179 Waiting: 106
Разбираем по косточкам, потому что половину этих цифр люди понимают неправильно:
  • Active connections: 291 - текущее число активных клиентских соединений, ВКЛЮЧАЯ waiting (keep-alive). Это не число пользователей: один браузер открывает несколько соединений на одну страницу.
  • accepts (16630948) - сколько соединений nginx принял ВСЕГО с момента старта. Счётчик только растёт.
  • handled (16630948) - сколько обработал. В норме равен accepts. Если handled МЕНЬШЕ accepts - значит, nginx упёрся в лимит (worker_connections исчерпан или ulimit), и часть соединений он принял, но дропнул. Расхождение этих двух чисел - это красный флаг, его обязательно надо вынести в алерт.
  • requests (31070465) - сколько HTTP-запросов всего. Больше handled, потому что по одному keep-alive соединению проходит много запросов. Делишь дельту requests на дельту времени - получаешь RPS.
  • Reading: 6 - nginx читает заголовки запроса от клиента.
  • Writing: 179 - nginx обрабатывает запрос или пишет ответ (включая ожидание апстрима).
  • Waiting: 106 - простаивающие keep-alive соединения. Равно Active минус Reading минус Writing. Зависит от keepalive_timeout.
Главное, что нужно осознать про stub_status: это счётчики и гейджи на уровне всего инстанса. Тут НЕТ разбивки по location, по апстриму, по статус-кодам, по latency. Ты не узнаешь отсюда, сколько было 5xx и какой p95 у /api/. Для этого ванильному nginx нужны либо логи (парсить access_log), либо ngx_otel_module, либо переход на Angie. Это фундаментальное ограничение, держи его в голове.

Изображение

nginx prometheus exporter: мост от семи цифр к дашборду

Prometheus не умеет читать текстовый формат stub_status - ему нужен свой формат метрик (строки вида metric_name{label="x"} value). Связующее звено - официальный nginx-prometheus-exporter от nginx/F5. Это маленький Go-бинарник: ходит на твой /nginx_status, парсит семь цифр и отдаёт их по своему порту 9113 в формате Prometheus.

Запуск в docker-compose рядом с нашим gateway выглядит так:

Код: Выделить всё

  nginx-exporter:
    image: nginx/nginx-prometheus-exporter:1.5.1
    command:
      - --nginx.scrape-uri=http://openresty:8080/nginx_status
    ports:
      - "127.0.0.1:9113:9113"
    restart: unless-stopped
Обрати внимание: scrape-uri указывает на имя сервиса openresty (как в docker-compose эталона) и тот самый порт 8080. Дёрнем экспортер и посмотрим, во что он превращает stub_status:

Код: Выделить всё

$ curl -s http://127.0.0.1:9113/metrics | grep '^nginx'
nginx_connections_accepted 1.6630948e+07
nginx_connections_active 291
nginx_connections_handled 1.6630948e+07
nginx_connections_reading 6
nginx_connections_waiting 106
nginx_connections_writing 179
nginx_http_requests_total 3.1070465e+07
nginx_up 1
Метрика nginx_up - бесплатный бонус: 1, если экспортер достучался до nginx, 0 - если нет. Идеальный сигнал, что инстанс жив. Дальше Prometheus скрейпит этот эндпоинт, и ты строишь графики в PromQL. RPS считается через rate по счётчику:

Код: Выделить всё

rate(nginx_http_requests_total[1m])
И тут же ловишь главное ограничение пути ванильный nginx плюс exporter: восемь метрик. Никакого 5xx rate, никакого latency, никакой разбивки по апстримам. Чтобы мониторить ЭТО на ванильном nginx, тебе придётся либо доставлять логи в Loki/ELK и считать там, либо подключать ngx_otel_module (официальный, open-source, отдаёт трейсы и метрики по OTLP/gRPC), либо - и это самый прямой путь - брать Angie.

angie prometheus и REST /status: метрики без экспортера

Здесь начинается то, ради чего многие в 2026 мигрируют с nginx на Angie. Angie отдаёт детальную телеметрию НАТИВНО, тремя способами сразу, без единого стороннего бинарника.

Первое - REST API /status, который возвращает развёрнутый JSON по всему инстансу: соединения, http-зоны, КАЖДЫЙ upstream с состоянием каждого сервера (up/down, число фейлов, время отклика), кэши, резолверы. Конфиг:

Код: Выделить всё

server {
    listen 127.0.0.1:8080;

    location /status/ {
        api /status/;
        allow 127.0.0.1;
        allow 10.0.0.0/8;
        deny all;
    }
}
Запрос вернёт что-то такое (фрагмент по апстриму - заметь, тут ЕСТЬ то, чего нет в stub_status):

Код: Выделить всё

$ curl -s http://127.0.0.1:8080/status/http/upstreams/backend/
{
  "peers": {
    "10.0.0.1:9000": {
      "state": "up",
      "selected": { "current": 12, "total": 84021 },
      "responses": { "200": 80112, "500": 9, "4xx": 233 },
      "data": { "sent": 19283746, "received": 882347612 },
      "health": { "fails": 0, "unavailable": 0 }
    }
  }
}
Видишь? Состояние пира, разбивка ответов по кодам, счётчик фейлов по health-чеку. В ванильном nginx этого не получить никак. Второе - нативный Prometheus-формат через модуль http_prometheus: задаёшь prometheus_template (готовый шаблон Angie поставляет в комплекте) и отдаёшь готовые метрики прямо из конфига:

Код: Выделить всё

location =/p8s {
    prometheus all;
    allow 10.0.0.0/8;
    deny all;
}
Никакого nginx-prometheus-exporter, никакого парсинга текста, никакого лишнего контейнера. Angie сам генерит метрики в формате Prometheus, и они совместимы с существующими nginx-дашбордами в Grafana. Третье - Console Light: лёгкая веб-панель, которая на лету рисует те же данные из /status в браузере. Поставил пакет angie-console-light, открыл location - и у тебя живой дашборд без Grafana вообще. Для дежурного, которому надо быстро глянуть состояние апстримов, это ровно то, что доктор прописал.

что реально мониторить и как ловить инциденты

Метрики ради метрик - мусор. nginx мониторинг полезен, когда ты замеряешь то, что предсказывает или объясняет боль пользователя. Вот мой обязательный набор, золотые сигналы для шлюза:
  • Доля 5xx (error rate) - сколько процентов ответов это серверные ошибки. Главный сигнал боли. Алерт, когда доля 5xx за 5 минут превышает порог (например 1-2%). На ванильном nginx считается из логов или ngx_otel, на Angie - прямо из responses в /status.
  • Latency p95/p99 - не средняя (она лжёт, среднее размазывает выбросы), а 95-й и 99-й перцентиль request_time и upstream_response_time. Если p95 апстрима растёт, а p95 nginx нет - тормозит бэкенд, не шлюз.
  • Здоровье апстримов - сколько серверов в пуле в состоянии up. На Angie это поле state в /status плюс активные health checks (бесплатно, в ванильном nginx их нет - только пассивный max_fails). Алерт, если живых серверов меньше N.
  • Активные соединения и расхождение accepts/handled - приближение к worker_connections и дропы соединений. Из stub_status напрямую.
  • Cache hit ratio - доля ответов из кэша. Наш эталон шлёт заголовок X-Proxy-Cache со значением $upstream_cache_status (HIT/MISS/BYPASS/EXPIRED). Считаешь долю HIT - падение hit ratio бьёт по бэкенду нагрузкой. На Angie cache hit виден в /status по зоне кэша.
Дальше эти цифры едут в Grafana. Под nginx-prometheus-exporter есть готовые дашборды, под Angie тоже (Angie публикует свой dashboard в каталоге Grafana, и он же работает с метриками http_prometheus). Алерты вешаешь в Alertmanager на те же PromQL-выражения. Правило хорошего алерта: будит человека только то, что требует действия прямо сейчас. 5xx burst - будит. Рост waiting на одну единицу - не будит, это график для разбора, а не повод поднимать дежурного в три ночи.

типичные грабли
  • stub_status торчит наружу. Без allow/deny твоя страница метрик доступна всему интернету, и это утечка инфраструктурной информации (число соединений, RPS - подарок для того, кто планирует DDoS). В эталоне доступ закрыт приватными сетями жёстко. Всегда deny all в конце.
  • Скрейпы засоряют логи. Забыл access_log off на location метрик - и Prometheus каждые 15 секунд пишет строку в твой структурированный лог. За сутки это десятки тысяч мусорных записей. Выключай логирование на эндпоинте метрик.
  • Ждёшь от stub_status того, чего там нет. Классика: человек поднял exporter и ищет в Grafana latency и 5xx по location. Их там НЕТ и быть не может - stub_status это инстанс-уровень. Нужна разбивка - бери ngx_otel, логи или Angie.
  • Считаешь среднюю latency. Avg по латенси скрывает хвосты. Один пользователь ждёт 8 секунд, остальные 50 мс - средняя красивая, а человек страдает. Всегда перцентили.
  • Метрики считаются за всё время аптайма. accepts/handled/requests - это счётчики с момента старта nginx. Сырое число бесполезно, всегда бери rate/дельту за окно. Перезагрузил nginx - счётчик не обнулился (reload сохраняет), а вот рестарт обнулит, и rate в Prometheus корректно это переживёт.
  • VTS-модуль как первый выбор. Сторонний nginx-module-vts раньше был стандартом для per-location метрик, но в 2026 он во многом вытеснен: на ванильном nginx бери ngx_otel_module (официальный), а если нужны детальные метрики из коробки - просто переходи на Angie, где это нативно.
мини-лаба: stub_status в Grafana за 15 минут

Соберём цепочку stub_status -> exporter -> Prometheus руками. Понадобится docker и docker-compose.
  • Шаг 1. Создай рядом с gateway конфиг метрик из эталона (отдельный server на 8080, location = /nginx_status с stub_status и allow приватных сетей). Проверь конфиг: docker exec -it openresty nginx -t.
  • Шаг 2. Изнутри контейнера дёрни страницу: docker exec -it openresty curl -s http://127.0.0.1:8080/nginx_status. Убедись, что видишь Active connections и три счётчика. Если 403 - проверь allow/deny.
  • Шаг 3. Добавь сервис nginx/nginx-prometheus-exporter:1.5.1 в docker-compose со scrape-uri на http://openresty:8080/nginx_status, подними его.
  • Шаг 4. Проверь экспортер: curl -s http://127.0.0.1:9113/metrics | grep nginx_up. Должно быть nginx_up 1. Если 0 - exporter не достучался до nginx, смотри имя сервиса и порт.
  • Шаг 5. Подними Prometheus, в scrape_configs добавь target nginx-exporter:9113. В UI Prometheus выполни запрос rate(nginx_http_requests_total[1m]) - погоняй curl-ом продовый эндпоинт и увидь, как RPS растёт на графике.
  • Шаг 6. Подними Grafana, добавь Prometheus как источник, импортируй готовый nginx-prometheus-exporter дашборд по ID из каталога Grafana. Любуйся живыми соединениями и RPS.
  • Шаг 7 (бонус). Если есть Angie - подними его вместо nginx, включи location /status/ с api и location с prometheus, и сравни: те же данные, но БЕЗ контейнера-экспортера, плюс per-upstream разбивка, которой у тебя только что не было.
контрольные вопросы
  • В выводе stub_status accepts равно 9000, а handled равно 8990. Что это значит и почему это повод для алерта?
  • Почему нельзя получить долю ответов 5xx и p95 latency напрямую из stub_status, и какие три способа решают это на nginx и Angie?
  • Зачем в конфиге метрик стоит access_log off в двух местах и какой набор allow/deny закрывает эндпоинт от внешнего мира?
  • Чем путь Angie (REST /status плюс нативный Prometheus) отличается от связки ванильный nginx плюс nginx-prometheus-exporter по архитектуре и по детальности метрик?
итог

stub_status - это семь цифр инстанс-уровня и фундамент мониторинга на ванильном nginx; чтобы они доехали до Grafana, нужен nginx-prometheus-exporter. Но детальной картины (5xx, latency, здоровье каждого апстрима, cache hit) из stub_status не выжмешь - для этого либо ngx_otel_module, либо переход на Angie, который отдаёт REST /status в JSON, нативный Prometheus и Console Light без единого стороннего бинарника. Мониторь золотые сигналы - долю 5xx, перцентили latency, здоровье пула, соединения, cache ratio - и алерти только на то, что требует действия. Метрики, которые никто не смотрит до инцидента, - это просто диски, забитые числами.

Источники для сверки: nginx.org (ngx_http_stub_status_module), github.com/nginx/nginx-prometheus-exporter, angie.software (console, http_prometheus, /status API).
👍7 ❤️2 🔥1 😄 🤔1
Аватара пользователя
patl18
Сообщения: 1
Зарегистрирован: 17 май 2026, 17:43

Re: Метрики и мониторинг Nginx

Сообщение patl18 »

Дельта accepts/handled зашла как откровение. Год снимаю stub_status и ни разу не вешал алерт на их расхождение - оказывается прямо отсюда видно дропы соединений. Спасибо!
👍 ❤️ 🔥 😄 🤔
Аватара пользователя
CudaVeteran
Сообщения: 1
Зарегистрирован: 01 июн 2026, 07:42

Re: Метрики и мониторинг Nginx

Сообщение CudaVeteran »

Поднял Angie на тесте по шагу 7 и реально снёс контейнер с exporter - метрики per-upstream теперь прямо из /status. Вопрос: prometheus_template из комплекта совместим со старым дашбордом под nginx-exporter или придётся новый импортить?
👍 ❤️1 🔥1 😄 🤔
Ответить
← Предыдущая глава
Сквозная трассировка запросов и OpenTelemetry
Следующая глава →
Производительность и тюнинг под нагрузку

Все главы курса «Nginx профессионально: от первого конфига до API-gateway на OpenResty и Angie»

Поделиться темой: ✈ Telegram VK
Похожие запросы: Мониторинг и метрики nginxAngie: форк nginx с нативными метриками

Вернуться в «Nginx профессионально: от первого конфига до API-gateway на OpenResty и Angie»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость