← Назад к проектам

AI API Gateway: Unified LLM Traffic Routing Infrastructure

> Закрытый репозиторий. Доступен для code review по запросу.

▍ Проблематика

Организации, использующие несколько провайдеров больших языковых моделей (OpenAI, Anthropic, Google и др.), сталкиваются с системными инфраструктурными проблемами:

  • Фрагментация протоколов: Каждый провайдер имеет собственный формат запросов/ответов, семантику streaming (SSE), обработку ошибок и модель аутентификации.
  • Rate limits и квоты: Жёсткие ограничения на уровне аккаунта/минуты/токена, требующие интеллектуальной балансировки нагрузки между пулами учётных записей.
  • Непредсказуемые задержки: Фазы «обдумывания» (thinking) у frontier-моделей длятся до 2-3 минут, вызывая idle timeout disconnects на уровне балансировщиков.
  • Отсутствие единого observability: Расход токенов, latency-распределение, error rates — разрозненные метрики без единого контроля.

Бизнесу требуется единый шлюз (Gateway), предоставляющий унифицированный OpenAI-совместимый API, прозрачную маршрутизацию между провайдерами, устойчивость к сетевым аномалиям и строгую консистентность распределённого состояния между узлами.

▍ Архитектура

Система представляет собой высоконагруженный reverse-proxy и API-шлюз, написанный полностью на Rust. Cargo workspace: 15+ крейтов, чёткое разделение на domain/infra/api слои.

┌─────────────────────────────────────────────────────────┐
│                     CLIENTS                             │
│         (OpenAI SDK, curl, любой HTTP-клиент)           │
└───────────────────────┬─────────────────────────────────┘
                        │ OpenAI-compatible API
                        ▼
┌─────────────────────────────────────────────────────────┐
│                   GATEWAY LAYER                         │
│  ┌──────────┐  ┌──────────────┐  ┌───────────────────┐  │
│  │ Protocol │  │   Session    │  │  Load Balancer    │  │
│  │ Adapter  │  │   Affinity   │  │  (least-loaded)   │  │
│  │ (transl.)│  │   Manager    │  │                   │  │
│  └────┬─────┘  └──────┬───────┘  └────────┬──────────┘  │
│       │               │                   │             │
│  ┌────▼───────────────▼───────────────────▼──────────┐  │
│  │              STATE LAYER                          │  │
│  │  ArcSwap (lock-free config)  +  CRDT/LWW sync     │  │
│  │  PostgreSQL (Event Sourcing + streaming replica)  │  │
│  └───────────────────────────────────────────────────┘  │
└───────────────────────┬─────────────────────────────────┘
                        │ Managed connection pool
                        ▼
┌─────────────────────────────────────────────────────────┐
│               UPSTREAM PROVIDERS                        │
│     OpenAI    │    Anthropic    │    Google    │  ...   │
└─────────────────────────────────────────────────────────┘

Ключевые компоненты:

  • Protocol Adapter: двунаправленная трансляция форматов (OpenAI ↔ проприетарные API провайдеров). Клиенты работают через единый OpenAI-совместимый интерфейс, независимо от того, какой провайдер обрабатывает запрос.
  • Session Affinity Manager: персистентная привязка «сессия → аккаунт провайдера», выживающая после рестартов сервиса. Максимизирует утилизацию кэша контекста (до 128K токенов) и обеспечивает предсказуемое поведение для stateful-диалогов.
  • Load Balancer: least-loaded distribution с анти-thundering-herd алгоритмом при первичном назначении сессии. Распределяет нагрузку между пулом учётных записей провайдеров.
  • State Layer: `ArcSwap` для lock-free горячей перезагрузки конфигурации (zero contention на hot path). CRDT/LWW с tombstone-записями для синхронизации состояния между узлами. PostgreSQL с Event Sourcing и потоковой репликацией как единый источник истины.
  • Managed Connection Pool: RAII-контролируемый пул соединений с агрессивным HTTP/2 keepalive для предотвращения idle timeout disconnects во время длительных фаз генерации.

Инфраструктура:

  • Frontend: Административный дашборд на Rust (Leptos + WASM) — real-time мониторинг, управление аккаунтами, аналитика расходов.
  • DevOps: Nix Flakes (воспроизводимые сборки) + systemd socket activation (zero-downtime deploy).

▍ Метрики (Production Data)

Система работает под реальной производственной нагрузкой:

73,000+ / мес
API-запросов
2.7 млрд / нед
Обработано токенов
124 часа / нед
GPU-инференс
28.3 req/min
Пиковая нагрузка
~94%
Аптайм
45-81%
Prompt Cache hit rate
<30с (вкл. thinking)
Средняя задержка
~6% (разрешено)
Error rate
900+ тестов
Кодовая база

▍ Ключевые инженерные решения

Проблема
Состояние аккаунтов, квот и сессий должно быть консистентно между узлами без центрального координатора.
Решение
LWW (Last-Write-Wins) CRDT с tombstone-записями. Каждый узел автономен; конфликты разрешаются по временной метке. Tombstones предотвращают «воскрешение» удалённых записей при merge.
Отвергнутая альтернатива
Raft/Paxos — избыточная сложность для eventually-consistent workload; CRDT не требует leader election.
Проблема
Конфигурация (список провайдеров, квоты, routing rules) меняется в runtime. Классический RwLock создаёт contention при тысячах конкурентных запросов.
Решение
ArcSwap — атомарная замена Arc<Config> без блокировок. Читатели получают snapshot за O(1), writer публикует новую версию атомарно. Zero contention на hot path.
Проблема
При обрыве upstream-соединения во время SSE streaming, клиент получает незавершённый поток — ломает парсинг на стороне SDK.
Решение
Gateway перехватывает сетевую ошибку и генерирует синтетический `[DONE]` chunk с `finish_reason: "error"`, конвертируя транспортный сбой в штатное завершение потока. Клиентский код обрабатывает это как обычное завершение, а не как exception.
Проблема
Frontier-модели «думают» 60-180 секунд. Upstream-балансировщики разрывают idle-соединения по timeout (30-60s), хотя запрос ещё обрабатывается.
Решение
Агрессивный HTTP/2 PING keepalive на уровне мультиплексора. Поддерживает соединение активным в глазах промежуточных load balancers, не мешая работе модели.
Проблема
LLM-провайдеры кэшируют контекст диалога (до 128K токенов) на стороне конкретного аккаунта. Смена аккаунта = потеря кэша = повторная оплата prompt tokens.
Решение
Персистентная привязка «клиентская сессия → аккаунт провайдера», сохраняемая в PostgreSQL. Выживает после рестартов. При назначении новой сессии — least-loaded алгоритм с антипаттерном thundering herd.

▍ Технологический стек

Backend
Rust, Axum, Tokio, SQLx, PostgreSQL, ArcSwap, DashMap
Frontend
Rust, Leptos, WebAssembly (WASM)
DevOps
Nix (Flakes), Systemd (socket activation), Podman

▍ Что демонстрирует этот проект

Системная архитектура
Проектирование распределённого stateful-сервиса, устойчивого к сетевым аномалиям, partial failures и длительным задержкам upstream.
Распределённые системы
Практическое применение CRDT, Event Sourcing и потоковой репликации PostgreSQL в production.
Performance Engineering
Lock-free hot path, zero-copy streaming, управление пулами соединений без утечек под постоянной нагрузкой.
Production Operations
Zero-downtime deploy, глубокая инструментация (метрики, трейсинг), graceful degradation при отказах upstream-провайдеров.
Rust Ecosystem Mastery
Workspace из 15+ крейтов, 900+ тестов, type-safe domain model с exhaustive pattern matching.

Готовы построить нечто подобное?

Начать проект