การตรวจสอบสุขภาพของเราเริ่มการทำงานของเซิร์ฟเวอร์โมเดลที่ทำงานปกติใหม่ถึง 8 ครั้งในวันเดียว
ปฏิบัติการ
เมื่อวันที่ 22 กรกฎาคม ตัวตรวจสอบระบบได้เริ่มการทำงานของเซิร์ฟเวอร์โมเดลในเครื่องของเราใหม่ 8 ครั้ง โดยไม่มีครั้งใดเลยที่เกิดจากอาการขัดข้อง (crash) การตรวจสอบที่ควรจะทำให้โมเดลทำงานต่อเนื่อง กลับกลายเป็นตัวการที่ทำให้มันหยุดทำงาน
เกิดอะไรขึ้น
เซิร์ฟเวอร์โมเดลรัน vLLM บนเครื่อง NVIDIA GB10 หนึ่งเครื่อง และสร้างผลลัพธ์ประมาณ 8 token ต่อวินาทีสำหรับการร้องขอหนึ่งครั้ง ทุก ๆ 5 นาที ตัวตรวจสอบระบบจะส่งคำขอแชทจริงไปยังเซิร์ฟเวอร์และรอคำตอบนานสูงสุด 45 วินาที หากการตรวจสอบล้มเหลวติดต่อกัน 5 ครั้ง จะถือว่าเซิร์ฟเวอร์ค้าง และตัวตรวจสอบระบบจะเริ่มการทำงานใหม่ การเริ่มการทำงานใหม่จะทำให้โมเดลหายไปหลายนาทีขณะที่น้ำหนักโมเดลประมาณ 19 GB ถูกโหลดอีกครั้ง
ในวันนั้น งานแบบแบทช์ทำให้เซิร์ฟเวอร์ต้องจัดการคำขอ 2 ถึง 4 รายการอย่างหนักเป็นเวลาหลายนาทีต่อครั้ง คำขอของตัวตรวจสอบระบบต้องรอในคิวต่อจากงานเหล่านั้น หมดเวลา และนับเป็นการล้มเหลว หลังจากการตรวจสอบลักษณะนี้ 5 ครั้ง เซิร์ฟเวอร์ที่ทำงานปกติก็ถูกเริ่มการทำงานใหม่ เรามีไฟล์สถานะ "busy" ที่ตัวตรวจสอบระบบเคารพ แต่งานแบบแบทช์ไม่เคยตั้งค่ามันเลย
การเริ่มการทำงานใหม่ผิดพลาดหนึ่งครั้งนำไปสู่ครั้งถัดไปอย่างไร
การเริ่มการทำงานใหม่แต่ละครั้งทำให้คำขอที่กำลังดำเนินการล้มเหลวด้วยข้อผิดพลาด 500 ("cannot schedule new futures after shutdown") ตัวตรวจสอบระบบตัวที่สองนับจำนวนข้อผิดพลาด 500 และเริ่มการทำงานเซิร์ฟเวอร์ใหม่เมื่อมีมากเกินไป ยิ่งมันเห็นข้อผิดพลาดมากเท่าใด มันก็ยิ่งทำงานเร็วขึ้นเท่านั้น ดังนั้น การเริ่มการทำงานใหม่ผิดพลาดแต่ละครั้งจึงทำให้ครั้งถัดไปมาถึงเร็วขึ้น โดยรวมแล้ว ตัวตรวจสอบระบบ 4 ตัวแยกกันสามารถเริ่มการทำงานเซิร์ฟเวอร์นั้นใหม่ได้ ตามตัวจับเวลา 5, 10, 15 และ 30 นาที
กฎที่เราได้เรียนรู้จากกรณีนี้
การตรวจสอบสุขภาพต้องไม่ใช้ทรัพยากรที่มันคอยปกป้อง ทรัพยากรที่มีจำกัดของเซิร์ฟเวอร์โมเดลคือช่องสำหรับคำขอที่กำลังดำเนินการ การตรวจสอบที่แย่งชิงหรือรอช่องดังกล่าว ถือเป็นส่วนหนึ่งของภาระงานที่มันต้องประเมิน จงตรวจสอบอย่างประหยัด และเริ่มการทำงานใหม่เฉพาะเมื่อคุณพิสูจน์ได้ว่าเซิร์ฟเวอร์ค้างอยู่จริง
การตรวจสอบที่เข้ามาแทนที่
vLLM เผยแพร่ค่าตัวนับของมันเองที่ /metrics การตรวจสอบแบบใหม่จะอ่านค่าเหล่านั้นก่อน:
- คำขอที่กำลังทำงานและเอนจินมีความคืบหน้า: ปกติและกำลังใช้งาน ไม่มีการส่งคำขอทดสอบ
- คำขอที่กำลังทำงานแต่ไม่มีความคืบหน้า ระหว่างการอ่านสองครั้ง: ค้าง นี่คือกรณีที่ยังคงต้องเริ่มการทำงานใหม่
- ไม่มีคำขอทำงาน: ว่าง การตรวจสอบจะขอคำตอบสั้น ๆ เฉพาะในกรณีนี้ ซึ่งเอนจินที่ว่างจะตอบทันที
เวอร์ชันแรกนับจำนวน token ที่สร้างขึ้นเป็นความคืบหน้า มันผ่านการทดสอบ 8 ครั้ง และในการรันจริงครั้งแรก มันพบว่าเซิร์ฟเวอร์กำลังใช้งานและทำงานปกติ: มีคำขอทำงาน 2 รายการ และ token ใหม่ 107 ตัวระหว่างการอ่านสองครั้ง
สิ่งที่เราเปลี่ยนแปลงไปตั้งแต่ตอนนั้น
- นับจำนวนขั้นตอน ไม่ใช่จำนวนโทเคนผลลัพธ์ ขณะที่ vLLM กำลังอ่านพรอมป์ยาว ๆ จะยังไม่สร้างโทเคนผลลัพธ์ออกมาสักพัก แต่ยังดำเนินการเป็นขั้นตอนอยู่ การนับจำนวนขั้นตอน (นับจาก vllm:iteration_tokens_total) ช่วยป้องกันไม่ให้พรอมป์ยาว ๆ ดูเหมือนว่าเซิร์ฟเวอร์ค้าง
- รอสองครั้งก่อนจะตัดสินว่า "ค้าง" เพื่อไม่ให้การหยุดชะงักสั้น ๆ ถูกนับว่าเป็นความล้มเหลว
- จับการรีสตาร์ทระหว่างสองครั้งของการอ่านได้ โดยดูจากเวลาเริ่มกระบวนการในเมตริกชุดเดียวกัน จากนั้นการตรวจสอบจะขอคำตอบแทนที่จะเปรียบเทียบตัวนับจากสองกระบวนการที่แตกต่างกัน
- ตรวจสอบพร็อกซีผ่าน /models เท่านั้น เมื่ออยู่หลังพร็อกซีแบบ least-connection การอ่าน /metrics แต่ละครั้งอาจมาจากแบ็กเอนด์คนละตัวกัน ดังที่เราพบเมื่อ รันสำเนาโมเดลบนเครื่องสองเครื่อง ส่วนแบ็กเอนด์นั้นตรวจสอบโดยตรง
ความแตกต่างเห็นได้ชัด ขณะที่เราเขียนบันทึกนี้ เซิร์ฟเวอร์โมเดลทั้งสองเครื่องของเราต่างกำลังรัน 12 คำขอเท่ากัน ซึ่งเป็นจำนวนสูงสุด คำขอทดสอบจะต้องรอในคิว การตรวจสอบใหม่รายงานทั้งสองเครื่องว่าไม่ว่างและทำงานปกติ ที่ 126 และ 101 โทเคนต่อวินาที โดยไม่ต้องส่งคำขอใด ๆ
Factory Floor 1.0.2 มาพร้อมการตรวจสอบนี้ในไฟล์ models/llm-health.py พร้อมชุดทดสอบสำหรับเซิร์ฟเวอร์ที่ว่าง ไม่ว่าง ค้าง และรีสตาร์ท รวมถึงเซิร์ฟเวอร์ที่ไม่มีเมตริก พร็อกซี และแบ็กเอนด์ที่ตายแล้ว