Náš kontrolní mechanismus osmkrát za den restartoval zdravý server s modelem
Provoz
Dne 22. července hlídač osmkrát restartoval náš lokální server s modelem. Za žádným z těch restartů nebyl pád. Kontrola, která měla model udržet v chodu, byla tím, co ho shazovalo.
Co se stalo
Server s modelem běžel na vLLM na jednom stroji NVIDIA GB10 a pro jeden požadavek produkoval přibližně 8 tokenů za sekundu. Každých pět minut mu hlídač poslal skutečný chatovací požadavek a čekal na odpověď až 45 sekund. Pět neúspěšných kontrol v řadě znamenalo zaseknutý server a hlídač ho restartoval. Restart na několik minut odebral model, zatímco se znovu načítalo přibližně 19 GB vah.
Ten den dávková úloha udržovala na serveru dva až čtyři požadavky v činnosti po dobu několika minut. Požadavek hlídače čekal ve frontě za nimi, vypršel mu čas a byl započítán jako selhání. Po pěti takových kontrolách byl restartován zdravý server. Měli jsme soubor s příznakem "busy", který hlídač respektoval, ale dávková úloha ho nikdy nenastavila.
Jak jeden falešný restart vedl k dalšímu
Každý restart ukončil probíhající požadavky chybou 500 ("cannot schedule new futures after shutdown"). Druhý hlídač počítal chyby 500 a restartoval server, když jich bylo příliš mnoho, a čím více chyb viděl, tím dříve zasáhl. Každý falešný restart tedy přiblížil ten další. Celkem mohly tento server restartovat čtyři samostatní hlídači na časovačích 5, 10, 15 a 30 minut.
Pravidlo, které jsme z toho vyvodili
Kontrolní mechanismus nesmí využívat to, co střeží. Vzácným zdrojem serveru s modelem jsou jeho sloty pro probíhající požadavky. Kontrola, která jeden z těch slotů zabere nebo na něj čeká, je součástí zátěže, kterou má posuzovat. Kontrolujte levně a restartujte pouze tehdy, když dokážete, že je server zaseknutý.
Kontrola, která ji nahradila
vLLM zveřejňuje vlastní čítače na /metrics. Nová kontrola nejprve čte ty:
- Probíhající požadavky a postupující engine: zdravý a zaneprázdněný. Není odeslán žádný testovací požadavek.
- Probíhající požadavky a žádný postup mezi dvěma čteními: zaseknutý. To je případ, který stále restartuje.
- Nic neběží: nečinný. Až teprve tehdy se kontrola zeptá na krátkou odpověď, kterou nečinný engine poskytne okamžitě.
První verze počítala vygenerované tokeny jako postup. Prošla osmi testy a při prvním ostrém běhu našla server zaneprázdněný a zdravý: 2 probíhající požadavky, 107 nových tokenů mezi dvěma čteními.
Co jsme od té doby změnili
- Kroky enginu, ne výstupní tokeny. Zatímco vLLM čte dlouhý prompt, chvíli negeneruje žádné výstupní tokeny, ale stále provádí kroky. Počítání kroků (počet vllm:iteration_tokens_total) zabraňuje tomu, aby dlouhý prompt vypadal jako zaseknutý server.
- Dvě čekání před vyhlášením zaseknutí, aby krátká pauza nebyla počítána jako chyba.
- Restart mezi dvěma čteními je zachycen pomocí času spuštění procesu ve stejných metrikách; kontrola pak vyžaduje odpověď místo porovnávání čítačů ze dvou různých procesů.
- Proxy je kontrolována pouze přes /models. Za proxy s nejnižším počtem spojení může každé čtení /metrics pocházet z jiného backendu, jak jsme zjistili, když jsme spustili kopii modelu na každém ze dvou strojů. Backendy jsou kontrolovány přímo.
Rozdíl je snadno patrný. Když jsme tuto poznámku psali, oba naše servery s modelem měly spuštěných 12 požadavků, což je jejich limit. Testovací požadavek by čekal ve frontě. Nová kontrola ohlásila oba jako zaneprázdněné a zdravé, při 126 a 101 tokenech za sekundu, aniž by jeden poslala.
Factory Floor 1.0.2 obsahuje tuto kontrolu jako models/llm-health.py, s testy pro nečinné, zaneprázdněné, zaseknuté a restartované servery, server bez metrik, proxy a mrtvý backend.