Наша перевірка стану вісім разів за день перезапустила справний сервер моделей
Операції
22 липня вартовий вісім разів перезапустив наш локальний сервер моделей. Жоден із цих перезапусків не був спричинений збоєм. Перевірка, яка мала тримати модель у робочому стані, саме й зупиняла її.
Що сталося
Сервер моделей працював на vLLM на одній машині NVIDIA GB10 та генерував близько 8 токенів на секунду для одного запиту. Кожні п’ять хвилин вартовий надсилав йому справжній запит чату та чекав на відповідь до 45 секунд. П’ять невдалих перевірок поспіль означали завислий сервер, і вартовий його перезапускав. Перезапуск позбавляв моделі на кілька хвилин, поки повторно завантажувалися ваги обсягом близько 19 ГБ.
Того дня пакетне завдання займало від двох до чотирьох запитів на сервері на кілька хвилин. Запит вартового чекав у черзі за ними, вичерпував час очікування та рахувався невдалим. Після п’яти таких перевірок справний сервер було перезапущено. У нас був файл прапорця «зайнято», який вартовий враховував, але пакетне завдання його ніколи не встановлювало.
Як один хибний перезапуск призводив до наступного
Кожен перезапуск завершував поточні запити з помилкою 500 («неможливо запланувати нові майбутні завдання після завершення роботи»). Другий вартовий рахував помилки 500 і перезапускав сервер, коли їх ставало надто багато, і чим більше помилок він бачив, тим швидше діяв. Тож кожен хибний перезапуск прискорював настання наступного. Загалом чотири окремих вартових могли перезапустити цей сервер за таймерами на 5, 10, 15 і 30 хвилин.
Правило, яке ми з цього винесли
Перевірка стану не повинна використовувати те, що вона захищає. Дефіцитним ресурсом сервера моделей є слоти для поточних запитів. Перевірка, яка займає один із цих слотів або чекає на нього, стає частиною навантаження, яке має оцінювати. Перевіряйте дешево й перезапускайте лише тоді, коли можете показати, що сервер завис.
Перевірка, яка замінила попередню
vLLM публікує власні лічильники за адресою /metrics. Нова перевірка спершу зчитує їх:
- Запити в роботі та прогрес рушія: справний і зайнятий. Тестовий запит не надсилається.
- Запити в роботі та відсутність прогресу між двома зчитуваннями: завис. Це випадок, який досі перезапускає сервер.
- Нічого не працює: простоює. Лише тоді перевірка запитує коротку відповідь, яку простоюючий рушій видає одразу.
Перша версія вважала прогресом згенеровані токени. Вона пройшла вісім тестів, а під час першого робочого запуску виявила сервер зайнятим і справним: 2 запити в роботі, 107 нових токенів між двома зчитуваннями.
Що ми змінили з того часу
- Кроки рушія, а не вихідні токени. Поки vLLM обробляє довгий запит, він деякий час не видає вихідних токенів, але продовжує виконувати кроки. Підрахунок кроків (значення лічильника vllm:iteration_tokens_total) не дає довгому запиту виглядати як завислий сервер.
- Дві паузи перед позначкою «завис», щоб коротка затримка не вважалася збоєм.
- Перезавантаження між двома зчитуваннями виявляється за часом запуску процесу в тих самих метриках; тоді перевірка запитує відповідь замість порівняння лічильників із двох різних процесів.
- Проксі перевіряється лише через /models. За проксі з найменшою кількістю з'єднань кожне зчитування /metrics може надходити від різного бекенду, як ми виявили, коли запустили копію моделі на двох машинах. Бекенди перевіряються напряму.
Різницю легко помітити. Коли ми писали цю нотатку, на обох наших серверах моделей виконувалося по 12 запитів — їхній ліміт. Тестовий запит чекав би в черзі. Нова перевірка повідомила про обидва сервери як зайняті та працездатні, зі швидкістю 126 і 101 токен за секунду, не надіславши жодного запиту.
Factory Floor 1.0.2 постачає цю перевірку у файлі models/llm-health.py, з тестами для серверів у режимах очікування, зайнятості, зависання та після перезавантаження, для сервера без метрик, проксі та непрацюючого бекенду.