Webrium
Подписаться

Обратный прокси: что он решает и что ломает

Что он действительно снимает с приложения и что ломает молча

Прокси как граница: часть данных пересекает её и теряетсяснаруживнутри

Приложение умеет слушать порт и отвечать на запросы. Зачем тогда ставить перед ним ещё одну программу, которая просто передаёт запросы дальше? Ответ не в скорости и не в моде: прокси берёт на себя обязанности, которые иначе придётся реализовать в каждом приложении отдельно.

Что он снимает с приложения

Шифрование соединения. Сертификаты, их обновление, выбор протоколов, перенаправление с незащищённого адреса. Это работа, которую не хочется делать дважды, а при нескольких сервисах она умножается.

Один вход на много сервисов. Наружу торчит один адрес и один порт, внутри — десяток приложений на своих портах. Без прокси каждому нужен свой публичный порт, и адрес превращается в набор цифр.

Раздача статики. Файлы отдаёт программа, специально для этого написанная, а не приложение, которое в это время могло бы обрабатывать запросы.

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

Замена без разрыва. Прокси переключает поток на новую версию, старая дорабатывает начатые запросы. Читатель не видит момента подмены.

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

Отсюда следует ответ на исходный вопрос: прокси нужен не приложению, а системе, в которой приложений больше одного. Для единственного сервиса, отдающего только динамику и живущего без шифрования, он действительно лишний.

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

Тупик: настроить и забыть

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

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

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

Что ломается чаще всего

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

Размер тела. Предел у прокси меньше, чем у приложения. Загрузка файла падает, не дойдя до кода, и сообщение об ошибке приходит не то, которое написали разработчики.

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

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

Постоянные соединения. Соединения с обновлением протокола требуют явного разрешения. Без него они молча закрываются, и отладка уходит в приложение, где всё правильно.

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

Сжатие дважды. Приложение сжало ответ, прокси сжал ещё раз или, наоборот, распаковал и упаковал заново. Процессор тратится на работу, которая ничего не даёт, а иногда ломает заголовки о длине содержимого.

Что стоит настроить сразу

Согласовать тайм-ауты и пределы размера между прокси и приложением, записав их в одном месте. Разошедшиеся значения — источник ошибок, которые ищут в коде.

Передавать и принимать настоящий адрес клиента, с явным списком доверенных источников заголовка.

Отключить буферизацию там, где ответ потоковый, и оставить там, где нет.

Задать поведение при недоступном приложении: страница с понятным текстом вместо технического сообщения, и не кешировать её.

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

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

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

Позиция редакции

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

Мы неправы, если приложение одно, живёт за чужим управляемым балансировщиком и не отдаёт статики: там свой прокси добавит слой, который нечем оправдать.

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

С чем это связано

Метка над заголовком говорит, зачем туда идти: продолжить тему, перейти к практике или увидеть возражение.

Ответ из кеша совпадает с источником или разошёлся с нимсовпалоустарело
Практика

Кеширование по HTTP: заголовки, которые действительно работают

Руками по заголовкам: чем срок годности отличается от проверки и какие правила ставить, чтобы кеш не отдавал устаревшее.

Вложенные слои — поколения модных инструментов; в самой глубине выделен старый механизм, то, что осталось живым.старые механизмы
Усиление

Деплой без кластера: что осталось живым

Подтверждает вывод с другой стороны: кластер из одной ноды даёт всю сложность оркестратора и ни одной его выгоды.

Четыре показателя-поля трейса: ID запроса, шаг вызова и код ошибки в норме, а тело запроса уходит за шкалу — его место в архиве, а не в трейсетело запроса
Углубление

Что писать в трассировку, а что нет

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

Письмо по вторникам

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

Начните вводить — материалы появятся здесь.

выбрать · Enter открыть · Esc закрыть