apt update
apt install nginx -y
CentOS
yum install nginx -y
systemctl enable nginx
Установка более свежей версии из исходников
cd /opt/
wget [https://nginx.org/download/nginx-1.25.3.tar.gz](https://nginx.org/download/nginx-1.25.3.tar.gz)
tar zxf nginx-1.25.3.tar.gz nginx-1.25.3/
cd nginx-1.25.3/
Конфиг, как у нас на sy-live, если нужен перенос, то смотри другой конфиг с помощью nginx -V
./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/sy/log/nginx/default/error/error.log --http-log-path=/sy/log/nginx/default/access/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
[Install]
WantedBy=multi-user.target
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/sbin/nginx-debug -t -c /etc/nginx/nginx.conf
ExecStart=/usr/sbin/nginx-debug -c /etc/nginx/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
[Install]
WantedBy=multi-user.target
Проверить конфиг
или
Проверить конфиг по-умолчанию
Вывести весь окончательный конфиг (особенно полезно, когда много файлов дополнительно подключается и нужно оценить как все это видит nginx после подключения)
Просмотреть все модули, которые включены в nginx, включая остальные настройки сборки
но если только модули, то удобнее смотреть так
Перезагрузить конфиг
Лучше так, а не через systemctl reload (показывает ошибки и реально перегружает, а не делает вид). Особенно критично для конфигов модулей nginx
Если трафик идет через IPv6, например, localhost - это ::1, то в конфиге сайта
allow ::1;
stub status page
server {
listen localhost;
server_name status.localhost;
keepalive_timeout 0;
access_log off;
allow 127.0.0.1;
allow ::1;
deny all;
location /basic_status {
stub_status on;
}
}
HTTP/1.1 200 OK
Server: nginx/1.14.1
Date: Tue, 23 May 2023 22:01:46 GMT
Content-Type: text/plain
Connection: close
Ошибки
Ошибка в веб-интерфейсе при добавлении файла, что файл слишком большой, хотя по размеру должен проходить, например, для redmine:
Request Entity Too Large
http {
...
client_max_body_size 0;
...
}
Ошибка в логах одного из сайтов
connect() to unix:/var/run/php-fpm/php-fpm.sock failed (2: No such file or directory) while connecting to upstream, client: XX.XX.XX.XX, server: srv.net, request: "GET / HTTP/2.0", upstream: "fastcgi://unix:/var/run/php-fpm/php-fpm.sock:", host: "srv.net"
Неверно задан путь к php-fpm.sock
Ищем правильный путь к php-fpm.sock
Исправляем
fastcgi_pass unix:/run/php-fpm/www.sock;
Это старье
nginx bad block blocker
https://github.com/mitchellkrogza/nginx-badbot-blocker
Установка
...
http {
...
include nginx-badbot-blocker/blacklist.conf;
include nginx-badbot-blocker/blockips.conf;
}
symfio
Блокировка ip и сетей
...
deny 178.238.234.1;
deny 45.114.224.0/22;
deny 49.12.0.0/16;
...
Блокировка пользовательских агентов и реферреров. По-умолчанию настроен
nginx-ultimate-bad-bot-blocker
https://github.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker
Nginx Bad Bot and User-Agent Blocker, Spam Referrer Blocker, Anti DDOS, Bad IP Blocker and Wordpress Theme Detector Blocker
Классный блокер ботов и замедлитель их запросов. Крупный обновляемый проект от специалиста по безопасности. У него еще есть интересные проекты, в частности обновляемый fail2ban фильтр от разных эксплойтов. Тоже полезно было бы его внедрить.
или
dry-run
Скачиваем все необходимые файлы по папкам
dry-run
-e conf - означает расширение на которое заканчиваются все наши vhost (если .vhost, то вообще этот параметр не надо), обычно рекомендуется для nginx для vhost иметь расширение именно .vhost, но будет работать и так
Добавить вот это включение во все vhost nginx или во все conf, также добавит nginx.conf include /etc/nginx/conf.d/*, если этого еще нет
include /etc/nginx/bots.d/ddos.conf;
include /etc/nginx/bots.d/blockbots.conf;
Рекомендуется добавить (можно даже чаще обновлять), потому что разработчик обновляет 3-4 раза в день. И свою почту указать, чтобы знать, что происходило, если вдруг будет EMERG nginx'а после релоада (что-то не так с конфигом)
00 22 * * * sudo /usr/local/sbin/update-ngxblocker -e yourname@youremail.com
Добавление заголовков (header'ов)
Например, на sy-dev. Добавляются заголовки для URL-ссылок, которые содержат папку assets
location ~ /(assets)
{
# add_header Access-Control-Allow-Origin "admin.symfio.net|admin.dev.symfio.net";
add_header Access-Control-Allow-Origin *;
add_header access-control-allow-headers "X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Authorization";
add_header access-control-allow-credentials true;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
if ($request_method = OPTIONS ) {
add_header "Access-Control-Allow-Origin" *;
add_header "Access-Control-Allow-Credentials" "true";
add_header "Access-Control-Allow-Headers" "X-API-KEY, Origin, X-Requested-With, Content-Type, Content-Disposition, Accept, Access-Control-Request-Method, Authorization, X-Current-Location";
add_header "Access-Control-Allow-Methods" "GET, POST, PUT, DELETE, OPTIONS";
return 200;
}
}
Логирование
Дополнительно https://docs.nginx.com/nginx/admin-guide/monitoring/debugging/
Уровни логирования
debug
info
warn
error
crit
alert
emerg
Формат лога
From reading src/core/ngx_log.c I guess the general error log format seems to be
YYYY/MM/DD HH:MM:SS [LEVEL] PID#TID: *CID MESSAGE
With PID and TID being the logging process and thread id and CID a number identifying a (probably proxied) connection, probably a counter. The *CID part is optional.
nginx -V 2>&1 | grep arguments
Ищем debug
nginx -V 2>&1 | grep -- '--with-debug'
Включаем
error_log /var/log/nginx/error.log debug;
...
http {
...
error_log /var/log/nginx/error.log debug;
Лог на доступ
http {
...
access_log /var/log/nginx/access.log main;
Может быть в памяти
error_log memory:32m debug;
Можно по конкретным IP
error_log /path/to/log;
...
events {
debug_connection 192.168.1.1;
debug_connection 192.168.10.0/24;
}
Для каждого или конкретного хоста
Обычно в основном контексте применяется для всех хостов, но если внутри определенного сервера или блока местоположения, например, для блоков http, server, stream и location, указана другая директрива error_log, то глобальные настройки будут переопределены и такая директива установит свой собственный путь к файлу лога, а также уровень логирования
error_log /path1/to/log debug;
...
http {
...
server {
error_log /path2/to/log debug;
...
}
}
Или, например, отключить ведение лога для определенного хоста (просто указать директиву и путь без уровня логирования)
error_log /path/to/log debug;
...
http {
...
server {
error_log /path/to/log;
...
}
}
rate limit
map size не обязательно - работает и без него
для пропуска либо # либо "", любое другое значение как идентификатор и относит к этой группе, также, если ввести в конце default $binary_remote_addr, то все, кроме тех, которые "" будут восприниматься, как относящиеся к группе, типа любой адрес по-умолчанию. "" - вынуждает просто пропустить этот адрес
include - позволяет просто включить в таком формате файл, где прописаны, относящиеся к этому лимиту ip-адреса
$limit_bot и $limit_bot_google - позволяет указать лимиты по user-agent - используется при этом вариант регулярного выражения
Siege/4.1.4 - это agent siege - утилиты для тестирования нагрузки на веб-сервер
Сами лимиты по времени реализуются просто, например, если не стандартный 1 запрос в 2 секунды - это 30 запросов в 1 минуту по сути.
map_hash_max_size 4096;
map_hash_bucket_size 128;
map $remote_addr $limit_ip {
159.69.249.10 "";
# include /etc/nginx/conf.d/blacklist_facebook1.txt;
# default $binary_remote_addr;
}
map $http_user_agent $limit_bot {
default "";
~*(Bytespider) $http_user_agent;
~*(Siege/4.1.4) $http_user_agent;
}
map $http_user_agent $limit_bot_google {
default "";
~*(Bytespider) $http_user_agent;
# ~*(Siege/4.1.4) $http_user_agent;
}
limit_req_zone $limit_ip zone=ip:20m rate=3r/m;
limit_req_zone $limit_bot zone=bots:20m rate=10r/m;
limit_req_zone $limit_bot_google zone=bots_google:20m rate=30r/m;
limit_req_zone $binary_remote_addr zone=one:20m rate=190r/s;
В блоке server {...} вводим непосредственно включение limit'ов, burst по сути размер буфера для запросов, которые приходят чаще, чем установленное время между запросами - когда заполнится начнет отбрасываться и давать ошибку, nodelay - в использовании просто burst есть изъян - если запрос поступил раньше определенного нами времени, то он помещается в обработку соответственно нашего установленного rate limit - т.е. сервер делает соответствующую паузу, но если добавить nodelay, то этой паузы не будет и ответ будет дан немедленно, но вот очищается буфер согласно паузе установленного нами rate limit - т.е. если поступит запросов больше, чем уже очищено в буфере (burst), то такие просто будут отброшены, иначе обработаны сразу - команда nginx рекомендует использовать оба параметра вместе для лучшей эффективности, status - что будет выдавать в случае превышения - можно любую ошибку HTTP
server {
server_name ab-automobile-norderstedt.de *.ab-automobile-norderstedt.de;
ssl_certificate /etc/letsencrypt/live/ab-automobile-norderstedt.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ab-automobile-norderstedt.de/privkey.pem;
# rewrite ^(.+)$ https://ab-automobile-norderstedt.de7$1 permanent;
include /etc/nginx/conf.d/symfio/_ssl_template.txt;
}
nano /etc/nginx/conf.d/symfio/_ssl_template.txt
limit_req zone=ip burst=4;
limit_req zone=bots burst=4;
limit_req zone=bots_google burst=4;
limit_req zone=one burst=65 nodelay;
limit_req_status 429;
Если нужно по-разному обрабатывать IP-адреса
Сначала делаем список белых IP (они будут без лимита). А в map все остальные, которые лимит имеют
nano /etc/nginx/conf.d/nginx.conf
geo $one {
default 1;
88.198.68.180 0; # исключаем этот IP из зоны
2a01:4f8:140:40b5::2 0; # и этот тоже - оба sy-jenkins
}
map $one $one_key {
0 "";
1 $binary_remote_addr;
}
limit_req_zone $limit_bot zone=bots:10m rate=1r/s;
limit_req_zone $limit_bot_chatgpt zone=bots_chatgpt:10m rate=30r/m;
limit_req_zone $limit_bot_google zone=bots_google:10m rate=10r/s;
limit_req_zone $one_key zone=one_all:20m rate=190r/s;
nano /etc/nginx/conf.d/symfio/_ssl_template_81.txt
limit_req zone=bots burst=4;
limit_req zone=bots_chatgpt burst=2;
limit_req zone=bots_google burst=4;
limit_req zone=one_all burst=65 nodelay;
limit_req_status 429;
\
Facebook / Meta crawler 429 на sy-live
Симптом: Facebook Sharing Debugger или рекламный переход через Meta жалуется на 429 Too Many Requests, при этом обычный браузер получает 200. В access log обычно видно facebookexternalhit, Facebot, meta-externalagent, meta-externalads. Если request_time около 0.000, а upstream-поля пустые, значит ответ дал сам nginx через limit_req, до PHP-FPM.
Проверка:
# домен и URL из обращения
DOMAIN=autohaus-dietz-gmbh.de
URL=/de/achsvermessung-wildau
# конфиг и активные limit_req
nginx -T 2>/dev/null | grep -nE 'limit_req|limit_req_zone|facebook|meta-external|Facebot|facebookexternalhit'
# ошибки nginx rate limit
grep -i "$DOMAIN" /sy/log/nginx/symfio_81_dealers/errors/symfio_81_dealers_error.log | grep 'limiting requests' | tail -50
# ручной тест crawler UA
curl -4 -k -A 'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)' \
-o /dev/null -s -w 'status=%{http_code} time=%{time_total}\n' \
"https://$DOMAIN$URL"
Важно: не отключать Facebook / Meta crawler глобально из общего bot limit. На sy-live это может открыть crawler-трафик по всем дилерским доменам, забить PHP-FPM и нагрузить MongoDB. Если нужно решить проблему для одного клиента, делаем отдельный host-scoped лимит.
Пример: оставить старую зону bots для всех доменов, но для autohaus-dietz-gmbh.de вывести Meta crawler в отдельную зону bots_meta_autohaus.
В /etc/nginx/nginx.conf общий bot map делаем по $host:$http_user_agent, чтобы исключение сработало только для нужного домена:
map "$host:$http_user_agent" $limit_bot {
default "";
~*(Amazonbot) "amazonbot";
~*(DotBot) "dotbot";
~*(YandexBot) "yandexbot";
~*(AwarioBot) "awariobot";
~*(wpbot) "wpbot";
~*(MJ12bot) "mj12bot";
~*(PerplexityBot) "perplexitybot";
~*(PetalBot) "petalbot";
~*(serpstatbot) "serpstatbot";
# Только этот домен не попадает в старый жесткий facebook limit.
~*^(?:.+\.)?autohaus-dietz-gmbh\.de:.*(?:facebookexternalhit|Facebot|meta-externalagent|meta-externalads) "";
# Для остальных доменов Facebook / Meta остается в общей bot-зоне.
~*(facebook) "facebook";
}
map "$host:$http_user_agent" $limit_bot_meta_autohaus {
default "";
~*^(?:.+\.)?autohaus-dietz-gmbh\.de:.*(?:facebookexternalhit|Facebot|meta-externalagent|meta-externalads) "fb_autohaus";
}
limit_req_zone $limit_bot zone=bots:10m rate=5r/m;
limit_req_zone $limit_bot_meta_autohaus zone=bots_meta_autohaus:10m rate=30r/m;
В общем include для дилерских доменов, например /etc/nginx/conf.d/symfio/_ssl_template.txt, добавить новую зону рядом со старой:
limit_req zone=bots burst=2;
limit_req zone=bots_meta_autohaus burst=10;
limit_req zone=bots_ai burst=2;
limit_req zone=bots_search burst=4;
limit_req zone=one_all burst=65 nodelay;
limit_req_status 429;
Применение:
cp -a /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak-$(date +%Y%m%d%H%M%S)
cp -a /etc/nginx/conf.d/symfio/_ssl_template.txt /etc/nginx/conf.d/symfio/_ssl_template.txt.bak-$(date +%Y%m%d%H%M%S)
nginx -t
nginx -s reload
# нужный домен должен пройти
curl -4 -k -A 'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)' \
-o /dev/null -s -w 'autohaus_fb status=%{http_code} time=%{time_total}\n' \
https://autohaus-dietz-gmbh.de/de/achsvermessung-wildau
# другой домен должен остаться под старым лимитом
curl -4 -k -A 'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)' \
-o /dev/null -s -w 'other_fb status=%{http_code} time=%{time_total}\n' \
https://autohaus-lotzenaecker.de/
# обычный запрос должен быть быстрым
curl -4 -k -o /dev/null -s -w 'normal status=%{http_code} time=%{time_total}\n' \
https://autohaus-dietz-gmbh.de/de/achsvermessung-wildau
uptime
tail -n 80 /sy/log/nginx/symfio_81_dealers/errors/symfio_81_dealers_error.log | \
grep -E 'Resource temporarily unavailable|bots_meta_autohaus|server: autohaus-dietz-gmbh.de'
Ожидаемый результат:
autohaus_fb status=200
other_fb status=429
normal status=200
Если после изменения растет load или появляются ошибки connect() to unix:/var/run/php-fpm/php-fpm.sock failed (11: Resource temporarily unavailable), сразу откатываем backup и перезапускаем PHP-FPM только если воркеры уже забиты:
cp -a /etc/nginx/nginx.conf.bak-YYYYMMDDHHMMSS /etc/nginx/nginx.conf
cp -a /etc/nginx/conf.d/symfio/_ssl_template.txt.bak-YYYYMMDDHHMMSS /etc/nginx/conf.d/symfio/_ssl_template.txt
nginx -t && nginx -s reload
# если php-fpm уже забит очередью
systemctl restart php-fpm
symfio sy-live логи:
Структура sy-live:
Дилеры и подсайты
/etc/nginx/conf.d/symfio/
Дополнительные настройки на некоторых (или всех) поддоменах
/etc/nginx/conf.d/symfio/_ssl_template.txt
Скрипты (также деплоятся из sy-jenkins в /var/lib/jenkins/workspace/Symfio/Backend/Live.Updade.SY/config/deploy.rb)
/sy/scripts/consumers
Убранные (sf3_rabbitmq_caratana.sh тут)
/sy/scripts/consumers/del
Позволяет на одном IP разделять куда будут идти запросы внутри сети и обойтись одним IP для кучи доменов
Nginx конфигурация с upstream:
nano /etc/nginx/sites-available/proxy
# Upstream для Proxmox Web UI
upstream proxmox_backend {
server 127.0.0.1:8006;
}
# Upstream для Exchange виртуалки
upstream exchange_backend {
server 192.168.1.100:443; # Внутренний IP виртуалки с Exchange
}
# Proxmox VE Web UI
server {
listen 443 ssl;
http2 on;
server_name pve.symfio.net;
ssl_certificate /etc/letsencrypt/live/pve.symfio.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/pve.symfio.net/privkey.pem;
location / {
proxy_pass https://proxmox_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Proxmox WebSocket support
proxy_buffering off;
client_max_body_size 0;
proxy_connect_timeout 3600s;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
send_timeout 3600s;
}
}
# Exchange Autodiscover
server {
listen 443 ssl;
http2 on;
server_name autodiscover.gabelstapler-zentrum.at;
ssl_certificate /etc/letsencrypt/live/autodiscover.gabelstapler-zentrum.at/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/autodiscover.gabelstapler-zentrum.at/privkey.pem;
location / {
proxy_pass https://exchange_backend;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Exchange specific
proxy_buffering off;
client_max_body_size 50M;
}
}
# Exchange Mail (OWA/ECP/ActiveSync)
server {
listen 443 ssl;
http2 on;
server_name mail.gabelstapler-zentrum.at;
ssl_certificate /etc/letsencrypt/live/mail.gabelstapler-zentrum.at/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mail.gabelstapler-zentrum.at/privkey.pem;
location / {
proxy_pass https://exchange_backend;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Exchange OWA/ActiveSync
proxy_buffering off;
client_max_body_size 50M;
proxy_read_timeout 300s;
}
}
# HTTP redirect to HTTPS
server {
listen 80;
server_name pve.symfio.net mail.gabelstapler-zentrum.at autodiscover.gabelstapler-zentrum.at;
return 301 https://$host$request_uri;
}
Создать симлинк
ln -s /etc/nginx/sites-available/proxy /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
Получить SSL сертификаты (Let's Encrypt): Получить сертификаты
certbot certonly --nginx -d pve.symfio.net
certbot certonly --nginx -d mail.gabelstapler-zentrum.at
certbot certonly --nginx -d autodiscover.gabelstapler-zentrum.at
systemctl status certbot.timer
# Проверить upstream
curl -I https://pve.symfio.net
# Проверить Exchange
curl -I https://mail.gabelstapler-zentrum.at
curl -I https://autodiscover.gabelstapler-zentrum.at
Потом просто меняешь IP в upstream exchange_backend
nano /etc/nginx/sites-available/proxy
upstream exchange_backend {
server 192.168.1.200:443; # Новый IP виртуалки
}
nginx -t && systemctl reload nginx
$requestДоступные переменные nginx: ┌─────────────────────────┬────────────────────────────┐ │ Переменная │ Пример │ ├─────────────────────────┼────────────────────────────┤ │ $request │ GET /page?id=1 HTTP/1.1 │ ├─────────────────────────┼────────────────────────────┤ │ $request_method │ GET │ ├─────────────────────────┼────────────────────────────┤ │ $request_uri │ /page?id=1 │ ├─────────────────────────┼────────────────────────────┤ │ $uri │ /page (без query string) │ ├─────────────────────────┼────────────────────────────┤ │ $args │ id=1 (только query string) │ ├─────────────────────────┼────────────────────────────┤ │ $server_protocol │ HTTP/1.1 │ ├─────────────────────────┼────────────────────────────┤ │ $request_time │ 0.123 (секунды) │ ├─────────────────────────┼────────────────────────────┤ │ $upstream_response_time │ 0.100 │ └─────────────────────────┴────────────────────────────┘
$___timeКлиент → Nginx → PHP-FPM → Nginx → Клиент Временная шкала запроса: |-------- upstream_connect_timeЧто измеряет: Время установки соединения с бэкендом Пример: 0.001 - сеть до php-fpm ──────────────────────────────────────── Переменная:upstream_response_timeЧто измеряет: Полное время ответа бэкенда Пример: 0.200 - всё, включая передачу body ──────────────────────────────────────── Переменная:$request_time` Что измеряет: Полное время запроса (клиент → nginx → бэкенд → nginx → клиент) Пример: 0.250
┌────────────────────────────────────┬─────────────────────────────────┐ │ Симптом │ Причина │ ├────────────────────────────────────┼─────────────────────────────────┤ │ connect_time высокий │ Проблема сети или бэкенд не │ │ │принимает соединения (пул занят) │ ├────────────────────────────────────┼─────────────────────────────────┤ │ header_time высокий │ Бэкенд долго обрабатывает запрос│ │ │ (тяжёлый код, БД) │ ├────────────────────────────────────┼─────────────────────────────────┤ │ response_time - header_time высокий│Большой ответ, медленнаяпередача │ ├────────────────────────────────────┼─────────────────────────────────┤ │ request_time - response_time │ Медленный клиент │ │ высокий │ (мобильный интернет) │ └────────────────────────────────────┴─────────────────────────────────┘ Добавить в лог json или обычный формат: '"upstream_connect_time":"upstream_connect_time",' '"upstream_header_time":"upstream_header_time",' '"upstream_response_time":"upstream_response_time",' '"request_time":"request_time"'
Если $___time пустой или 0.000
Пример в логах:
# Запрос к php-fpm
request_time=0.150 upstream_connect=0.000 upstream_header=0.120 upstream_response=0.148
# Статика или 429
request_time=0.001 upstream_connect=- upstream_header=- upstream_response=-
# Для аналитики полезно фильтровать:
# Только запросы которые дошли до бэкенда
{job="sy-live-nginx"} | json | upstream_response_time!=""
# Медленные запросы к бэкенду (>1s)
{job="sy-live-nginx"} | json | upstream_response_time > 1