В каких случаях выбор L4-балансировщика вместо L7 лишает систему маршрутизации по содержимому HTTP-запроса?
L4-балансировщик работает на транспортном уровне и принимает решения по IP-адресам, портам и состоянию TCP или UDP-соединения. Он не видит HTTP-метод, путь, заголовки и содержимое запроса, поэтому не может направить /orders и /payments в разные сервисы. Для такой маршрутизации нужен L7-балансировщик, который завершает или анализирует прикладной протокол.
Первые балансировщики в основном распределяли сетевые соединения между серверами. Работа на уровне TCP или UDP была проще, быстрее и не требовала понимания конкретного прикладного протокола.
По мере роста микросервисов стало необходимо направлять запросы по домену, URL-пути, HTTP-заголовкам и другим признакам. Так появились и получили широкое применение L7-балансировщики и обратные прокси, способные принимать решения на уровне HTTP.
Предположим, один внешний адрес обслуживает несколько API: запросы к /orders должны попадать в сервис заказов, а запросы к /payments — в платёжный сервис. Если перед ними установлен только L4-балансировщик, он видит одно TCP-соединение с общим адресом и портом, но не знает, какой HTTP-путь передан внутри.
Попытка решить задачу только настройками L4 приведёт либо к распределению соединений между несовместимыми сервисами, либо к необходимости выделять отдельные IP-адреса или порты. Это усложняет публичный API, увеличивает число инфраструктурных ресурсов и не решает задачи маршрутизации по заголовкам, cookies или HTTP-методам.
L4-балансировщик принимает решение до разбора HTTP. Он может выбрать backend по адресу назначения, порту, протоколу, хешу соединения или другим сетевым признакам. После выбора он обычно пересылает поток байтов, не интерпретируя его как HTTP-запрос.
L7-балансировщик принимает TCP-соединение или работает за уже установленным защищённым каналом, разбирает HTTP и использует прикладные признаки: host, URL-путь, метод, заголовки и иногда cookies. Поэтому он может реализовать маршруты вроде «все запросы к одному домену — в один пул, а путь /v2 — в другой».
Цена L7 — дополнительная обработка и часто завершение TLS на балансировщике. Это увеличивает требования к CPU, добавляет задержку и требует корректной передачи исходного адреса клиента, например через заголовки или отдельные механизмы проксирования. Если TLS проходит сквозь балансировщик без расшифровки, он теряет возможность анализировать HTTP и фактически работает как L4 для этого трафика.
L4 предпочтителен, когда важны высокая производительность, минимальная задержка, прозрачная передача протокола или работа с TCP/UDP, который балансировщик не умеет интерпретировать. L7 оправдан, когда маршрутизация, защита и политики зависят от содержания запроса.
Важно различать маршрутизацию соединений и маршрутизацию запросов. L4 обычно выбирает backend для соединения, поэтому несколько HTTP-запросов в одном keep-alive-соединении не обязаны распределяться независимо. L7 может принимать решение для каждого запроса, но конкретное поведение зависит от реализации и настроек прокси.
Компания размещает несколько HTTP-сервисов за одним публичным адресом. Сначала выбран L4-балансировщик: он прост, хорошо масштабируется и поддерживает TLS passthrough. Однако после появления версий API /v1 и /v2 потребовалось направлять их в разные пулы.
Рассматривались три варианта. Выделение отдельных портов сохраняло L4-модель, но делало API менее удобным и требовало изменений у клиентов. Выделение отдельных IP-адресов решало проблему маршрутизации, но увеличивало стоимость и операционную сложность. Переход на L7 добавлял обработку TLS и зависимость от HTTP-прокси, зато позволял централизованно маршрутизировать запросы по host и path.
Выбрали L7-балансировщик с завершением TLS и явной передачей исходного адреса клиента в доверенном заголовке. L4 оставили для потокового TCP-трафика, где анализ содержимого не нужен. В результате HTTP-маршруты стали управляться независимо от портов и IP-адресов, а для непрозрачных протоколов сохранились производительность и прозрачность L4.
1. Может ли L4-балансировщик распределять отдельные HTTP-запросы из одного keep-alive-соединения?
Обычно нет. L4 видит транспортное соединение, а не границы HTTP-запросов, поэтому выбранный backend закрепляется за соединением или потоком. Независимое распределение запросов требует разбора HTTP на L7.
2. Можно ли использовать L7-маршрутизацию при сквозном TLS?
Полноценная маршрутизация по пути, методу и заголовкам невозможна, пока балансировщик не получит расшифрованный HTTP. Он может использовать имя сервера из TLS ClientHello, если доступен SNI, но это не заменяет анализ URL и других HTTP-полей.
3. Почему переход на L7 может изменить видимый IP-адрес клиента для приложения?
При завершении соединения на L7 балансировщик устанавливает отдельное соединение с backend. Приложение видит адрес прокси, если исходный адрес не передан доверенным способом и не обработан на backend. Поэтому необходимо настроить передачу клиентского адреса и ограничить доверие к соответствующим заголовкам, иначе их можно подделать напрямую.