Маршрутизация на L7: балансировка HTTP, gRPC и WebSocket, настройка Nginx, Traefik и Envoy | AdminWiki

Маршрутизация на L7: балансировка HTTP, gRPC и WebSocket, настройка Nginx, Traefik и Envoy

20 сентября 2026 15 мин. чтения

L7-балансировщик читает прикладной протокол (HTTP/1.1, HTTP/2, gRPC или WebSocket) и решает, куда направить конкретный запрос: по URL, домену, заголовкам, cookie, весам или содержимому. L4-балансировщик работает с потоком TCP или UDP, видит только IP-адрес и порт, а прикладной слой не разбирает. Отсюда расходятся и возможности, и стоимость решения.

Гибкость L7 оплачивается ресурсами. Балансировщику приходится завершать TLS, парсить заголовки, держать состояние сессий и иногда буферизовать тела запросов. Вычислительная работа на каждый запрос выше, чем при простой пересылке байтов на L4, а точные цифры зависят от профиля трафика, размера запросов и включённых функций. Публичные замеры по этой теме в приведённых источниках не собраны, поэтому перед продакшеном опирайтесь на собственные нагрузочные тесты, а не на общие оценки.

Выбирайте L7, когда за одним входом стоит несколько сервисов, когда нужны gRPC, WebSocket, канареечные релизы или маршрутизация по cookie. Оставайтесь на L4 для чистого TCP-проброса, кластеров баз данных и задач, где приоритет у пропускной способности и минимальной задержки. WebSocket удобен как наглядный пример: он работает поверх TCP и начинается как обычный HTTP-запрос с предложением изменить протокол соединения (механика рукопожатия WebSocket). Значит, L7-балансировщик видит это рукопожатие и может направить его по URL и заголовкам, а L4 видит только поток.

Фрагменты конфигураций ниже даны как справочные шаблоны типовых задач. Синтаксис и доступные директивы зависят от версии продукта: сверяйте параметры с документацией именно вашей версии Nginx, Traefik и Envoy перед применением в продакшене.

Что такое L7-маршрутизация и чем она отличается от L4

L7-маршрутизация смотрит на прикладной протокол и принимает решение по его содержимому: метод, путь, домен, заголовки, cookie, конкретный gRPC-сервис или WebSocket-рукопожатие. L4-маршрутизация работает с транспортным потоком и оперирует парой IP-адрес плюс порт. Разница практическая: L7 разведёт десять сервисов под одним адресом на порту 443, а L4 разведёт их только по отдельным портам или адресам. Разбор уровней с привязкой к модели OSI и конкретным протоколам собран в материале про уровни маршрутизации L2-L7.

Если нужен чистый TCP-проброс без чтения прикладного слоя, смотрите на балансировку TCP/UDP через HAProxy и Nginx Stream. L4 не завершает TLS, не парсит заголовки и не хранит состояние HTTP-сессий, поэтому пропускает больше соединений на том же железе.

Ключевые отличия L4 и L7 в одной таблице

КритерийL4L7
Уровень модели OSIТранспортный (4)Прикладной (7)
Что видит балансировщикIP-адрес, порт, TCP/UDP-потокМетод, URL, Host, заголовки, cookie, HTTP/2-фреймы
Типичные решенияHAProxy в режиме TCP, IPVS, Nginx streamNginx (http), Traefik, Envoy
Правила маршрутизацииПо IP и портуПо пути, домену, заголовкам, cookie, весам
TLSPassthrough: шифрование сохраняетсяТерминация или re-encryption до бэкенда
Health-checkУспешное TCP-подключениеHTTP GET с кодом 200, gRPC Health, анализ кодов ответов
Стоимость обработкиПересылка байтов, минимум вычисленийРазбор протокола, TLS, буферизация, состояние сессий
Типичный сценарийБазы данных, SSH, DNS, произвольный TCPIngress микросервисов, API-шлюз, real-time трафик

Обратите внимание на строку про стоимость: L7 не «медленнее» в абсолюте, он делает больше работы на запрос. На статике и больших файлах разница малозаметна, на тысячах мелких API-вызовов с TLS-терминацией она проявляется сильнее.

Когда L7 оправдан, а когда избыточен

Задачи, где L7 экономит время и упрощает схему:

  • Мультисервисный ingress: домен api.example.com и пути /api, /media, /ws ведут на разные бэкенды под общим сертификатом.
  • gRPC: протокол требует HTTP/2, а распределять его запросы можно только на прикладном уровне.
  • WebSocket: рукопожатие проходит по HTTP, поэтому балансировщик может направить его по пути и заголовкам, а дальше держать долгоживущее соединение.
  • Канареечные релизы и A/B: 5 процентов трафика уходит на новую версию, остальные 95 на стабильную.
  • Маршрутизация по cookie: сессия привязана к конкретной реплике, а внутренние тестировщики получают новую версию по флагу.
  • Единая точка TLS: сертификаты Let's Encrypt и правила редиректа живут в одном месте, а не на десятке бэкендов.

Случаи, где L7 добавляет сложность без пользы:

  • Один TCP-сервис без прикладных правил: проксировать его на L7 дороже, чем пробросить на L4.
  • Кластеры PostgreSQL, MySQL, Redis: балансировщику нечего разбирать в бинарном протоколе на уровне HTTP.
  • Файловые хранилища и медиапотоки, где важна максимальная пропускная способность.
  • Сценарии, где по требованиям нельзя завершать TLS на периметре.

Про задержки стоит сказать честно: WebSocket не отменяет задержку маршрутизации, шифрования и обработки данных, а сокращает накладные расходы и ожидание следующего запроса (разбор протокола WebSocket). Хорошо настроенное соединение обычно передаёт небольшое событие за десятки миллисекунд внутри одного региона, тогда как постоянные опросы могут добавлять секунды, создавать лишний трафик и нагружать сервер.

Три механизма закрывают большинство задач прикладной маршрутизации. Путь и хост разделяют сервисы и версии API. Заголовки дают тонкое управление для тестов и внутренних клиентов. Cookie обеспечивают привязку сессии и канареечные сценарии. Ниже приведены типовые фрагменты для Nginx, Traefik и Envoy; готовые схемы с тюнингом для высоких нагрузок есть в статье про маршрутизацию процессов и health checks.

Маршрутизация по URL и хосту в Nginx, Traefik и Envoy

Nginx сопоставляет запрос с блоками location, а домен проверяет через server_name. Порядок важен: префиксные location выбираются по самому длинному совпадению, регулярные выражения проверяются после префиксных, если не указан модификатор ^~. Шаблон для двух версий API:

server {
    listen 443 ssl;
    http2 on;
    server_name api.example.com;

    location /v1/ {
        proxy_pass http://backend_v1;
        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;
    }

    location /v2/ {
        proxy_pass http://backend_v2;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Директива http2 on включает HTTP/2 и ALPN на слушателе. Забытый proxy_set_header Host ломает виртуальные хосты на бэкенде: приложение получает внутреннее имя апстрима вместо публичного домена.

Traefik описывает правила в routers и ссылается на сервисы. Файловый провайдер читает YAML:

http:
  routers:
    api-v2:
      rule: "Host(`api.example.com`) && PathPrefix(`/v2`)"
      service: api-v2-service
      entryPoints:
        - websecure
      priority: 100
    api-v1:
      rule: "Host(`api.example.com`)"
      service: api-v1-service
      entryPoints:
        - websecure
      priority: 10
  services:
    api-v2-service:
      loadBalancer:
        servers:
          - url: "http://10.0.0.12:8080"
    api-v1-service:
      loadBalancer:
        servers:
          - url: "http://10.0.0.11:8080"

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

Envoy строит маршруты внутри virtual_hosts, где домены заданы полем domains, а путь разбирается в match:

virtual_hosts:
  - name: api
    domains: ["api.example.com"]
    routes:
      - match: { prefix: "/v2" }
        route:
          cluster: api_v2
          timeout: 15s
      - match: { prefix: "/v1" }
        route:
          cluster: api_v1
          timeout: 15s
      - match: { prefix: "/" }
        route:
          cluster: api_v1
          timeout: 15s

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

Заголовки удобны для канареечных релизов и внутреннего тестирования: клиент явно помечает свой запрос, и балансировщик отправляет его на новую версию. В Nginx проверку удобно вынести в map:

map $http_x_canary $api_pool {
    default  api_stable;
    "true"   api_canary;
}

map $cookie_canary $cookie_pool {
    default  api_stable;
    "1"      api_canary;
}

upstream api_stable {
    server 10.0.0.11:8080 max_fails=3 fail_timeout=10s;
}

upstream api_canary {
    server 10.0.0.21:8080 max_fails=3 fail_timeout=10s;
}

Дальше в location используется переменная в proxy_pass. Учтите: proxy_pass с переменной меняет поведение Nginx, ему нужен resolver, а имя апстрима разбирается во время выполнения. Это плата за гибкую маршрутизацию, и её стоит проверить на стенде.

location /api/ {
    proxy_pass http://$api_pool;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

В Traefik то же самое выражается правилом на заголовок и приоритетом выше общего правила:

http:
  routers:
    api-canary:
      rule: "Host(`api.example.com`) && Headers(`X-Canary`, `true`)"
      service: api-canary-service
      priority: 200
    api-cookie:
      rule: "Host(`api.example.com`) && HeadersRegexp(`Cookie`, `canary=1`)"
      service: api-canary-service
      priority: 190

Envoy сопоставляет заголовки внутри match и поддерживает точное совпадение, префикс и регулярные выражения:

routes:
  - match:
      prefix: "/api"
      headers:
        - name: "x-canary"
          exact_match: "true"
    route: { cluster: api_canary }
  - match: { prefix: "/api" }
    route: { cluster: api_stable }

Две частые ошибки в этом блоке. Первая: балансировщик снимает заголовок X-Forwarded-For или X-Forwarded-Proto, и приложение строит ссылки и определяет схему неверно. Вторая: cookie не доходит до бэкенда, потому что прокси переписывает заголовок Cookie целиком. Пропускайте заголовки явно и проверяйте их на стороне приложения.

Балансировка gRPC на L7

gRPC работает поверх HTTP/2, а HTTP/2 мультиплексирует множество параллельных запросов внутри одного TCP-соединения. Для L4-балансировщика это выглядит как один долгоживущий поток, поэтому все вызовы от клиента уходят на один бэкенд и нагрузка перекашивается. L7-балансировщик видит отдельные HTTP/2-стримы и распределяет их по бэкендам независимо.

Почему gRPC требует HTTP/2 и L7

Клиент открывает одно TCP-соединение и шлёт по нему десятки одновременных вызовов. L4 выбирает бэкенд один раз при установке соединения, а дальше только пересылает байты, поэтому распределение заканчивается на этом шаге. L7 разбирает HTTP/2-фреймы, выделяет стримы и применяет правила маршрутизации к каждому вызову.

Отдельно про WebSocket, чтобы не путать протоколы. WebSocket тоже начинается как HTTP-запрос с предложением изменить протокол, но после подтверждения канал перестаёт быть обычным обменом «запрос-ответ», и обе стороны могут отправлять сообщения в любой момент. gRPC же остаётся RPC поверх HTTP/2 с привычной схемой запрос-ответ по стримам. Набор директив балансировщика для них разный.

Конфигурации gRPC для Nginx, Traefik и Envoy

Nginx проксирует gRPC через директивы grpc_pass и родственные настройки. Для шифрованного бэкенда указывается схема grpcs, для незашифрованного grpc:

server {
    listen 443 ssl;
    http2 on;
    server_name grpc.example.com;

    location / {
        grpc_pass grpcs://grpc_backend;
        grpc_set_header X-Real-IP $remote_addr;
        grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        grpc_read_timeout 300s;
        grpc_send_timeout 300s;
    }
}

Если слушатель не поднят с поддержкой HTTP/2, клиент получит ошибку при попытке согласовать h2. Для длительных серверных стримов дефолтные таймауты обрывают соединение, поэтому grpc_read_timeout и grpc_send_timeout увеличивают под профиль сервиса.

Traefik требует явно указать схему подключения к бэкенду. Для незашифрованного gRPC это h2c, для TLS-бэкенда используется https с HTTP/2:

http:
  services:
    grpc-service:
      loadBalancer:
        serversTransport: grpc-transport
        servers:
          - url: "h2c://10.0.0.20:50051"
  serversTransports:
    grpc-transport:
      protocols:
        http2: true

Путаница h2c и h2 приводит к ошибке согласования протокола: h2c означает HTTP/2 без TLS, h2 требует шифрованного канала. Если бэкенд слушает незашифрованный порт, оставляйте h2c.

Envoy объявляет HTTP/2 в самом кластере и умеет проверять здоровье gRPC-сервиса:

clusters:
  - name: grpc_backend
    type: STRICT_DNS
    connect_timeout: 1s
    http2_protocol_options: {}
    load_assignment:
      cluster_name: grpc_backend
      endpoints:
        - lb_endpoints:
            - endpoint:
                address:
                  socket_address: { address: 10.0.0.20, port_value: 50051 }
    health_checks:
      - timeout: 1s
        interval: 5s
        unhealthy_threshold: 3
        healthy_threshold: 1
        grpc_health_check:
          service_name: "grpc.health.v1.Health"

Без http2_protocol_options Envoy пойдёт к бэкенду по HTTP/1.1, и gRPC-вызов завершится ошибкой. Health-check через grpc_health_check опрашивает стандартный сервис grpc.health.v1.Health, который приложение должно реализовать.

Проксирование WebSocket через L7-балансировщик

WebSocket работает поверх TCP и начинается как обычный HTTP-запрос с предложением изменить протокол соединения. Если сервер согласен, он отвечает специальным статусом переключения протокола, после чего канал перестаёт быть обычным HTTP-обменом «запрос-ответ», и обе стороны могут отправлять сообщения в любой момент (установка соединения и обмен кадрами). Балансировщик видит только рукопожатие, а дальше держит длительное двустороннее соединение.

Заголовки Upgrade и Connection: что и зачем

Клиент отправляет заголовки Upgrade: websocket и Connection: Upgrade. Сервер подтверждает переход статусом 101 Switching Protocols. Прокси обязан пробросить оба заголовка, иначе браузер получит 400 Bad Request и соединение не поднимется. Nginx по умолчанию приводит Connection к значению close и заголовки не передаёт, поэтому их задают вручную:

location /ws/ {
    proxy_pass http://ws_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-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_read_timeout 3600s;
    proxy_send_timeout 3600s;
    proxy_buffering off;
}

Директива proxy_http_version 1.1 обязательна: механизм Upgrade не поддерживается в HTTP/1.0, который Nginx использует по умолчанию при проксировании. Буферизацию отключают, чтобы кадры уходили клиенту сразу.

Envoy описывает апгрейд отдельной конструкцией в маршруте:

routes:
  - match: { prefix: "/ws" }
    route:
      cluster: ws_backend
      timeout: 0s
      upgrade_configs:
        - upgrade_type: websocket
          enabled: true

Значение timeout: 0s отключает таймаут маршрута для долгоживущего соединения. Traefik поддерживает WebSocket без дополнительных директив, ему достаточно обычного HTTP-роутера.

Таймауты, keepalive и sticky sessions

Соединение чата или мониторинга живёт часами, а стандартные таймауты прокси рассчитаны на короткие HTTP-запросы. В Nginx по умолчанию proxy_read_timeout равен 60 секундам, и молчащий WebSocket разрывается примерно на этой отметке. Увеличение до 3600 секунд закрывает типовой случай, а период активности соединения дополнительно поддерживают пингами на уровне приложения.

При нескольких репликах бэкенда нужна привязка клиента к конкретному экземпляру. Traefik умеет это через sticky cookie:

http:
  services:
    ws-service:
      loadBalancer:
        sticky:
          cookie:
            name: ws_affinity
            httpOnly: true
            secure: true
        servers:
          - url: "http://10.0.0.31:8080"
          - url: "http://10.0.0.32:8080"

Без привязки балансировщик может отправить повторное подключение на другую реплику, и состояние сессии потеряется, если оно хранится в памяти процесса. Для деплоя без обрывов нужен механизм drain: под перестаёт принимать новые соединения, существующие закрываются по таймауту, и только потом процесс останавливается. При rolling update чата с 10 тысячами соединений отсутствие drain даёт одномоментный разрыв всех клиентов и шторм переподключений.

TLS-терминация на L7-балансировщике

Завершение TLS на балансировщике собирает управление сертификатами в одной точке. Выпуск через Let's Encrypt, продление и единые наборы шифров настраиваются один раз, а бэкенды общаются с прокси по внутренней сети. Обратная сторона: балансировщик видит расшифрованный трафик, а значит, держит ключи и несёт нагрузку на криптографию.

Терминация, re-encryption или passthrough

Модель passthrough пропускает зашифрованный поток насквозь и не расшифровывает его. L7 при этом не видит ни URL, ни заголовков, ни cookie, поэтому маршрутизация по пути и содержимому становится невозможной: остаётся выбор бэкенда по SNI или по порту. Это ключевой компромисс модели.

Терминация снимает шифрование на периметре и отдаёт трафик внутрь по HTTP. Re-encryption делает то же самое, но восстанавливает TLS до бэкенда, что полезно при требованиях к защите внутреннего периметра. Прокидывайте X-Forwarded-Proto, чтобы приложение знало исходную схему и не строило ссылки на http вместо https.

ALPN и SNI: почему gRPC ломается без них

Клиент и сервер выбирают протокол прикладного уровня через ALPN на этапе TLS-рукопожатия. Для gRPC согласование h2 обязательно: без него клиент получает HTTP/1.1 и вызов завершается ошибкой. В Nginx поддержку включают вместе с HTTP/2 на слушателе:

server {
    listen 443 ssl;
    http2 on;
    server_name grpc.example.com;

    ssl_certificate     /etc/letsencrypt/live/grpc.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/grpc.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
}

В Envoy список протоколов задаётся прямо в контексте TLS:

downstream_tls_context:
  common_tls_context:
    alpn_protocols: ["h2", "http/1.1"]
    tls_certificates:
      - certificate_chain: { filename: "/certs/fullchain.pem" }
        private_key: { filename: "/certs/priv.key" }

SNI решает вторую задачу: по имени домена из рукопожатия балансировщик выбирает нужный сертификат. Если SNI не передаётся или не совпадает, клиент получит сертификат другого домена и ошибку проверки. WebSocket по схеме wss работает через тот же слушатель, что и обычный HTTPS, отдельных сертификатов для него не нужно.

Health-check и канареечные релизы

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

Health-check для HTTP, gRPC и WebSocket

Проверки делятся на активные и пассивные. Активный health-check сам опрашивает эндпоинт с заданным интервалом, пассивный анализирует коды ответов реального трафика и выводит бэкенд из ротации после серии ошибок. Для HTTP достаточно ручки liveness и readiness, которая возвращает 200 и проверяет зависимости.

Nginx в открытой версии умеет пассивные проверки через параметры апстрима:

upstream api_backend {
    server 10.0.0.11:8080 max_fails=3 fail_timeout=10s;
    server 10.0.0.12:8080 max_fails=3 fail_timeout=10s;
    keepalive 32;
}

После трёх неудач за fail_timeout сервер исключается из ротации на 10 секунд. Активные проверки с HTTP-запросами доступны в коммерческой версии Nginx Plus и через сторонние модули. В Traefik проверка описывается в сервисе: путь, интервал и таймаут. В Envoy health_checks задаёт интервал, таймаут и пороги unhealthy_threshold и healthy_threshold.

Для gRPC правильный способ проверки - стандартный сервис grpc.health.v1.Health/Check, а не попытка открыть обычный HTTP-порт. Для WebSocket проверять нужно отдельный HTTP-эндпоинт или TCP-подключение, потому что само WebSocket-соединение долгоживущее: балансировщик не может считать разрыв канала за время между проверками признаком падения, иначе живые бэкенды будут постоянно исключаться из ротации.

Канареечный релиз через веса и заголовки

Весовое распределение отправляет фиксированную долю трафика на новую версию. В Nginx это делается через split_clients по хешу от адреса и User-Agent:

split_clients "${remote_addr}${http_user_agent}" $api_pool {
    5%     api_canary;
    *      api_stable;
}

В Envoy веса задаются в weighted_clusters внутри маршрута:

route:
  weighted_clusters:
    clusters:
      - name: api_stable
        weight: 95
      - name: api_canary
        weight: 5

В Traefik используется сервис типа weighted со списком сервисов и весами, а для внутреннего тестирования удобнее правило на заголовок X-Canary или cookie canary=1: тестировщики видят новую версию, остальные пользователи остаются на стабильной.

Решение об откате принимают по метрикам: доля ответов 5xx, задержка p99 и частота ошибок gRPC-статусов. Порог вроде роста 5xx выше 1 процента на канареечной группе при стабильных 95 процентах основного трафика даёт достаточный сигнал для автоматического возврата весов.

Типичные ошибки и как их избежать

Список собран по симптомам, которые чаще всего встречаются при настройке L7-маршрутизации.

  1. 400 Bad Request на WebSocket. Прокси не пробросил заголовки Upgrade и Connection. Исправление: proxy_http_version 1.1 и явная передача обоих заголовков.
  2. 502 или 504 на gRPC. Бэкенд слушает HTTP/1.1 либо сработал дефолтный таймаут 60 секунд. Исправление: включить HTTP/2 на подключении к апстриму и увеличить grpc_read_timeout и grpc_send_timeout.
  3. WebSocket рвётся примерно через минуту. Виноват proxy_read_timeout по умолчанию. Исправление: поднять значение до 3600 секунд и добавить пинги на уровне приложения.
  4. gRPC-клиент получает HTTP/1.1. Не согласован ALPN h2. Исправление: включить HTTP/2 на слушателе и проверить список alpn_protocols на стороне балансировщика.
  5. Перекос трафика на gRPC. Вместо L7 используется L4-балансировка по TCP. Исправление: перевести сервис на L7-прокси, который видит отдельные HTTP/2-стримы.
  6. Cookie не доходит до бэкенда. Прокси переписывает заголовок Cookie целиком. Исправление: сохранять исходное значение и явно пропускать нужные cookie.
  7. Health-check выводит живые бэкенды. Слишком агрессивный интервал и низкий порог. Исправление: увеличить unhealthy_threshold и интервал, проверять отдельный лёгкий эндпоинт.
  8. Канареечная версия получает 100 процентов трафика. Неверный вес или порядок правил, общее правило перехватывает запрос раньше точного. Исправление: задать явный приоритет и проверить распределение по метрикам.

Как выбрать балансировщик: Nginx, Traefik или Envoy

Выбор сводится к способу управления конфигурацией и требуемой динамике. Расширенное сравнение по производительности и поддержке современных протоколов приведено в отдельном материале про сравнение Nginx, HAProxy и Traefik.

КритерийNginxTraefikEnvoy
Порог входаНизкий, много примеров и статейНизкий в Kubernetes, правила на аннотациях и меткахВыше: конфигурация многословна, нужен опыт
Динамическая конфигурацияПерезагрузка файлов, ограниченные динамические APIНативная реакция на события Docker и KubernetesxDS API, обновления без перезапуска
gRPCgrpc_pass, требует HTTP/2 на слушателеСхема h2c или https с HTTP/2http2_protocol_options, grpc_health_check
WebSocketРучная настройка Upgrade, Connection и таймаутовРаботает без дополнительных директивupgrade_configs в маршруте
Канареечные релизыsplit_clients или map по cookieСервис weighted и правила на заголовкахweighted_clusters
TLS-автоматизацияЧерез внешние инструменты и certbotВстроенный ACME с Let's EncryptЧерез SDS и внешний менеджер сертификатов
Гибкость маршрутизацииДостаточно для классических задачХорошо для микросервисов и ingressМаксимальная, включая service mesh

Практическое правило: для виртуальных машин и простых ingress берите Nginx, для Kubernetes с частыми деплоями и автоматическим TLS удобнее Traefik, для сложной прикладной маршрутизации, тонких весов и service mesh подходит Envoy. Перед переходом в продакшен поднимите стенд с реальным профилем трафика, проверьте рукопожатие WebSocket, gRPC-вызовы и поведение при деплое. Нагрузочный тест на ваших данных даст больше, чем любое сравнение из документации.

Поделиться:
Сохранить гайд? В закладки браузера