Sticky-сессии vs префикс-кэш-роутер для LLM-инференса: когда переходить
Разбор типовой ситуации, в которой разработчики LLM-сервисов интуитивно выбирают стики-сессии, но архитектурно перерастают их — и как не потерять кэш и не перегрузить инстансы при росте сценариев.
Постановка: как балансировать запросы между идентичными инференс-инстансами
Представьте типичную промышленную конфигурацию: у вас есть три (или больше) replica inference‑сервера, каждый держит одну и ту же большую модель. Приходит поток запросов от пользователей, агентов или batch‑обработки. Ключевой эксплуатационный вопрос — на какой инстанс отправить очередной запрос — не имеет простого ответа, если вы всерьёз считаете latency и утилизацию GPU‑памяти.
Наивные подходы вроде round‑robin не учитывают ни текущую нагрузку, ни состояние KV‑кэша модели. Более умные варианты — least‑conn или стики‑сессии — решают часть проблем, но создают новую: вы рискуете недополучить выигрыш от переиспользования префиксного кэша, когда сценариев становится много и они разделяют крупные общие префиксы.
Разберём четыре реально применяемых подхода и определим, когда имеет смысл переходить от привычных стики‑сессий к роутеру, осведомлённому о префиксном кэше (prefix‑cache‑aware router, например vllm‑router).
Четыре подхода к роутингу: краткий справочник
| Подход | Принцип | Плюсы | Минусы |
|---|---|---|---|
| Round‑robin | Запросы распределяются по очереди | Простота реализации | Игнорирует нагрузку; один инстанс может быть перегружен, пока другие простаивают |
| Least‑conn | Отправка на инстанс с наименьшим числом активных соединений | Учитывает загрузку | Не учитывает кэш; с ростом числа инстансов вероятность попадания в «тёплый» префикс падает |
| Стики‑сессии (sticky sessions) | Запросы одной сессии (например, одного диалога) всегда идут на один и тот же инстанс | Высокая вероятность попадания в кэш для повторяющихся диалогов; эффективно при малом числе сценариев | Не переиспользует кэш между разными сессиями; плохо масштабируется при многих сценариях с общим префиксом |
| Префикс‑кэш‑роутер | Модель определяет, на каком инстансе совпадение префикса с текущим состоянием кэша наибольшее, и отправляет запрос туда | Максимальный reuse префиксного кэша между сессиями и сценариями; оптимален для ваншотов и смешанных пулов | Требует дополнительной логики и сборки метрик кэшей; оправдан при росте числа разнородных сценариев |
Выбор между двумя последними — главный вопрос. На практике многие команды годами живут на стики‑сессиях, не замечая, что теряют до 30–50 % потенциального ускорения инференса на чужих префиксах.
Стики‑сессии: где они работают безупречно
Рассмотрим классический сценарий: обслуживание диалогового агента. Пользователь ведёт разговор, каждый новый запрос содержит всю историю:
Запрос 1: system + user_turn_1
Запрос 2: system + user_turn_1 + assistant_turn_1 + user_turn_2
Запрос 3: system + … + user_turn_3
Все три запроса принадлежат одной сессии и при стики‑роутинге попадают на один инстанс. Для KV‑кэша это идеальный случай: модель видит реплику префикса из предыдущего шага, и дорогой префилл‑этап выполняется только для нового суффикса. Пока пул моделей загружен преимущественно такими диалогами, стики‑сессии оправданы и просты в эксплуатации.
Условие счастья здесь — основной reuse происходит внутри, а не между сессиями. Пока вы гоняете один‑два сценария с фиксированным системным промптом и длинными диалогами, стики будут давать близкий к оптимальному результат.
Провал стики‑сессий при общих префиксах между сессиями
Картина резко меняется, когда в один пулл моделей начинают поступать запросы из разных сессий, но с большим общим префиксом. Часто это бывает, когда:
- Несколько продуктовых сценариев используют один и тот же объёмный system‑prompt (например, 2000 токенов инструкции по соблюдению политик безопасности).
- Пулл обслуживает преимущественно ваншоты — однократные вызовы без истории диалога. Каждый запрос — это отдельная сессия, но все они начинаются с идентичного блока инструкций.
- Вы запускаете batch‑обработку тысяч однотипных запросов, и каждый раз модель заново обсчитывает префикс, даже если на соседнем инстансе он уже закэширован для другой сессии.
Механика потери очевидна: стики‑роутер привязывает сессию к инстансу, но ничего не знает о том, что на другом инстансе уже висит кэш для точно такого же префикса. Коэффициент переиспользования падает, вы платите вычислительными ресурсами за повторные префиллы, которые могли бы быть исключены.
Порог, после которого стики начинают вредить, индивидуален, но эмпирическое правило: как только объём общих префиксов между сессиями превышает объём уникальных продолжений и количество сценариев > 3‑4, морально готовьтесь к смене роутера.
Префикс‑кэш‑роутер: когда выигрыш очевиден
Роутер, способный заглянуть в состояние кэшей на всех инстансах, решает описанную выше проблему в корне. Он вычисляет длину наибольшего совпадающего префикса для входящего запроса на каждом сервере и отправляет запрос туда, где совпадение максимально. Это позволяет переиспользовать префиксный кэш не только в рамках одного диалога, но и между полностью независимыми сессиями, если они разделяют общую начальную часть (например, большой system‑prompt или фиксированное введение).
Практическая реализация (например, vllm‑router) опирается на метрики занятости KV‑блоков, а не просто на количество соединений; поэтому маршрутизация получается одновременно чувствительной и к приросту нагрузки, и к экономии вычислений.
Переход на такой роутер даёт ощутимый эффект в случаях:
- Разные сценарии обрабатываются одним пулом моделей (агенты, RAG, классические чаты).
- Есть общий крупный префикс между сессиями, и вы не хотите раздувать hardware‑парк.
- Преобладают ваншот‑запросы, где традиционные sticky‑сессии не могут переиспользовать кэш между разными однократными вызовами.
Чек-лист: определите свою потребность в роутере
Прежде чем внедрять или отвергать префикс‑кэш‑роутер, пройдите короткую самодиагностику по пунктам. Если больше двух ответов «да» — серьёзно рассмотрите миграцию.
- [ ] В одном инференс‑пуле обслуживается три и более продуктовых сценария с разной логикой, но одним системным промптом или частично совпадающими префиксами.
- [ ] Существенная доля запросов (>20 %) — ваншоты (без истории диалога), и их совокупный префикс превышает 1000 токенов.
- [ ] Вы замечаете, что на разных инстансах дублируется дорогой префилл одинаковых промптов, а метрики утилизации GPU‑памяти необъяснимо высоки.
- [ ] Вы регулярно перезапускаете или масштабируете инстансы, и после пересборки кэша возникает всплеск latency — хочется быстрее «прогревать» общий префикс на всех репликах.
- [ ] Текущие стики‑сессии реализованы через балансировщик, но он ничего не знает о семантике запросов и не может принять решение на основе содержимого промпта.
- [ ] Команда готова добавить в стек компонент, собирающий и агрегирующий метрики состояния KV‑кэша (например, через встроенные endpoint’ы движка инференса).
Если вы пока оперируете одним‑двумя сценариями с длинными диалогами и системный промпт у всех сессий разный — стики‑сессии останутся адекватным и простым решением. Но как только появляется третий сценарий с общим большим префиксом, выгода от кэш‑роутера быстро перевешивает затраты на его внедрение.