Unser Health-Check hat einen gesunden Modellserver an einem Tag achtmal neu gestartet
Ops
Am 22. Juli hat ein Watchdog unseren lokalen Modellserver achtmal neu gestartet. Keiner dieser Neustarts ging auf einen Absturz zurück. Die Prüfung, die das Modell am Laufen halten sollte, war genau das, was es zu Fall brachte.
Was passiert ist
Der Modellserver führte vLLM auf einem NVIDIA GB10-System aus und lieferte etwa 8 Tokens pro Sekunde für eine einzelne Anfrage. Alle fünf Minuten sandte ein Watchdog eine echte Chat-Anfrage und wartete bis zu 45 Sekunden auf die Antwort. Fünf fehlgeschlagene Prüfungen in Folge bedeuteten einen hängenden Server, und der Watchdog startete ihn neu. Ein Neustart nahm das Modell für mehrere Minuten aus dem Betrieb, während etwa 19 GB Gewichte erneut geladen wurden.
An diesem Tag hielt ein Batch-Job zwei bis vier Anfragen minutenlang auf dem Server beschäftigt. Die Anfrage des Watchdogs wartete in der Warteschlange dahinter, lief in die Zeitüberschreitung und zählte als Fehler. Nach fünf solchen Prüfungen wurde ein gesunder Server neu gestartet. Wir hatten eine „busy“-Flag-Datei, die der Watchdog beachtete, aber das Batch-Job setzte sie nie.
Wie ein falscher Neustart zum nächsten führte
Jeder Neustart ließ die laufenden Anfragen mit einem 500-Fehler fehlschlagen („cannot schedule new futures after shutdown“). Ein zweiter Watchdog zählte 500-Fehler und startete den Server neu, wenn es zu viele waren; je mehr Fehler er sah, desto schneller handelte er. So ließ jeder falsche Neustart den nächsten früher eintreten. Insgesamt konnten vier separate Watchdogs diesen Server auf Timern von 5, 10, 15 und 30 Minuten neu starten.
Die daraus abgeleitete Regel
Ein Health-Check darf nicht das nutzen, was er überwacht. Die knappe Ressource eines Modellservers sind die Slots für laufende Anfragen. Eine Prüfung, die einen dieser Slots belegt oder auf einen wartet, ist Teil der Last, die sie beurteilen soll. Prüfen Sie günstig, und starten Sie nur dann neu, wenn Sie nachweisen können, dass der Server hängt.
Die Prüfung, die sie ersetzte
vLLM stellt eigene Zähler unter /metrics bereit. Die neue Prüfung liest diese zuerst:
- Anfragen laufen und die Engine macht Fortschritte: gesund und beschäftigt. Es wird keine Testanfrage gesendet.
- Anfragen laufen und kein Fortschritt zwischen zwei Auslesungen: hängend. Dies ist der Fall, der weiterhin einen Neustart auslöst.
- Nichts läuft: im Leerlauf. Nur dann fragt die Prüfung eine kurze Antwort an, die eine im Leerlauf befindliche Engine sofort liefert.
Die erste Version zählte generierte Tokens als Fortschritt. Sie bestand acht Tests, und beim ersten Live-Einsatz fand sie den Server beschäftigt und gesund: 2 laufende Anfragen, 107 neue Tokens zwischen den beiden Auslesungen.
Was wir seitdem geändert haben
- Engine-Schritte, keine Ausgabe-Tokens. Während vLLM einen langen Prompt liest, erzeugt es eine Weile keine Ausgabe-Tokens, führt aber weiterhin Schritte aus. Das Zählen der Schritte (die Anzahl von vllm:iteration_tokens_total) verhindert, dass ein langer Prompt wie ein hängender Server aussieht.
- Zwei Wartezeiten vor „stuck“, damit eine kurze Pause nicht als Fehler gewertet wird.
- Ein Neustart zwischen den beiden Auslesungen wird erkannt durch die Prozessstartzeit in denselben Metriken; die Prüfung bittet dann um eine Antwort, anstatt Zähler aus zwei verschiedenen Prozessen zu vergleichen.
- Ein Proxy wird nur über /models geprüft. Hinter einem Least-Connection-Proxy kann jeder Abruf von /metrics von einem anderen Backend stammen, wie wir feststellten, als wir eine Kopie des Modells auf zwei Maschinen laufen ließen. Die Backends werden direkt geprüft.
Der Unterschied ist leicht zu erkennen. Als wir diese Notiz schrieben, verarbeiteten beide Modellserver jeweils 12 Anfragen, ihr Limit. Eine Testanfrage hätte in der Warteschlange gestanden. Die neue Prüfung meldete beide als beschäftigt und gesund, mit 126 und 101 Tokens pro Sekunde, ohne eine Anfrage zu senden.
Factory Floor 1.0.2 liefert diese Prüfung als models/llm-health.py, mit Tests für inaktive, beschäftigte, hängende und neu gestartete Server, einen Server ohne Metriken, einen Proxy und ein totes Backend.