5.8 KiB
Вопросы: Nginx
Опираются на кейс: CASE.md.
Чем reverse proxy отличается от обычного proxy?
Обычный (forward) proxy работает на стороне клиента — скрывает клиента от сервера. Reverse proxy стоит перед сервером(ами) и скрывает их от клиента — клиент обращается к одному адресу, а Nginx уже сам решает, на какой бэкенд отправить запрос. В своём кейсе я как раз настроил Nginx как reverse proxy перед двумя бэкендами через upstream + proxy_pass.
Какие алгоритмы балансировки нагрузки есть в Nginx и в чём разница?
По умолчанию — round-robin (запросы по очереди). least_conn — на сервер с наименьшим числом активных соединений (я использовал именно его в лабе, чтобы не заливать один инстанс, если он медленнее отвечает). ip_hash — привязывает клиента к одному и тому же серверу по хешу IP, что полезно для sticky-сессий, если приложение не умеет в shared-сессии.
Зачем нужны proxy_set_header в конфиге?
По умолчанию бэкенд видит IP и Host самого Nginx, а не реального клиента, потому что запрос проксируется. proxy_set_header X-Real-IP $remote_addr и X-Forwarded-For передают реальный IP клиента дальше, а Host $host сохраняет исходный заголовок Host — это важно, если бэкенд как-то зависит от домена или логирует IP клиентов.
Как Nginx понимает, что бэкенд «упал», и что делает в этом случае?
Через пассивные health-check параметры в upstream: max_fails — сколько неудачных попыток допустимо, fail_timeout — на сколько сервер помечается недоступным после превышения max_fails. В моём кейсе я гасил один из бэкендов и видел, что Nginx перестаёт направлять на него трафик и весь поток идёт на оставшийся, без ошибок для клиента.
Что такое rate limiting и как он настроен в Nginx?
limit_req_zone объявляет зону в разделяемой памяти, ключ (обычно $binary_remote_addr, то есть IP клиента) и допустимую скорость запросов (rate=5r/s в моём случае). limit_req в конкретном location применяет эту зону, а burst разрешает кратковременный всплеск сверх лимита (запросы ставятся в очередь) — nodelay убирает искусственную задержку для burst-запросов, но всё равно возвращает 503 при превышении burst. Я специально прогонял 20 запросов подряд и видел 503 после исчерпания лимита.
В чём разница между location / и отдельным location /health?
location определяет, как обрабатывается конкретный путь URL. Я вынес /health в отдельный блок, который отвечает статикой (return 200) без проксирования на бэкенд — так делают health-check эндпоинты, чтобы проверка живости самого Nginx/прокси-слоя не зависела от состояния бэкендов.
Чем отличается $host от $http_host и от server_name?
server_name — значение в конфиге, по которому Nginx выбирает нужный server-блок для запроса. $host — переменная времени выполнения: значение из заголовка Host запроса (без порта), либо server_name, если заголовка нет. $http_host — заголовок Host как есть, включая порт, если он был передан клиентом. На практике для проксирования обычно используют $host, чтобы не тащить порт туда, где он не нужен.
Как бы вы отдавали статику через Nginx, а не проксировали на бэкенд?
Через location с директивой root/alias, указывающей на директорию со статикой, вместо proxy_pass — тогда Nginx сам отдаёт файлы, не дёргая бэкенд, что быстрее и снимает нагрузку с приложения.
Что произойдёт, если в upstream все сервера окажутся недоступны?
Nginx вернёт ошибку (обычно 502 Bad Gateway или 504 Gateway Timeout, в зависимости от того, где именно произошёл сбой — на этапе соединения или ожидания ответа) — в моём кейсе, если бы я остановил оба backend1 и backend2, curl к proxy начал бы получать 502.