Cloud & Databases

Шлюз Spring Boot для LLM: возьмите под контроль расходы на A

Ваша AI-фича обошлась в $47 000. Продукт на бесплатном тарифе. Потому что никто не поставил предохранители. Этот новый шлюз на Spring Boot — недостающее звено.

Диаграмма, иллюстрирующая архитектуру мультиарендного LLM-шлюза

Key Takeaways

  • Прямые вызовы LLM API ведут к неконтролируемым расходам и отсутствию изоляции по арендаторам.
  • Шлюз на Spring Boot предоставляет необходимые элементы контроля: ограничение частоты запросов, бюджетирование по токенам и аудиторское логирование.
  • Режимы применения политик (HARD, SOFT, OBSERVE) обеспечивают безопасное развёртывание и гибкое управление расходами.
  • Надлежащая наблюдаемость через аудиторские логи критически важна для отладки и поддержки клиентов.
  • Данный шлюз преобразует интеграцию LLM из рискованной в управляемую и экономически эффективную.

Задумывались ли вы когда-нибудь о тихом убийце, таящемся в ваших новообретённых AI-функциях? Нет, не Скайнет. Хуже. Инвойс. Команда, с которой я «сотрудничал» — назовём их «Невинные ООО» — запустила свою первую LLM-фичу за две недели. Две недели! А затем, шесть недель спустя, БАМ. Счёт от OpenAI на $47 000. За продукт бесплатного тарифа. Ой. По сути, они заплатили за очень дорогой урок.

Разбор полётов стал мастер-классом по тому, как не надо делать. Оказалось, один арендатор посчитал логику повторных попыток лишь рекомендацией для медленных дней, другой с энтузиазмом попросил модель «ответить в десяти тысячах токенов» (почему бы и не замахнуться на луну?), а третий, скажем так, энтузиаст обнаружил, что API-ключ фактически безлимитный, и решил прогнать через него весь свой пакетный рабочий процесс. Просто прямые вызовы SDK. Никаких ограничений по частоте. Никаких бюджетов на арендатора. Никаких потолков расходов. Никаких аудиторских следов. Ничего. Просто прямое, ничем не прикрытое злоупотребление API, любезно предоставленное общим ключом.

Если ваша команда запускает LLM-фичи так же — как будто на дворе 1999 год, и пропускная способность бесплатна — этот пост для вас. Потому что прежде чем вы получите этот шокирующий инвойс, вам понадобятся предохранители. Речь не о том, чтобы изобретать велосипед. Речь о создании функционального, мультиарендного шлюза на Spring Boot, который будет располагаться между вашими клиентами и провайдером LLM. Представьте, что это вышибала на вашей AI-вечеринке.

Он обеспечивает соблюдение API-ключей, лимитов запросов, бюджетов по токенам, кеширования и аудиторского логирования. Вся эта скучная, «взрослая» рутина, которая нужна вам до выхода в продакшн, а не после того, как ваш финансовый директор начнёт видеть кошмары.

Проблема: Единая точка отказа

Когда ваш код приложения обращается к OpenAI напрямую, каждый запрос выглядит для провайдера одинаково. Они видят один API-ключ, один источник, один счёт. Это как если бы все в переполненном многоквартирном доме пользовались одним почтовым ящиком. Хаос.

Это означает, что вы не можете:

  • Разграничивать ключи по арендаторам. Единый общий ключ означает, что один проблемный арендатор может уронить весь продукт. Ротация невозможна без скоординированных множественных развёртываний. Удачи с этим.
  • Ограничивать расходы на арендатора. Без шлюза вы узнаете, что превысили месячный бюджет, когда придёт счёт. Вы не можете регулировать в реальном времени. Сюрприз!
  • Блокировать вышедшие из-под контроля ответы. Ошибочный промпт с запросом 10 000 токенов выполняется без проблем. Провайдер не знает, что это неправильно; вы узнаете только постфактум. Дорого.
  • Кешировать детерминированные вызовы. Идентичные запросы с temperature=0 оплачиваются каждый раз. Отсутствие общего кеш-слоя означает отсутствие общего кеширования.
  • Аудировать что-либо. Когда клиент жалуется: «ваш AI предоставил мне неверную информацию», вы не можете реконструировать, что было отправлено, что пришло обратно, или какая модель использовалась. Данные находятся в логах OpenAI, которые вы не можете запрашивать. Удачи в роли детектива.

Шлюз — это стандартное решение. Вопрос в том, какие именно ограничения он применяет. И как он их применяет.

Восьмиступенчатая система защиты шлюза

Этот шлюз — не просто пропускной пункт. Это сложный конвейер из восьми стадий, каждая из которых решает определённую задачу. Представьте себе высокоорганизованный, очень строгий пункт контроля в аэропорту для ваших AI-запросов.

Клиент
POST /v1/chat/completions
Authorization: Bearer <tenant_api_key>
Стадия 1: Аутентификация -> поиск хешированного ключа, определение арендатора
Стадия 2: Нормализация ввода -> канонизация модели/параметров, подсчёт байтов
Стадия 3: Принятие решения по политике -> РАЗРЕШИТЬ / ПОНИЗИТЬ КАЧЕСТВО / БЛОКИРОВАТЬ
Стадия 4: Контроль квот -> ограничение частоты + проверка бюджета (Redis)
Стадия 5: Проверка кеша -> только если temperature=0 и политика разрешает
Стадия 6: Вызов провайдера -> ограничение по времени, предохранитель (circuit breaker)
Стадия 7: Фильтрация ответа -> удаление метаданных провайдера, маскировка PII
Стадия 8: Аудит + агрегация -> запись в PostgreSQL, увеличение счётчиков
Клиент получает ответ

Сама архитектура опирается на три компонента хранения. PostgreSQL для долговечных данных — арендаторы, ключи, политики, аудиторские логи. Redis для быстрой обработки — счётчики лимитов запросов, семафоры, возможно, кеш. И, наконец, сами экземпляры шлюза без состояния, расположенные за балансировщиком нагрузки. Масштабирование горизонтальное. Проще простого.

Искусство политики: не все блокировки одинаковы

Решение, которое делает шлюз или ломает его — это то, как он обрабатывает применение политик. Большинство команд по умолчанию выбирают либо «блокировать всё, что превышает лимиты», либо «логировать всё, но никогда не блокировать». Оба варианта… неправильные. Катастрофически неправильные.

Шлюз поддерживает три режима, настраиваемых для каждого арендатора, для каждой политики. Вот где кроется магия.

HARD — Отклонить запрос при достижении лимита. Возвращает 429 (лимит запросов) или 402 (превышение бюджета) с кодом причины. Это для арендаторов на платных тарифах, где перерасход недопустим. Без исключений. Без аргументов.

SOFT — Понизить качество запроса вместо его отклонения. Шлюз перезаписывает запрос: переключается на более дешёвую модель, уменьшает max_tokens, ужесточает параметры. Пользователь получает ответ — просто не премиум-качества. Это как получить место в эконом-классе вместо первого. Лучше, чем ничего.

OBSERVE — Разрешить запрос, но пометить его в аудиторском логе. Это критически важно для развёртывания новой политики. Вы точно видите, какие арендаторы были бы заблокированы или понижены в качестве, не затрагивая их фактически. Вы проверяете политику на реальном трафике, прежде чем переключиться на HARD или SOFT. Это единственный разумный путь развёртывания изменений.

Режим OBSERVE — практичный. Вы никогда не установите правильные пороговые значения политики с первой попытки. Установка их, работа в режиме OBSERVE в течение двух недель, анализ трафика, который был бы заблокирован, а затем переключение на HARD или SOFT — единственный безопасный путь развёртывания.

Управление состоянием: основа базы данных

Пять таблиц — всё, что вам нужно для долговечного состояния. Это лаконично. Это эффективно.

tenants

id, name, status (ACTIVE/SUSPENDED), created_at

api_keys — ключи никогда не хранятся в открытом виде. Слава богу.

id, tenant_id, key_hash, scopes, status,
created_at, last_used_at, rotated_at

policies — одна строка на арендатора. Здесь живут правила.

tenant_id,
allowed_models (json),
max_prompt_tokens (integer),
max_completion_tokens (integer),
max_requests_per_minute (integer),
max_budget_usd (decimal),
// ... и так далее для других настроек

usage_rollups — для ежедневных итогов. Потому что нужно видеть общую картину.

tenant_id, model, date, total_prompt_tokens, total_completion_tokens, total_cost_usd, total_requests

audit_logs — основа основ для отладки и соответствия требованиям.

id, tenant_id, key_id, request_timestamp, request_body_hash, response_status, response_body_hash, model_used, prompt_tokens, completion_tokens, cost_usd, latency_ms

Настоящий MVP: Наблюдаемость (Observability)

Когда клиент кричит о некорректном AI-выводе, вам нужны данные. Не оправдания. Аудиторские логи предоставляют криминалистический след. Вы можете реконструировать точный запрос, использованную модель и полученный ответ. Это не только для отладки; это необходимо для соответствия требованиям и разрешения споров. Представьте, как пытаться объяснить счёт в $47 000 без логов. Неприятно.

Этот шлюз — не просто механизм контроля затрат; это операционная необходимость. Он превращает интеграцию LLM из дикого запада и всеобщего хаоса в структурированное, управляемое и, осмелюсь сказать, прибыльное предприятие. Создание этого сейчас означает, что вы не будете тем, кто будет отвечать на эти душераздирающие звонки с инвойсами позже. Ваш финансовый директор будет вам благодарен. Ваши разработчики, возможно, даже смогут спать по ночам.


🧬 Связанные материалы

Written by
Open Source Beat Editorial Team

Curated insights, explainers, and analysis from the editorial team.

Worth sharing?

Get the best Open Source stories of the week in your inbox — no noise, no spam.

Originally reported by Dev.to