Ο έλεγχος υγείας μας επανεκκίνησε έναν υγιή διακομιστή μοντέλου οκτώ φορές μέσα σε μία ημέρα
Λειτουργίες
Στις 22 Ιουλίου ένας φύλακας επανεκκίνησε τον τοπικό διακομιστή μοντέλου μας οκτώ φορές. Καμία από αυτές τις επανεκκινήσεις δεν είχε κάποια κατάρρευση πίσω της. Ο έλεγχος που προοριζόταν να κρατήσει το μοντέλο σε λειτουργία ήταν αυτός που το έριχνε.
Τι συνέβη
Ο διακομιστής μοντέλου εκτελούσε vLLM σε ένα μηχάνημα NVIDIA GB10 και παρήγαγε περίπου 8 tokens ανά δευτερόλεπτο για ένα μόνο αίτημα. Κάθε πέντε λεπτά ένας φύλακας του έστελνε ένα πραγματικό αίτημα συνομιλίας και περίμενε έως 45 δευτερόλεπτα για την απάντηση. Πέντε αποτυχημένοι έλεγχοι στη σειρά σήμαιναν έναν διακομιστή σε αδιέξοδο και ο φύλακας τον επανεκκινούσε. Μια επανεκκίνηση αφαιρούσε το μοντέλο για αρκετά λεπτά, ενώ φορτώνονταν ξανά περίπου 19 GB βαρών.
Εκείνη την ημέρα μια εργασία δέσμης κρατούσε δύο έως τέσσερα αιτήματα απασχολημένα στον διακομιστή για λεπτά τη φορά. Το αίτημα του φύλακα περίμενε στην ουρά πίσω από αυτά, εξάντλησε τον χρόνο του και καταγράφηκε ως αποτυχία. Μετά από πέντε τέτοιους ελέγχους, ένας υγιής διακομιστής επανεκκινήθηκε. Είχαμε ένα αρχείο σήμανσης «απασχολημένος» που ο φύλακας σέβονταν, αλλά η εργασία δέσμης δεν το όριζε ποτέ.
Πώς μια λανθασμένη επανεκκίνηση οδήγησε στην επόμενη
Κάθε επανεκκίνηση απέτυχε στα αιτήματα σε εξέλιξη με σφάλμα 500 («cannot schedule new futures after shutdown»). Ένας δεύτερος φύλακας μετρούσε σφάλματα 500 και επανεκκινούσε τον διακομιστή όταν υπήρχαν πολλά, και όσο περισσότερα σφάλματα έβλεπε, τόσο νωρίτερα δρούσε. Έτσι, κάθε λανθασμένη επανεκκίνηση έκανε την επόμενη να έρχεται νωρίτερα. Συνολικά, τέσσερις ξεχωριστοί φύλακες μπορούσαν να επανεκκινήσουν αυτόν τον διακομιστή, σε χρονοδιακόπτες 5, 10, 15 και 30 λεπτών.
Ο κανόνας που βγάλαμε από αυτό
Ο έλεγχος υγείας δεν πρέπει να χρησιμοποιεί αυτό που φυλάσσει. Ο σπάνιος πόρος ενός διακομιστή μοντέλου είναι οι θέσεις για αιτήματα σε εξέλιξη. Ένας έλεγχος που καταλαμβάνει μία από αυτές τις θέσεις, ή περιμένει για μία, είναι μέρος του φορτίου που καλείται να κρίνει. Ελέγξτε φθηνά και επανεκκινήστε μόνο όταν μπορείτε να δείξετε ότι ο διακομιστής έχει κολλήσει.
Ο έλεγχος που τον αντικατέστησε
Το vLLM δημοσιεύει τους δικούς του μετρητές στο /metrics. Ο νέος έλεγχος τους διαβάζει πρώτα:
- Αιτήματα σε εξέλιξη και η μηχανή να κάνει πρόοδο: υγιής και απασχολημένη. Δεν στέλνεται δοκιμαστικό αίτημα.
- Αιτήματα σε εξέλιξη και καμία πρόοδος μεταξύ δύο αναγνώσεων: κολλημένη. Αυτή είναι η περίπτωση που ακόμα επανεκκινεί.
- Τίποτα σε εξέλιξη: αδρανής. Μόνο τότε ο έλεγχος ζητά μια σύντομη απάντηση, την οποία μια αδρανής μηχανή δίνει αμέσως.
Η πρώτη έκδοση μετρούσε τα παραγόμενα tokens ως πρόοδο. Πέρασε οκτώ δοκιμές και στην πρώτη ζωντανή εκτέλεσή της βρήκε τον διακομιστή απασχολημένο και υγιή: 2 αιτήματα σε εξέλιξη, 107 νέα tokens μεταξύ των δύο αναγνώσεων.
Τι αλλάξαμε έκτοτε
- Βήματα μηχανής, όχι διακριτικά εξόδου. Ενώ το vLLM διαβάζει ένα μεγάλο prompt, δεν παράγει διακριτικά εξόδου για λίγο αλλά συνεχίζει να κάνει βήματα. Η μέτρηση των βημάτων (ο αριθμός του vllm:iteration_tokens_total) εμποδίζει ένα μεγάλο prompt να φαίνεται σαν διακομιστής που έχει κολλήσει.
- Δύο αναμονές πριν το «κολλημένο», ώστε μια σύντομη παύση να μην μετράει ως αποτυχία.
- Μια επανεκκίνηση μεταξύ των δύο αναγνώσεων εντοπίζεται από τον χρόνο έναρξης της διαδικασίας στα ίδια metrics· ο έλεγχος τότε ζητά απάντηση αντί να συγκρίνει μετρητές από δύο διαφορετικές διαδικασίες.
- Ένας proxy ελέγχεται μόνο μέσω /models. Πίσω από έναν proxy με ελάχιστες συνδέσεις, κάθε ανάγνωση του /metrics μπορεί να προέρχεται από διαφορετικό backend, όπως διαπιστώσαμε όταν τρέξαμε ένα αντίγραφο του μοντέλου σε δύο μηχανές. Τα backend ελέγχονται απευθείας.
Η διαφορά είναι εύκολα ορατή. Καθώς γράφαμε αυτή τη σημείωση, και οι δύο διακομιστές μοντέλων μας εκτελούσαν 12 αιτήματα ο καθένας, το όριό τους. Ένα δοκιμαστικό αίτημα θα περίμενε στην ουρά. Ο νέος έλεγχος ανέφερε και τους δύο ως απασχολημένους και υγιείς, με 126 και 101 διακριτικά ανά δευτερόλεπτο, χωρίς να στείλει κάποιο.
Factory Floor 1.0.2 περιλαμβάνει αυτόν τον έλεγχο ως models/llm-health.py, με δοκιμές για διακομιστές σε αδράνεια, απασχολημένους, κολλημένους και επανεκκινημένους, έναν διακομιστή χωρίς metrics, έναν proxy και ένα νεκρό backend.