Всем привет, меня зовут Сергей Прощаев. В этой статье расскажу про одну из самых горячих тем 2026 года — интеграцию AI/ML как самостоятельных сервисов в микросервисную архитектуру. Я Tech Lead и руководитель направления Java/Kotlin разработки в FinTech & E-commerce, также преподаю на курсах разработки и архитектуры в OTUS.
Представьте: вы разрешили сервисам в вашей компании напрямую вызывать ChatGPT. Сначала всё отлично — фичи выкатываются быстро. Но через месяц приходит счёт от OpenAI на $15K, а вы не понимаете, кто нагенерировал столько токенов. Потом один из сервисов начинает ждать ответа LLM по 3 секунды, и вся продовая цепочка падает. Разработчики добавляют всё новые вызовы, никто не кеширует повторяющиеся вопросы. Знакомо?
За последние полгода я пересмотрел архитектуры четырёх проектов, куда заказчики стремительно добавляли LLM. Картина везде была похожа: сначала все счастливы, потом хаос. Мне как-то попалась статистика: до 40% вызовов LLM — повторяющиеся запросы. А ещё один стартап заплатил $50K за месяц, потому что у них не было кеширования и каждый чих уходил в GPT-4.
К 2026 году AI-модели стали полноценными «гражданами» архитектуры, но подход «дёрни LLM из любого сервиса» больше не работает. Нужен специальный паттерн — AI Gateway. В этом гайде я покажу, как спроектировать его как инфраструктурный слой (отдельный сервис, плагин API Gateway или sidecar), добавить семантическое кеширование, контроль стоимости, rate limiting, resilience и безопасность. А главное — как не повторить чужих ошибок.
Исходные условия
Прежде чем идти дальше, давайте зафиксируем, с чем мы работаем. Предположим, у вас есть:
-
Kubernetes-кластер (версия 1.28+), в котором живут микросервисы.
-
Несколько Java/Kotlin-сервисов на Spring Boot. Они уже общаются через REST, возможно, есть API Gateway.
-
Доступ к двум-трём LLM: например, OpenAI GPT-4 (для сложных задач) и локальная Llama 3 (для быстрых, дешёвых ответов).
-
Трафик к LLM — до 1000 запросов в час, но с пиками.
-
Команда из 5–10 разработчиков, никто централизованно не управляет вызовами к моделям.
-
Счета за LLM растут на 20–30% месяц к месяцу, и непонятно, почему.
Ограничения на старте: нет готового AI-шлюза, нет кеширования, нет контроля токенов, rate limiting отсутствует. Все вызовы — синхронные и напрямую.
Исходя из этого, мы построим AI Gateway, который решит эти боли.
Что такое AI Gateway и почему Spring Cloud Gateway — хороший вариант
AI Gateway — это выделенный инфраструктурный слой между вашими сервисами и LLM-провайдерами. Он может быть реализован как:
-
отдельный микросервис (например, на Spring Cloud Gateway),
-
плагин к существующему API Gateway (Kong, APISIX),
-
sidecar в mesh-архитектуре (Envoy),
-
специализированный inference proxy.
В статье я буду использовать Spring Cloud Gateway для примеров, потому что он реактивный, легко конфигурируется и отлично ложится на Java/Kotlin-стек. Но описанные паттерны универсальны.
AI Gateway управляет:
-
маршрутизацией на разные модели (стоимость, SLA, доступность);
-
кешированием (прямым и семантическим);
-
контролем стоимости (лимиты на сервис/пользователя/сутки);
-
rate limiting (запросы/минуту, токены/минуту);
-
мониторингом задержек и качества;
-
безопасностью: фильтрация prompt injection, маскирование PII, аудит;
-
resilience: circuit breaker, retry policies, bulkhead, защита от retry storm.
Пошаговый маршрут: как построить AI Gateway с нуля
Шаг 1. Базовый роутинг
Добавляем зависимость spring-cloud-starter-gateway. В application.yml прописываем маршруты. Для демонстрации я использую простейший маршрут по заголовку. В продакшене модель обычно выбирает не клиентский сервис, а policy engine внутри Gateway: на основе SLA, стоимости, типа задачи, текущей доступности моделей и предпочтений пользователя. Клиент просто шлёт запрос в единый OpenAI‑compatible chat completion API contract (единый контракт, эмулирующий API OpenAI), а шлюз сам решает, куда его направить.
spring:
cloud:
gateway:
routes:
- id: openai_route
uri: https://api.openai.com/v1/chat/completions
predicates:
- Header=model-type, premium
filters:
- name: RequestRateLimiter
args:
key-resolver: "#{@userKeyResolver}"
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
- id: local_llama_route
uri: http://llama-service:8080/generate
predicates:
- Header=model-type, economy
Проверка: выполните тестовый запрос к Gateway с заголовком model-type: premium — он должен уйти на OpenAI. Затем с model-type: economy — на локальную Llama. Посмотрите логи Gateway: в них должен быть URI, куда реально пошёл запрос.
Шаг 2. Добавляем кеш результатов
Самый эффективный способ сэкономить. Для точных совпадений (один и тот же промпт) — обычный Redis. Но 80% пользы даст семантический кеш: вы храните эмбеддинги запросов и, если новый запрос семантически близок к сохранённому (например, «Как будет погода завтра в Москве» и «Завтрашний прогноз для Москвы»), возвращаете кешированный ответ.
В production semantic cache почти никогда не строится только на косинусной близости. Обычно в cache key дополнительно включают:
-
tenant/user scope — изоляция данных между разными пользователями;
-
model version и system prompt hash;
-
domain context.
Кроме того, cache entries имеют TTL (time-to-live) и должны инвалидироваться при смене embedding model или system prompt version. Без этого вы рискуете получить устаревшие или неконсистентные ответы. Порог срабатывания (обычно 0,8–0,9) настраивается под конкретную предметную область.
Проверка: сделайте два одинаковых запроса подряд. Первый должен идти в LLM (медленно, например 500 мс). Второй — вернуться из кеша (быстро, 10–30 мс внутри одного региона). Добавьте заголовок X-Cache: HIT. Для семантического кеша проверьте два семантически похожих запроса — второй тоже должен быть хитом.
Шаг 3. Контроль стоимости и лимитов
Добавляем фильтр, который считает токены. Каждый запрос логируется в Prometheus. Устанавливаем:
-
requests per minute — классический rate limiting;
-
tokens per minute — ограничение на объём токенов в минуту;
-
budget per day/per user — жёсткий финансовый потолок, после которого шлюз возвращает 403.
Для LLM-систем обычного request rate limiting недостаточно — токен-ориентированное лимитирование гораздо точнее отражает реальную нагрузку на бюджет.
Полезный трюк: если модель слишком долго отвечает (таймаут), шлюз может переключить запрос на более быструю модель (fallback). Важное уточнение: fallback между моделями безопасен только для tolerant-сценариев (чаты, рекомендации, суммаризация). Для strict-output задач (JSON extraction, agents с tool calling) fallback может нарушить контракт ответа. В таких случаях лучше вернуть ошибку.
Проверка: превысьте лимит токенов — получите 429. Для fallback: отключите основную модель в тестовой среде — проверьте переключение на резервную.
Шаг 4. Мониторинг и observability
Каждый вызов LLM должен оставлять трейс (OpenTelemetry). Метрики:
-
latency p50/p95/p99 на модель;
-
стоимость вызова;
-
кеш-хиты;
-
частота rate limiting;
-
количество срабатываний circuit breaker.
Для resilience-слоя желательно добавить адаптивное поведение — например, автоматическую настройку порогов circuit breaker на основе наблюдаемых ошибок и задержек (auto tuning). Это уже следующий уровень зрелости, но его полезно иметь в виду.
Проверка: выполните несколько запросов, зайдите в Jaeger/Grafana. Должны быть спаны security-filter, cache-check, llm-call, resilience.
Шаг 5. Streaming-ответы
Streaming (SSE/WebFlux) требует отдельного внимания. Gateway должен проксировать поток без буферизации (иначе теряется смысл стриминга) и по возможности отменять запрос к upstream-модели при client disconnect. Важно: поддержка cancellation зависит от конкретного LLM-провайдера — некоторые API продолжают inference даже после разрыва соединения и биллят полную генерацию. Семантика биллинга (billing semantics) при частичной генерации также зависит от провайдера: могут списать токены за весь сгенерированный ответ, даже если клиент отключился. Это нужно учитывать при выборе провайдера и проектировании.
Проверка: начните генерацию длинного ответа через Gateway и закройте вкладку браузера. В логах должно быть событие отмены (если провайдер поддерживает). Убедитесь, что потребление токенов прекратилось.
Шаг 6. Resilience: circuit breaker, bulkhead, retry storm
AI Gateway быстро становится критической инфраструктурой. LLM-провайдеры могут деградировать, выдавать 5xx, rate limit’ить или зависать на десятки секунд. Без защиты один проблемный провайдер положит все сервисы.
Что добавляем:
-
Circuit Breaker — при достижении порога ошибок (например, 50% ошибок за 10 секунд) шлюз перестаёт отправлять запросы к этому провайдеру и быстро возвращает fallback-ответ или ошибку. Желательно настроить автоматическую подстройку порогов на основе наблюдаемых метрик (adaptive circuit breaker).
-
Bulkhead isolation — пул потоков/соединений для каждого провайдера, чтобы медленный провайдер не забирал все ресурсы.
-
Защита от retry storm — ограничение количества повторных попыток (обычно 1–2) с экспоненциальной задержкой, иначе при сбое провайдера все сервисы начнут ретраить одновременно и добьют остатки.
В Spring Cloud Gateway это реализуется через Resilience4J фильтры. Пример конфигурации circuit breaker:
filters:
- name: CircuitBreaker
args:
name: openaiCB
fallbackUri: forward:/fallback/openai
Проверка: в тестовой среде заставьте провайдера возвращать 500 ошибку. Circuit breaker должен разомкнуться после нескольких запросов, и последующие запросы сразу идти в fallback (не доходя до провайдера). Через заданное время (например, 10 секунд) перейти в half-open и проверить восстановление.
Визуализируем диалог: как работает AI Gateway с кешем
Прежде чем показывать схему, представьте: клиентский сервис (например, «рекомендации») хочет спросить у LLM: «Какие товары подойдут к красному пальто?». Вместо прямого вызова OpenAI он идёт к AI Gateway.
Вот как Gateway обрабатывает запрос — проверяет кеш, при промахе идёт к LLM, сохраняет результат и отдаёт клиенту (рис. 2).
Из диаграммы видно, что большая часть повторяющихся или похожих запросов никогда не долетает до платной LLM. Время ответа при cache hit — 10–30 мс, что на порядок быстрее вызова LLM. Кеш работает на уровне смыслов, а не точного совпадения, удерживая счета под контролем.
Внутреннее устройство AI Gateway: компоненты
Заглянем внутрь AI Gateway и посмотрим как запрос проходит через фильтр безопасности, аутентификацию, rate limiter, resilience, роутер на модель, кеш и сбор метрик (рис. 3).
Вы можете собрать такой шлюз из стандартных строительных блоков. В enterprise-сценариях Gateway становится точкой security-контроля (Prompt Security Filter проверяет jailbreak-паттерны, маскирует PII, ведёт аудит). Resilience Layer защищает систему от деградации одного провайдера. Аутентификация, rate limiting (включая token-based), кеш, роутинг — всё это кастомные фильтры или готовые реализации. В 2026 году многие компании уже выложили свои наработки в open source, например Envoy AI Gateway.
Где это решение не сработает (ограничения)
-
У вас всего один сервис и 100 запросов в день. Просто встройте вызов LLM в этот сервис — шлюз добавит сложности.
-
Все запросы уникальны и имеют низкую семантическую повторяемость. Кеш не поможет, но rate limiting и контроль стоимости всё равно полезны.
-
Streaming с очень жёсткими требованиями к задержке. Шлюз добавляет микро-задержку.
-
Нет возможности поддерживать ещё один компонент. AI Gateway — это отдельный слой, его нужно деплоить, мониторить, обновлять.
В остальных 80% случаев — да, стоит строить.
Реальный кейс: как Uber построил AI Gateway
Мне попался отличный пример из публичных источников — опыт Uber. В 2024–2025 годах они столкнулись с тем, что более 100 микросервисов начали напрямую вызывать LLM. Счета росли, разработчики жаловались на непредсказуемые задержки.
Uber разработал внутренний AI Gateway с тремя ключевыми особенностями:
-
Автоматическая маршрутизация на основе стоимости и SLA. Запрос к рекомендациям шёл на дешёвую модель, критичный диалог поддержки — на самую умную.
-
Динамический выбор модели в зависимости от загрузки кластера. Если локальная LLM была свободна — использовали её, если перегружена — переключались на OpenAI.
-
Семантический кеш с TTL, зависящим от домена. Для поиска товаров кеш жил 15 минут, для персональных рекомендаций — 1 минуту.
Результат: централизация доступа, единые политики безопасности, кеширование и fallback. Согласно публичным данным, GenAI Gateway обрабатывает более 5 миллионов запросов в день, обслуживая свыше 40 внутренних сервисов, и предоставляет единый OpenAI‑compatible chat completion API contract к моделям от OpenAI, Vertex AI и внутренним LLM.
Я бы предпочёл такой подход простой «ковровой бомбардировке» вызовов. Он системный и масштабируемый. В крупных системах подобная централизация часто окупается очень быстро — особенно при росте количества команд и LLM-интеграций.
Чек-лист перед внедрением
-
У нас больше двух сервисов, вызывающих LLM?
-
Месячный счёт за модели превышает $1000?
-
Бывают ситуации, когда один сервис случайно забивает лимиты для всех?
-
Разработчики жалуются на непредсказуемые задержки?
-
Мы хотим попробовать разные LLM без переписывания кода?
Если ответили «да» хотя бы на два пункта — AI Gateway вам нужен!
Подведём итог
AI-модели перестали быть экзотикой. В 2026 году они — обычные микросервисы, но с платным доступом и переменной задержкой. AI Gateway (инфраструктурный слой, а не просто ещё один сервис) позволяет управлять ими централизованно: экономить бюджет, обеспечивать безопасность (prompt injection, PII, аудит), добавлять resilience (circuit breaker, bulkhead) и не падать в прод при сбоях провайдеров.
Главный вывод: не ждите, пока хаос начнёт гореть. Стройте шлюз заранее. Он окупится быстрее, чем вы напишете очередной прямой вызов OpenAI из нового сервиса.
Что дальше?
В этом гайде я показал архитектуру и ключевые компоненты. Если хотите не просто прочитать, а научиться собирать такой шлюз руками на реальных проектах — обратите внимание на курс OTUS «Архитектура и шаблоны проектирования».
А перед стартом курса можно прийти на бесплатный открытый урок:
-
15 июня в 20:00 «Системы обмена сообщениями: RabbitMQ и Kafka». Записаться
Разберем два популярных брокера сообщений — RabbitMQ и Kafka: их архитектурные особенности, основные принципы работы и сценарии, в которых один инструмент подходит лучше другого. Это хороший способ познакомиться с преподавателем, протестировать формат обучения и задать вопросы по теме.
Если хотите выбрать не один вебинар, а сразу посмотреть, какие темы будут полезны именно вам, полный список бесплатных уроков июня смотрите в дайджесте.
Автор: sproshchaev


