Розробка AI-мікросервісу під ключ: FastAPI, Docker, масштабування

AI-сервіс, який упевнено працює на демонстрації й падає під реальним навантаженням, — знайома історія. Ми розробляємо AI-мікросервіси під ключ: проєктуємо схему, збираємо, тестуємо під піковим навантаженням і передаємо команді з документацією. Супроводжуємо запуск, тому сервіс витримує зростання звернень, а не потребує постійного втручання.
Часті запитання

Розробка AI-мікросервісу: що ламається під навантаженням

У розробці AI-мікросервісу демонстраційний контур виглядає переконливо: один запит, одна модель, чиста пам'ять.

Щойно на вхід надходить реальний потік, час відповіді під навантаженням перестає бути передбачуваним — і першим це помічає користувач, який іде, не дочекавшись відповіді.

Причина зазвичай одна: виведення моделі виконується прямо в обробнику запиту, синхронно й без обмеження паралелізму.

Черга запитів зростає швидше, ніж робочі процеси встигають її розбирати, але сервіс продовжує приймати нові з'єднання — замість швидкої відмови він накопичує затримку. Далі спрацьовує нелінійність: що довша черга, то довше живе кожен запит і то більше пам'яті він утримує.

Піковий трафік добиває контур відсутністю зрозумілої деградації. Немає ліміту на одночасні обчислення, немає порогу, після якого сервіс чесно відповідає «зайнятий», немає розігріву моделі під час старту й обмеження на розмір вхідних даних.

Підсумок — відмова сервісу цілком: падіння процесів через пам'ять, завислі з'єднання, втрачені запити й ручний перезапуск, який не гарантує, що наступний пік пройде інакше.

Окрема проблема — спостережуваність. Без метрик за довжиною черги й часом відповіді збій виявляють за скаргами, а не за графіком. Навіть сервіс, акуратно зібраний на FastAPI з асинхронними обробниками, без цих рамок поводиться як прототип.

Розбираємо, як це закривається: ізоляція обчислень, черга з лімітами й чесна деградація замість тихого падіння.

Що змінюється після впровадження: вимірювані ефекти

Ефекти впровадження фіксуємо як метрики до початку робіт: знімаємо поточний час випуску змін, історію відновлень після збоїв і частку ручних операцій супроводу. Через кілька тижнів після запуску ті самі заміри повторюємо — видно, що змінилося за фактом, а не «стало зручніше».

Час випуску змін скорочується в рази

Сервіс на FastAPI описаний конфігурацією, тому середовище піднімається відтворювано, а не «на тій машині, де працювало».

Зміна проходить автотести й викладку за одним і тим самим сценарієм: замість днів ручного складання й узгоджень — години, а для типових правок логіки відповіді — десятки хвилин.

Відновлення стає передбачуваним

Кожен реліз позначений образом, попередня версія залишається доступною для відкату. Обмеження за пам'яттю й часом відповіді задані явно, тому перезапуск контейнера повертає сервіс у робочий стан за хвилини, а не після ручного розбору логів.

Зникає цілий клас відмов під час перевантаження

Навантажувальне тестування прогонимо на профілі, близькому до пікового: черги, таймаути й поведінка під час відмови зовнішньої моделі перевіряються заздалегідь. Сервіс деградує керовано — часткові відповіді й повтори замість падіння всього сценарію в користувача.

Менше ручних операцій супроводу

Моніторинг будується на метриках затримки, частки помилок і глибини черги, а типові реакції описані в регламенті. Черговий отримує сигнал до того, як про проблему повідомить користувач, і не витрачає час на ручний перезапуск.

Режими роботи сервісу: синхронний, потоковий, пакетний

Режим роботи вибирають не за замовчуванням, а за тим, як споживач отримує результат. Синхронний повертає готову відповідь в одному запиті, потоковий віддає фрагменти в міру генерації, пакетний приймає набір завдань і складає результати вивантаженням. Від цього залежать тайм-аути, пропускна здатність і те, скільки простоюють робочі процеси.

Режим Коли підходить Обмеження режиму
Синхронний Короткі завдання: класифікація, вилучення полів, відповідь за одним документом З'єднання тримається до кінця генерації: довга відповідь упирається в тайм-аути клієнта й проксі, пропускна здатність падає зі зростанням одночасних запитів
Потоковий Діалоги й довгі тексти, де перші слова потрібні користувачеві негайно Обрив каналу рве відповідь, відданий фрагмент не переграти, вищі вимоги до стабільності мережі й журналювання
Пакетний Масова обробка: нічні прогони по архіву, перерахунок індексів, розбір вивантажень Результату немає «зараз»: потрібні черга, сховище проміжних результатів і контроль провалів за кожним завданням

Що врахувати до старту

Режими комбінують в одному сервісі: діалог іде потоково, а важкі прогони йдуть в окремий пул процесів, щоб пакетна обробка не з'їдала пропускну здатність онлайн-запитів.

Обмеження кожного режиму ми фіксуємо в контракті — тайм-аути, розмір порції, поведінку під час обриву, — щоб вони не спливли вже в продакшені.

Порядок робіт: аудит, схема, розробка, передача

Порядок робіт захищає від частих помилок: модель готова, а даних для неї немає або виклики впираються в ліміти суміжної системи. Маршрут іде від розбору поточного контуру до передачі — на кожному кроці залишається артефакт, який перевіряється до старту наступного.

  1. Аудит поточного контуру. Розбираємо джерела даних, їхню повноту й доступність, обмеження інфраструктури, вимоги до часу відповіді. На виході — карта ризиків і розуміння, де рішення дає ефект.
  2. Схема взаємодії. Фіксуємо, хто викликає сервіс, у якому форматі надходять дані, як обробляються відмови й що відбувається за недоступності моделі. Схему узгоджуємо до коду: правки на цьому кроці коштують найдешевше.
  3. Перевірка на історичних даних. Збираємо набір прикладів і порівнюємо моделі за метриками завдання: частка правильних відповідей, повнота, кількість хибних спрацювань. Так вибираємо підхід і поріг для включення в реальний потік.
  4. Розробка AI-мікросервісу. Модель ізольована від бізнес-логіки, версії моделей і журнал запитів ведуться окремо. Складання й розгортання відтворювані — стенд не розходиться з робочим контуром.
  5. Навантажувальна перевірка. Прогонимо сервіс на реальному профілі запитів: час відповіді під піком, поведінка під час відмов, зростання черги. За результатами налаштовуємо ліміти й правила масштабування.
  6. Передача в супровід. Віддаємо конфігурації, схему, регламент оновлення моделі й розбору інцидентів, навчаємо команду. Перший час супроводжуємо релізи й стежимо за якістю на живому потоці.

Що залишається у вас: конфігурації, схеми, регламенти

Робота закінчується не демонстрацією, а набором артефактів, за якими сервіс живе без нас.

Усе, що ми робимо в процесі, оформлюється так, щоб ваша команда могла розгорнути середовище з нуля, пояснити перевіряючому, які дані куди йдуть, і викотити оновлення без листування з підрядником. Нижче — що саме передається в репозиторій і до внутрішньої бази знань.

  • Конфігурації середовищ — окремі набори параметрів для розробки, тестового й робочого контуру, секрети зберігаються поза репозиторієм і підставляються під час розгортання, тому той самий образ поводиться передбачувано всюди.
  • Схема потоків даних — звідки надходить запит, які моделі й сервіси його обробляють, що пишеться у сховище, що кешується й що йде в зовнішні системи; на схемі позначені точки, де дані знеособлюються.
  • Політики доступу — ролі й області видимості, правила випуску й відкликання ключів, обмеження частоти звернень, журналювання викликів з ідентифікатором запиту для розбору інцидентів.
  • Документація сервісу — опис контрактів, приклади запитів і відповідей, коди помилок і їхні причини, обмеження за розміром вхідних даних і поведінка під час перевантаження.
  • Регламент супроводу — порядок випуску версій, схема відкату на попередній образ, перелік типових збоїв і перших дій чергового, точки ескалації.
  • Метрики й оповіщення — набір показників часу відповіді, частки помилок і споживання ресурсів, пороги спрацювання й маршрут повідомлень до конкретної команди.
  • Інструкція з розгортання — покроковий запуск на чистому середовищі, вимоги до ресурсів, порядок міграції даних і перевірка працездатності після встановлення.

Кейс: як сервіс перестав падати під піковим навантаженням

Проєкт — сервіс автоматичної обробки документів: на вході файл, на виході розмітка полів і оцінка впевненості моделі.

У рівному потоці він працював передбачувано, але на піках, коли запитів надходило в 4–5 разів більше за звичайне, починав деградувати: час відповіді для 95% запитів зростав з 0,4 секунди до 8–9, частка відмов сягала 12%, а частина завдань губилася під час перезапуску контейнера.

Де було вузьке місце

Розрахунок моделі виконувався прямо в обробнику запиту: поки вона рахувала, робочий процес був зайнятий і не приймав нові з'єднання. Далі вмикалася лавина — черга зростала, очікування перевищувало ліміт, заданий клієнтом, клієнт повторював запит, і навантаження подвоювалося.

До цього додавався холодний старт: кожна нова репліка піднімалася кілька хвилин, тому масштабування запізнювалося щодо піку.

Що змінили й які метрики отримали

Розрахунок винесли в окремий пул воркерів, а веб-шар залишили тільки на приймання й валідацію — приймання з'єднань перестало залежати від завантаження моделі.

Запити пішли через чергу з обмеженим паралелізмом і об'єднанням дрібних файлів у пачки, результати перевикористовуються за контрольною сумою вмісту, модель піднімається один раз на процес.

На прийманні й валідації сервіс тримається на FastAPI — асинхронна обробка не блокує робочий процес.

Після перебудови пропускна здатність зросла в 3,5 раза на тому самому парку машин. На колишніх піках час відповіді для 95% запитів тримається в межах 0,5 секунди, частка відмов опустилася нижче 0,5%, повтори з боку клієнта майже зникли.

Перезапуск репліки більше не втрачає завдання: черга тримає їх до підтвердження обробки — вузьким місцем була не модель, а важкий виклик у критичному шляху запиту.

Що робити, якщо сервіс уже розгорнуто, але він не масштабується?

Уже розгорнутий сервіс відповідає на запити, але на зростанні навантаження час відповіді зростає й з'являються відмови — повна перебудова потрібна рідко. Вузьке місце зазвичай локальне: стан у пам'яті процесу, синхронна обробка важких запитів, відсутність метрик. Знімаємо профіль під навантаженням і знаходимо, де саме втрачається пропускна здатність.

Перша точка зростання — стан процесу. Якщо кеш, сесії або сама модель живуть усередині веб-процесу, другий екземпляр не підняти без втрати даних, а перезапуск рве активні запити.

Виведення моделі виноситься в окремий процес, веб-шар стає таким, що не зберігає стан, і екземпляри розмножуються за балансувальником.

Друга — синхронна обробка: довгий запит тримає обробник і не дає приймати нові. Черга завдань з окремими виконавцями розводить приймання й обчислення — масштабування йде за довжиною черги, а сплески згладжуються без простою.

Третя — середовище: пул з'єднань до бази, кеш гарячих відповідей, ліміти одночасних обчислень. Зростання часто впирається у вичерпання з'єднань або тайм-аути, а не в модель, і це виправляється налаштуваннями.

Далі — часткова переробка: міняємо вузли, а не систему. Контракти API й навчена модель залишаються, переписується шар запуску й додаються метрики — час відповіді за перцентилями, довжина черги, частка помилок. За ними видно, де межа й коли пора додавати ресурси.

Завершує роботу передача в супровід: схема розгортання, опис налаштувань, порядок дій у разі відмови, правила оповіщення. Команда замовника експлуатує сервіс далі сама або разом із нами.

Сумніви щодо навантаження, доступів і супроводу

Заперечення на цьому етапі зазвичай одні й ті самі: як переносити вже працюючу модель, хто і як отримує доступ до даних, чи не змішаються контури й що робити з дообученням після запуску. Нижче — прямі відповіді без загальних слів.

Принцип один: видача передбачень і навчання моделі розведені. Робочий контур обслуговує запити, окремий — готує й перевіряє нові версії, тому модель, ключі й конфігурацію можна міняти прямо під поточним навантаженням.

Як перенести працюючу модель без зупинки сервісу?

Нову версію випускаємо поряд зі старою: частина трафіку йде на неї, метрики якості й затримки порівнюються, у разі розходження вага повертається на попередню. Перемикання займає секунди, зупинка процесів не потрібна.

Який доступ до даних потрібен сервісу?

Тільки читання потрібних полів через сервісний обліковий запис, з ротацією ключів і журналом звернень. Копії за межі вашого контуру не вивантажуються: сервіс розгортається там, де лежать дані.

Навіщо ізолювати середовища?

У розробки, передпродуктивного й робочого контурів свої бази, ключі й конфігурації за однакових образів. Перевірки йдуть на знеособлених наборах, тому тестовий запуск не зачіпає робочі дані.

Що відбувається з дообученням після запуску?

Дообучення йде в окремому контурі й не впливає на видачу. Нова версія спочатку рахується на живому трафіку в тіньовому режимі, і лише за збігу з поточною за ключовими метриками отримує частку запитів.

Хто відповідає за сервіс після здачі?

Передаємо регламенти, панелі метрик і алерти щодо затримки та частки помилок, схему оновлення моделі. Супровід іде за узгодженим часом реакції на інцидент — з розбором причин, а не тільки перезапуском.

Обговоримо завдання й повернемося з оцінкою та планом

Щоб оцінка робіт була предметною, а не діапазоном «від і до», починаємо з розбору завдання. Опишіть сценарій у вільній формі: які дані надходять на вхід, який результат потрібен на виході, де рішення має працювати — у вашому контурі чи в хмарі.

Далі достатньо кількох уточнень щодо навантаження й обмежень. Що конкретніші вихідні дані, то менше припущень у плані впровадження й то точніший склад команди під ваш випадок.

  • Сценарій і дані: що подається на вхід, у якому вигляді надходить відповідь, хто цим користується.
  • Навантаження: скільки запитів у піку й який час відповіді вважається прийнятним.
  • Якість: що вважається помилкою й яка частка помилок допустима на старті.
  • Поточний стек: мови, бази, черги, куди рішення має вбудуватися й за якими інтерфейсами.
  • Обмеження щодо даних: де вони лежать, що не можна виносити за контур, які потрібні доступи.
  • Строки й точки контролю: до якої дати потрібен перший робочий варіант і хто приймає результат.

У відповідь повертаємося з оцінкою робіт за етапами, планом впровадження з контрольними точками й складом команди — з ролями та зоною відповідальності кожного. Окремо показуємо ризики: де якість може впертися в дані, а де навантаження потребуватиме перегляду схеми.

Якщо завдання допускає кілька шляхів, дамо варіанти та їхній вплив на строк — вибір залишиться за вами.

Опишіть завдання листом або на созвоні — повернемося з оцінкою та планом.

Напрямки AI-розробки

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1369
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    816
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1141