Почему ваш AI-сервис падает под нагрузкой: гайд по архитектуре low-latency (vLLM, SGLang, Envoy)
Ваш AI-сервис падает под нагрузкой? Узнайте, как архитектурный подход "inference-bundle" с Envoy и vLLM гарантирует latency <50 мс в продакшене.

Если ваш AI-чат в продакшене начинает тормозить, а latency скачет от 50 мс до 500 мс при росте RPS, проблема не в модели. Это почти всегда сбой архитектуры.
Для того чтобы ваш генеративный сервис выдержал высокую нагрузку (high-load) и гарантировал стабильную задержку (low-latency), вам нужно отказаться от классических монолитов в пользу специализированного, изолированного "inference-bundle".
Зачем нужно «изолированный inference-bundle»?
Традиционные архитектуры (FastAPI + трансформеры + PostgreSQL) работают отлично на 10 запросах. Как только нагрузка возрастает, всё ломается: GPU начинает перегреваться, а latency взлетает. Причина в том, что AI-инференс — это не просто «запрос → обработка → ответ». Это сложный конвейер: роутинг, поиск векторов (retrieval), кэширование промтов, сам инференс.
Все эти слои нельзя смешивать в одном бэкенде. Они требуют разной оптимизации и живут по своим законам.
Изолированный inference-bundle — это не микросервис в классическом понимании. Это бизнес-ориентированный блок, который инкапсулирует:
- Балансировщик (Envoy): Отвечает за трафик, безопасность и отказоустойчивость.
- Движок инференса (vLLM/SGLang): Выполняет математику и оптимизирует использование GPU.
- Управляющие слои: Кэширование промтов и логика оценки качества.
Этот подход позволяет вам четко разделить зоны ответственности, масштабировать компоненты независимо и, самое главное, прогнозировать стоимость и производительность для бизнеса.
🧱 Четыре слоя low-latency AI-стека
Современный продакшн-стек для AI-инференса выглядит как сложная, но упорядоченная система. Я разложил его на четыре ключевых слоя, чтобы понять, где и как выигрывают миллисекунды.
1. Умный L7-роутинг: Envoy как первый защитник
Не стоит начинать с NGINX. Для AI-трафика необходим Envoy Proxy.
Почему? Потому что AI-запросы не похожи на обычные HTTP-запросы. Каждый запрос может работать десятки секунд, и модель может внезапно начать тормозить при длинном контексте.
Envoy не знает о «галлюцинациях» или «токенах», но его штатные L7-механики идеальны для AI-нод:
- Circuit Breaking: Позволяет автоматически исключить из ротации ноду, которая начала падать или работать слишком долго.
- Outlier Detection: Отслеживает аномально медленные ответы и перенаправляет трафик на здоровые инстансы.
- Graceful Failover: Обеспечивает плавный переход трафика между разными версиями модели или разными кластерами.
Пример реализации: Вместо того чтобы полагаться только на Envoy, нужно добавить внешний Orchestration-слой.
- Клиент → Envoy (Роутинг)
- Envoy → Orchestrator (Внешний сервис)
- Orchestrator → Model A (Инференс)
- Model A → Judge-модель (Оценка качества ответа)
- Judge-модель → Orchestrator (Вердикт)
- Orchestrator → Клиент (Финальный ответ)
В этом случае Envoy остается исполнительным механизмом, а логика оценки качества (например, через небольшую модель-судью, типа Gemma-2B) лежит выше.
2. Сердце системы: Выбор inference-движка (vLLM vs SGLang)
Это самый критичный и технически сложный выбор. Эти движки решают фундаментальную проблему GPU-памяти и пропускной способности.
Оба движка используют технику Continuous Batching (или in-flight batching). Это значит, что батч (группа запросов) не фиксируется в начале. По мере поступления новых запросов новые токены могут вставать в текущий батч на границах итераций. Без этой техники, при высокой нагрузке, ваш throughput (пропускная способность) упадет в разы.
| Характеристика | vLLM | SGLang | Когда выбирать | | :--- | :--- | :--- | :--- | | Основная техника | Page Attention | Flash Attention 3, RadixAttention | | | Сложность | Низкая (Быстрый старт) | Высокая (Требует настройки) | | | Continuous Batching | Отлично (Стабильно) | Отлично (Особенно при длинном контексте) | | | Лучше всего для | Proof of Concept (PoC), небольшие батчи (1–8). | Продакшен, высокие требования к скорости и длинному контексту (>32K). | | Память | Эффективнее при неравномерной длине запросов. | Может потреблять больше памяти на старте, но эффективнее при длинном контексте. | |
Когда использовать vLLM: Если вы на стадии PoC и вам нужен максимально быстрый и стабильный старт, vLLM — ваш выбор. Он хорошо справляется с базовым continuous batching.
Когда использовать SGLang: Если вы строите продакшен-систему с требованием к контексту 128K+ и вам критически важна минимальная latency, SGLang даст вам больше гибкости (например, через тензорный параллелизм) и лучшую производительность при работе с длинными контекстами. Но будьте готовы потратить неделю на настройку.
3. Управление знаниями: Prompt Registry
Хранение промтов (системных инструкций) — это отдельная боль. Никогда не храните их в коде или переменных окружения, если они могут меняться.
Идеальное решение — Prompt Registry. Это отдельный, консистентный источник истины (например, таблица в PostgreSQL), который используется во время запуска сервиса.
Пример структуры в БД:
``sql CREATE TABLE prompt_registry ( prompt_id UUID PRIMARY KEY, system_prompt TEXT NOT NULL, version INT DEFAULT 1, is_active BOOLEAN DEFAULT TRUE, created_at TIMESTAMP DEFAULT NOW() ); ``
Когда ваш оркестратор запускается, он не берет промт из Docker-образа, а запрашивает актуальную, активную версию из этой таблицы. Это позволяет вам обновлять логику работы AI, не пересобирая и не перезапуская весь сервис.
⚠️ Подводные камни: где ломается архитектура
- Смешивание логики: Самая частая ошибка — попытка сделать всё в одном месте. Нельзя, чтобы роутинг, кэширование, инференс и обработка данных были в одном бэкенд-сервисе.
- Игнорирование Continuous Batching: Если вы не используете этот механизм, ваш throughput будет в разы ниже, чем у конкурентов, и при той же нагрузке ваши GPU будут перегреваться.
- Неправильная гранулярность: Не пытайтесь построить 100 микросервисов. Используйте принцип inference-bundle — создавайте блоки, которые имеют четкую, понятную для бизнеса цену и задачу.
Что попробовать дальше
- Нагрузочное тестирование: Используйте инструменты, имитирующие реальный трафик с переменной длиной контекста. Начинайте с 10 RPS, и постепенно увеличивайте.
- Мониторинг: Обязательно настройте сквозную наблюдаемость (distributed tracing) между Envoy, Orchestrator и Inference-движком, чтобы точно понимать, где возникает задержка.
- Кэширование: Помимо Prompt Registry, настройте кэширование результатов инференса (Redis) для повторяющихся запросов. Это самый быстрый способ снизить нагрузку на GPU и гарантировать low-latency.