Проверката на състоянието рестартира здрав сървър за модели осем пъти за един ден
Операции
На 22 юли watchdog рестартира локалния ни сървър за модели осем пъти. Нито един от тези рестарти не е бил предшестван от срив. Проверката, която трябваше да поддържа модела активен, беше точно това, което го сваляше.
Какво се случи
Сървърът на модела е изпълнявал vLLM на една машина NVIDIA GB10 и е генерирал около 8 токена в секунда за единична заявка. На всеки пет минути watchdog изпращаше реална заявка за чат и изчакваше до 45 секунди за отговор. Пет последователно неуспешни проверки означаваха блокиран сървър и watchdog го рестартираше. Рестартът изключваше модела за няколко минути, докато около 19 GB тегла се заредеха отново.
Онзи ден пакетна задача задържа два до четири заявки на сървъра за по няколко минути всяка. Заявката на watchdog-а изчака на опашката зад тях, изчерпа времето си и беше отчетена като грешка. След пет подобни проверки здрав сървър беше рестартиран. Имахме файл-маркер за „заетост“, който watchdog-ът спазваше, но пакетната задача никога не го задаваше.
Как един фалшив рестарт доведе до следващия
Всяко рестартиране прекъсваше текущите заявки с грешка 500 („cannot schedule new futures after shutdown“). Второ watchdog броеше грешките 500 и рестартираше сървъра, когато те бяха твърде много, а колкото повече грешки виждаше, толкова по-скоро действаше. Така всяко фалшиво рестартиране караше следващото да настъпи по-скоро. Общо четири отделни watchdog можаха да рестартират този сървър, на таймери за 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, с тестове за неактивни, заети, заседнали и рестартирани сървъри, сървър без метрики, прокси и мъртъв бекенд.