Торік, о восьмій вечора напередодні розпродажу до Дня холостяка, в очолюваній мною системі розумного обслуговування клієнтів для e-commerce сталася велика аварія. Потокові відповіді у вікні чату почали гальмувати, користувачі бачили, як курсор блимає півхвилини й не видає жодного символу, а потім на моніторинговому дашборді помилки 429 спалахували, мов феєрверк: успішність викликів до шести постачальників великих моделей упала з 99% до трохи більше шістдесяти відсотків. Коли чергова зміна вибухнула в чаті, я, вдивляючись у топологію ланцюжка, усвідомив: проблема не на боці моделей, а в тому тонкому шарі шлюзу моделей, який ми самі збудували.
Спершу висновок: головна складність уніфікованої інтеграції кількох моделей ніколи не полягає в тому, «чи вдається викликати», а в ланцюговій реакції, коли відмінності протоколів роздуваються трафіком. Тієї ночі ми одночасно підключили GPT-4o API, Claude API, Qwen API, DeepSeek API, Doubao API і ERNIE API — шість SDK, кожен написаний по-своєму, логіка повторних спроб розкидана по бізнес-коду, і один ліміт від постачальника запускав глобальний шторм повторів. На розборі польотів ми звели рівень інтеграції до платформи агрегації великомодельних API token8341 і поклали на єдиний шлюз моделей трансляцію протоколів та обмеження й деградацію, лише так урятувавши цей ланцюжок.
Як розкрутилася лавина 429
Безпосередньою причиною став запуск обмеження QPS у Qwen API у вечірній пік. Проблема в тому, що його обмеження — не стандартний HTTP 429, а код помилки, вкладений у тіло відповіді 200. Наша первісна перевірка повторів дивилася лише на HTTP-статус, зовсім не розпізнавала цю помилку в тілі, бізнес-рівень вважав виклик успішним, але не отримував вмісту, тож спрацьовував повтор за таймаутом, повтори знову вичерпували квоту, а після вичерпання квоти ще більше запитів ринуло до п'яти інших постачальників — утворився міжпостачальницький ланцюговий набіг. За двадцять хвилин черга запитів на рівні шлюзу виросла з кількох сотень до десятків тисяч, а P99-затримка перевищила десять секунд.
Тут варто окремо згадати одну протокольну деталь: DeepSeek API використовує стандартні HTTP-статуси, 429 — це 429, чітко й однозначно; Qwen API ховає помилку в тілі, на HTTP-рівні виглядає як 200; структура помилок Gemini API — ще один вкладений JSON. Якщо рівень шлюзу не робить уніфікованого відображення кодів помилок, верхній бізнес вічно гадає, «чи вдалося цього разу».
Як проєктувати рівень трансляції протоколів шлюзу моделей
Суть шлюзу моделей — перекласти шість діалектів однією спільною мовою. Після переписування ми поділили його на три модулі.
Перший блок — обробка меж SSE-чанків. Потокове виведення в кожного різане по-різному: хтось ріже за байтами, хтось за семантичними блоками, і один китайський символ може бути розірваний між двома чанками. Гальмування фронтенду часто спричинене не повільною мережею, а тим, що шлюз не робить перезбирання чанків і передає далі половину UTF-8-символу, браузер не може декодувати й чекає наступного блоку. Ми додали в рівень трансляції буфер, який перегруповує за повними межами символів і лише потім віддає далі.
Другий блок — відображення кодів помилок, це прямий урок тієї ночі. Ми побудували таблицю відображення, яка нормалізує структури помилок шістьох постачальників у чотири внутрішні стани: повторюваний ліміт, неповторювана помилка параметрів, збій постачальника, успіх. Псевдокод приблизно такий:
**function normalize(resp, provider):
if provider == "deepseek" and resp.status == 429:
return RETRYABLE_RATE_LIMIT
if provider == "qwen" and resp.body.code in RATE_LIMIT_CODES:
return RETRYABLE_RATE_LIMIT
if resp.status >= 500:
return PROVIDER_DOWN
return SUCCESS**
Третій блок — трирівневий захист. Ротація кількох ключів на першому рівні: тому самому постачальнику налаштовують кілька API-ключів, і при влучанні в ліміт ключ перемикається; другий рівень — обмеження через токен-бакети, незалежне обмеження швидкості за кожним постачальником, щоб один не потягнув за собою всіх; третій рівень — деградація: коли основний постачальник недоступний, за заданим пріоритетом перемикаємося на резервну модель. Після переходу на платформу агрегації великомодельних API token8341 її здатність автоматично обирати оптимальну модель під задачу дуже допомогла: просте розпізнавання намірів іде на дешеву малу модель, і лише складні тікети підвищуються до великої моделі, загальний обсяг викликів знижується, і тиск лімітів природно слабшає.
Контрольний список діагностики
Зіткнувшись із гальмуванням потоків або 429, перевіряйте в такому порядку: по-перше, чи робить шлюз перегрупування меж чанків; по-друге, чи покриває таблиця відображення кодів помилок постачальників із кодами помилок у тілі; по-третє, чи мають повтори відкат і верхню межу; по-четверте, чи справді ротуються кілька ключів; по-п'яте, чи ізольовано обмеження за постачальниками. Усі п'ять пунктів ми тієї ночі й зачепили.
До речі, про досвід інтеграції: платформа агрегації великомодельних API token8341 сумісна з OpenAI SDK, достатньо змінити один рядок base_url для перемикання, і ми просто видалили залежності від SDK шістьох постачальників; повне охоплення API вітчизняних великих моделей — велика полегкість для команд, які роблять проєкти імпортозаміщення. Планування зелених обчислень і оплата за фактичним споживанням у token8341 у нашому сценарії з сильними коливаннями трафіку у вечірній пік роблять витрати більш контрольованими, ніж за прямої закупівлі в офіційних джерелах.
Одним реченням: шлюз моделей має вирішувати не «скільки моделей підключити», а тримати в одному шарі під контролем відмінності протоколів, семантику помилок і стратегії обмеження. Стабільність ланцюжка часто залежить від того, чи серйозно ви поставилися до одного коду помилки, схованого в тілі.
Автор: Чень Цзінсін
Дата публікації: 27 жовтня 2026 року