Nginx

Что это такое

Nginx — это веб-сервер, который чаще всего развёртывают как обратный прокси: он принимает соединения от клиентов и передаёт их одному или нескольким приложениям позади себя. В этой роли он отдаёт статические файлы напрямую, завершает TLS, распределяет запросы по нескольким бэкендам и скрывает от внешнего мира настоящую топологию приложения. Это часть инфраструктуры, стоящая между интернетом и всем остальным.

Почему это важно

Почти в каждой продакшен-системе есть что-то на этой позиции, и понимание роли делает конфигурацию читаемой, а отказы — диагностируемыми. Обратный прокси — это то место, где действительно происходят ограничения соединений, тайм-ауты, буферизация и переписывание заголовков; поэтому удивительная доля инцидентов на сайте — обрезанная загрузка, медленный ответ без следа в источнике, клиент, видящий не ту схему, — на самом деле конфигурация прокси. Это ещё и самое дешёвое место добавить TLS, сжатие и статическое кэширование, не трогая код приложения.

Ключевые идеи

Соединение принимает прокси, а не приложение

Приложение за прокси может быть простым и медленно запускаться, потому что прокси держит соединение с клиентом, обслуживает медленного клиента в быстрой сети и даёт бэкенду ограниченный объём работы. Это разделение и есть причина существования такой схемы: обращённая к интернету забота и бизнес-логика разделены, и каждую можно масштабировать и заменять независимо.

клиент -> nginx (TLS, статические файлы, лимиты) -> серверы приложения

TLS завершается здесь, и это решает, какой будет схема

Шифрование на прокси означает, что сертификаты управляются в одном месте, а бэкенд говорит по простому HTTP внутри доверенной сети. Следствие, которое надо помнить: приложение видит обычный HTTP-запрос и может сгенерировать незащищённый адрес, если прокси не передаёт исходную схему и хост в заголовках. Отсюда классические проблемы смешанного содержимого и цикла перенаправлений.

Балансировка нагрузки — это выбор политики

Запросы можно распределять по кругу, по наименьшему числу соединений, по хешу какого-то ключа или с весами и переключением при отказе. Хеш удерживает клиента на одном бэкенде, что помогает, когда бэкенд хранит состояние сессии, и вредит, когда он падает. Осознанный выбор и решение о том, что происходит с нездоровым бэкендом, — вот что не даёт балансировке стать случайностью.

Буферизация и тайм-ауты решают судьбу загрузок и долгих запросов

Прокси может буферизовать тело запроса и ответ, прежде чем передать их дальше, что защищает медленный бэкенд от медленного клиента. Это также значит, что большая загрузка пишется на диск, а тайм-ауты запроса и ответа действуют на прокси, даже если приложение готово ждать дольше. Большинство сообщений «загрузка падает ровно на первой минуте» — это одна из таких настроек.

Статические файлы отдаются, не будя приложение

Прокси, отдающий изображения, таблицы стилей и загрузки напрямую, полностью убирает этот трафик из приложения. Это ещё и естественное место для заголовков кэширования и сжатия. То же верно для эндпоинтов проверки работоспособности, которыми пользуется балансировщик выше по потоку, — поэтому их часто отвечают прямо на прокси.

Это ещё и точка политики

Правила доступа, ограничения размера запроса и ограничение частоты живут здесь, до того как выполнится хоть строка кода приложения. Это делает прокси действенным местом, чтобы притупить грубую атаку или вышедшего из-под контроля клиента. Но это не замена безопасности на уровне приложения: корректно сформированный запрос, злоупотребляющий бизнес-логикой, проходит сквозь нетронутым.

Практика

Отдайте статический сайт через прокси

Поместите статический каталог за прокси, а приложение — за путём, и убедитесь, что статические файлы отдаются, не доходя до бэкенда.

Готово, когда: в логах приложения нет запроса по статическому пути, а ответ несёт заголовок кэширования прокси.

Проследите тайм-аут, вызванный прокси

Настройте тайм-аут запроса короче обычного времени ответа приложения, затем отправьте медленный запрос и прочитайте ответ, который клиент действительно получает.

Готово, когда: вы можете назвать настройку, вызвавшую этот ответ, и улику в логе прокси, которая её опознаёт.

Частые ошибки

  • Не передавать исходную схему и хост бэкенду — приложение генерирует неверные адреса, и перенаправления зацикливаются; исправить: передавайте заголовки схемы и хоста и доверяйте им только от прокси.
  • Оставить ограничение размера тела запроса по умолчанию — большая загрузка отвергается с непонятной ошибкой; исправить: задайте предел под то, что ожидает приложение.
  • Балансировать по хешу, ожидая переключения при отказе — клиенты остаются прикреплёнными к упавшему бэкенду; исправить: выбирайте политику осознанно и определите поведение при нездоровом бэкенде.
  • Считать прокси единственным средством безопасности — валидные запросы, злоупотребляющие бизнес-логикой, проходят; исправить: сохраняйте авторизацию и валидацию на уровне приложения.
  • Игнорировать тайм-ауты прокси, когда запрос законно долгий — клиента обрывают, пока бэкенд продолжает работать; исправить: согласуйте тайм-ауты прокси с реальным временем ответа приложения.

Что читать дальше

  • Основы сетей (HTTP / DNS / TLS) (06-cloud-devops/10-networking-fundamentals-http-dns-tls) — протоколы, которые этот прокси завершает и пересылает, поэтому читайте первым.
  • CI/CD (06-cloud-devops/08-ci-cd) — как изменение конфигурации прокси тестируется и выпускается вместе с приложением, которое он обслуживает.
  • Docker (06-cloud-devops/06-docker) — распространённый способ упаковать прокси и его бэкенды и запускать их вместе.