สามารถออกแบบบริการด้วยความเชื่อถือได้และความยืนหยุ่นในตัวทุกรูปแบบ แต่เพื่อให้บริการมีความน่าเชื่อถือในการปฏิบัติจริง บริการจะต้องรับมือกับความล้มเหลวที่คาดการณ์ได้ด้วยเมื่อเกิดขึ้น ที่ Amazon เราสร้างบริการที่สามารถปรับขนาดแนวนอนและมีความซ้ำซ้อน เนื่องจากฮาร์ดแวร์ได้รับการออกแบบมาให้ทำงานล้มเหลวอยู่เสมอ ฮาร์ดแวร์ทุกชนิดจะมีขีดอายุการใช้งานที่คาดหวังไว้ และซอฟต์แวร์ทุกชิ้นเสี่ยงที่จะหยุดทำงานเมื่อถึงจุดๆ หนึ่ง ดูเหมือนว่าสภาพของเซิร์ฟเวอร์จะมีลักษณะอย่างใดอย่างหนึ่ง: ยังทำงานได้ หรือทำงานไม่ได้เลยและต้องทิ้งไป น่าเสียดายที่นี่ไม่ใช่กรณีดังกล่าว เราพบว่าแทนที่จะปิดการทำงาน เซิร์ฟเวอร์ที่ล่มอาจก่อให้เกิดความเสียหายที่คาดเดาไม่ได้ให้กับระบบ และในบางครั้งอาจเป็นความเสียหายที่ไม่ได้สัดส่วน การตรวจสอบสภาพจะตรวจจับและตอบโต้ปัญหาเหล่านี้โดยอัตโนมัติ

บทความนี้จะอธิบายถึงวิธีที่เราใช้การตรวจสอบสภาพเพื่อตรวจจับและรับมือกับความล้มเหลวของเซิร์ฟเวอร์เดียว สิ่งต่างๆ ที่เกิดขึ้นเมื่อไม่ได้ใช้การตรวจสอบสภาพ และวิธีที่ระบบที่ตอบสนองกับความล้มเหลวของการตรวจสภาพมากเกินไปสามารถเปลี่ยนปัญหาเล็กๆ ให้กลายเป็นการใช้งานไม่ได้โดยสมบูรณ์ เรายังมอบข้อมูลเชิงลึกจากประสบการณ์ของเราที่ Amazon เกี่ยวกับการรักษาสมดุลการแลกเปลี่ยนระหว่างการปรับใช้การตรวจสภาพชนิดต่างๆ

ความล้มเหลวเล็กๆ ที่มีผลกระทบขนาดใหญ่

ตอนที่ผมยังเป็นนักพัฒนาซอฟต์แวร์หน้าใหม่ที่ Amazon ผมทำงานเกี่ยวกับฟลีตการแสดงผลภาพเว็บไซต์เบื้องหลัง Amazon.com ในขณะที่ดำเนินการเปลี่ยนแปลงเพื่อเพิ่มการรายงานข้อมูลระบบ และรับการมองเห็นว่าซอฟต์แวร์ทำงานได้ดีเพียงใดขณะทำงาน ผมดันไปเขียนบั๊กขึ้นมา บั๊กทรกเกอร์ขึ้นมาไม่บ่อยนัก แต่เมื่อทริกเกอร์ขึ้นมา ก็จะทำให้เว็บเซิร์ฟเวอร์แสดงหน้าว่างที่ผิดพลาดเปล่าทุกครั้งที่มีคำขอ การรีสตาร์ทเว็บเซิร์ฟเวอร์เป็นวิธีเดียวที่จะแก้ปัญหานี้ได้ เราตรวจจับบั๊กและเรียกคืนการเปลี่ยนแปลงในทันที เพิ่มการทดสอบอีกมากมาย และปรับปรุงกระบวนการเพื่อจับสภาพเช่นนี้ในอนาคต แต่ในขณะที่บั๊กกำลังสร้างข้น เซิร์ฟเวอร์จำนวนหนึ่งในฟลีตขนาดใหญ่กลับอยู่ในสภาพเสียหาย
 
สิ่งหนึ่งที่ทำให้บั๊กนั้นตรวจจับได้ยากก็คือเซิร์ฟเวอร์ไม่รู้ว่าบั๊กนั้นเป็นภัย นอกจากนี้ เซิร์ฟเวอร์ยังสูญเสียความสามารถในการรายงานสภาพของมันให้ระบบการตรวจสอบ ดังนั้นเซิร์ฟเวอร์จึงไม่ถูกหยุดใช้งานในทันที และไม่ได้ทริกเกอร์การแจ้งเตือนตามปกติ เซิร์ฟเวอร์ทำงานอย่างรวดเร็วและเริ่มสร้างหน้าว่างที่ผิดพลาดได้เร็วกว่า “เซิร์ฟเวอร์ที่ปกติดี” ที่สร้างหน้าเว็บเพจที่ปกติอย่างมาก ซึ่งทำให้ปัญหาแย่ลงไปอีก เทคโนโลยีการกระจายภาระงานที่เราใช้ในขณะนั้นสนับสนุนเซิร์ฟเวอร์ที่ทำงานเร็วมากกว่าเซิร์ฟเวอร์ที่ทำงานช้า ดังนั้นจึงส่งผลโดยตรงกับจำนวนที่ไม่สมส่วนของการรับส่งข้อมูลไปยังเซิร์ฟเวอร์ที่ผิดปกติ ซึ่งเพิ่มผลกระทบให้มากขึ้นไปอีก

การแจ้งเตือนอื่นๆ ทริกเกอร์ขึ้น เนื่องจากการตรวจสอบจะรวมถึงการตรวจวัดระดับข้อผิดพลาดและเวลาแฝงจากจุดต่างๆ ในระบบ ในชณะที่ระบบตรวจสอบเหล่านี้และกระบวนการดำเนินการที่สามารถทำหน้าที่เป็นตัวหยุดเพื่อจำกัดปัญหา การตรวจสอบสภาพที่เหมาะสมสามารถลดผลกระทบจากข้อผิดพลาดนี้ทั้งหมดได้อย่างมาก และจัดการกับข้อผิดพลาดได้อย่างรวดเร็ว

การแลกเปลี่ยนการตรวจสอบสภาพ

การตรวจสอบเป็นถามว่าบริการสำหรับเซิร์ฟเวอร์เฉพาะนั้นสามารถทำงานได้อย่างสมบูรณ์หรือไม่ โหลดบาลานเซอร์จะถามคำถามนี้กับแต่ละเซิร์ฟเวอร์เป็นช่วงๆ เพื่อระบุว่าเซิร์ฟเวอร์ใดปลอดภัยเพื่อส่งการรับส่งข้อมูลไปถึง บริการที่ตรวจสอบข้อความจากคิวอาจถามตัวมันเองว่าปลอดภัยหรือไม่ก่อนที่จะตัดสินใจตรวจสอบงานอื่นๆ จากคิว ตัวแทนการตรวจสอบที่ทำงานบนแต่ละเซิร์ฟเวอร์หรือฟลีตการตรวจสอบภายนอกอาจถามเซิร์ฟเวอร์ว่าเซิร์ฟเวอร์ปลอดภัยหรือไม่ เพื่อให้ตัวแทนสามารถใช้การแจ้งเตือนหรือการรับมือได้โดยอัตโนมัติกับเซิร์ฟเวอร์ที่ล้มเหลว

อย่างที่เราเห็นในตัวอย่างบั๊กบนเว็บไซต์ เมื่อเซิร์ฟเวอร์ที่ไม่ปลอดภัยทำงานต่อไปเรื่อยๆ มันก็จสามารถลดความพร้อมใช้งานของบริการทั้งหมดอย่างไม่สมส่วน ด้วยจำนวนฟลีตเพียงรายการเดียวต่อสิบเซิร์ฟเวอร์ เซิร์ฟเวอร์ที่แย่เพียงรายการเดียวจะหมายความว่าความพร้อมใช้งานของฟลีตนั้นเหลือแค่ 90% หรือน้อยกว่านั้น อัลกอริทึมการกระจายภาระงาน เช่น “คำขอขั้นต่ำ” จะป้อนงานให้กับเซิร์ฟเวอร์ที่เร็วกว่ามากขึ้น ซึ่งทำให้ปัญหาแย่ลงไปอีก เมื่อเซิร์ฟเวอร์ล้มเหลว มักจะเริ่มจากไม่สามารถรับคำขออย่างรวดเร็ว ซึ่งจะสร้าง “หลุมดำ” ในฟลีตบริการโดยทำให้มีคำขอเพิ่มมากกว่าเซิร์ฟเวอร์ที่ปกติ ในบางกรณี เราเพิ่มการป้องกันเพิ่มเติมเพื่อป้องกันหลุมดำโดยลดความเร็วคำขอที่ล้มเหลว เพื่อให้พอดีกับระยะเวลาแฝงของคำขอที่สำเร็จ อย่างไรก็ตาม ยังมีสถานการณ์อื่นๆ เช่น ปัญหาที่เกิดกับตัวตรวจสอบคิว ซึ่งแก้ไขได้ยากกว่า ตัวอย่างเช่น ถ้าตัวตรวจสอบคิวกำลังตรวจสอบข้อความได้เร็วพอๆ กับที่สามารถรับข้อความได้ เซิร์ฟเวอร์ที่ล้มเหลวจะเป็นหลุมดำอีกครั้ง ด้วยสภาพแวดล้อมที่หลากหลายสำหรับการเผยแพร่งาน วิธีคิดของเราเกี่ยวกับการป้องกันเซิร์ฟเวอร์ที่ล้มเหลวบางส่วนจะแตกต่างกันไปตามแต่ละระบบ

เราพบว่าเซิร์ฟเวอร์ที่ล้มเหลวโดยไม่ขึ้นต่อกันด้วยสาเหตุหลายอย่าง ซึ่งรวมถึงดิสก์ที่เปลี่ยนมาเขียนไม่ได้ และทำให้คำขอล้มเหลวลงในทันที นาฬิกาที่คลาดเคลื่อนในทันทีและทำให้การเรียกใช้การอ้างอิงไม่สามารถตรวจสอบได้ เซิร์ฟเวอร์ที่ไม่สามารถดึงเอกสารเข้ารหัสที่อัปเดต และทำให้การถอดรหัสลับและการเข้ารหัสลับล้มเหลว การดำเนินการสนับสนุนที่สำคัญที่หยุดทำงานเพราะบั๊กของตนเอง การรั่วไหลของหน่วยความจำ และภาวะติดตายที่ทำให้การดำเนินการหยุดชะงัก

เซิร์ฟเวอร์ยังล้มเหลวด้วยเหตุผลที่สัมพันธ์กันหลายประการ ซึ่งทำให้เซิร์ฟเวอร์หลายรายการหรือทั้งหมดในฟลีตล้มเหลวไปด้วย เหตุผลที่สัมพันธ์กันนั้นรวมถึงการใช้งานไม่ได้ของแหล่งอ้างอิงที่แชร์ และปัญหาด้านเครือข่ายที่มีขนาดใหญ่ การตรอจสอบสภาพที่ดีที่สุดจะทดสอบเซิร์ฟเวอร์และสภาพของแอปพลิเคชันในทุกๆ ด้าน บางครั้งจะตรวจสอบแม้กระทั่งว่าการดำเนินการสนับสนุนที่ไม่สำคัญนั้นทำงานอยู่หรือไม่ อย่างไรก็ตาม ปัญหาจะเกิดขึ้นเมื่อการตรวจสอบสภาพสำหรับสาเหตุที่ไม่สำคัญล้มเหลว และเมื่อความล้มเหลวนั้นสัมพันธ์ไปทั่วทั้งเซิร์ฟเวอร์ ถ้าการทำงานอัตโนมัตินำเซิร์ฟเวอร์ออกจากบริการขณะที่เซิร์ฟเวอร์ยังสามารถทำงานได้อยู่ การทำงานอัตโนมัติจะส่งผลเสียมากกว่าผลดี

อย่างไรก็ตาม ความยากลำบากในการตรวจสอบสภาพคือ ความขัดแย้งระหว่างประโยชน์จากการตรวจสภาพอย่างละเอียดถี่ถ้วนและลดความล้มเหลวจากเซิร์ฟเวอร์เดียวอย่างรวดเร็ว และในอีกแง่หนึ่ง ก็คือความไม่ปลอดภัยที่เกิดจากข้อผิดพลาดที่เป็นผลลัพธ์ที่ผิดทั่วทั้งฟลีต ดังนั้น หนึ่งในความท้าทายในการสร้างการตรวจสอบสภาพที่ดีก็คือ การป้องกันการเกิดผลลัพธ์ที่ผิดอย่างรอบคอบ โดยทั่วไป นี่จะหมายความว่าการทำงานอัตโนมัติที่อยู่รอบการตรวจสภาพควรหยุดนำการรับส่งข้อมูลไปยังเซิร์ฟเวอร์ที่ไม่ดีเพียงเซิร์ฟเวอร์เดียว แต่ยังอนุญาตให้มีการรับส่งข้อมูลถ้าทั้งฟลีตปรากฏว่ากำลังประสบปัญหา

วิธีตรวจสอบสภาพ

มีหลายสิ่งที่อาจเกิดขึ้นได้บนเซิร์ฟเวอร์ และมีหลายจุดในระบบของเราที่เราตรวจวัดสภาพของเซิร์ฟเวอร์ การตรวจสภาพบางอย่างสามารถรายงานได้แน่นอนว่าเซิร์ฟเวอร์เฉพาะนั้นเสียหายโดยไม่เชื่อมโยงกับจุดอื่น ในขณะที่การตรวจสอบแบบอื่นนั้นจะคลุมเครือกว่าและรายงานผลลัพธ์ที่ผิดในกรณีที่เป็นความล้มเหลวแบบสัมพันธ์ การตรวจสภาพบางรางการก็ยากที่จะนำมาปรับใช้ ในขณะที่การตรวจสภาพแบบอื่นจะปรับใช้มาตั้งแต่ตอนตั้งค่ากับบริการ เช่น Elastic Compute Cloud (Amazon EC2) และ Elastic Load Balancing การตรวจสอบสภาพแต่ละชนิดมีจุดแข็งของตัวเอง

การตรวจสอบความสมบูรณ์

การตรวจสอบความสมบูรณ์จะทดสอบการเชื่อมต่อพื้นฐานกับบริการและการดำเนินการของเซิร์ฟเวอร์ที่แสดง โดยมักจะทำงานโดยโหลดบาลานเซอร์หรือตัวแทนการตรวจสอบภายนอก และไม่รู้ถึงรายละเอียดการทำงานของแอปพลิเคชัน การตรวจสอบความสมบูรณ์มีแนวโน้มว่าจะถูกรวมอยู่ในบริการ และไม่ต้องให้ผู้เขียนแอปพลิเคชันปรับใช้ใดๆ ตัวอย่างของการตรวจสอบความสมบูรณ์ที่เราใช้ที่ Amazon มีดังต่อไปนี้:

• การทดสอบที่ยืนยันว่าเซิร์ฟเวอร์ยังทำงานตามพอร์ตที่กำหนดไว้และรับการเชื่อมต่อ TCP ใหม่
• การทดสอบที่ดำเนินการคำขอ HTTP พื้นฐาน และตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์ตอบสนองกับโค้ดสถานะ 200
• การตรวจสอบสถานะสำหรับ Amazon EC2 ที่ทดสอบสิ่งพื้นฐานต่างๆ ที่จำเป็นสำหรับการทำงานของทุกระบบ เช่น ความสามารถในการเข้าถึงเครือข่าย

การตรวจสอบสภาพภายใน

การตรวจสอบสภาพภายในจะเป็นมากกว่าการตรวจสอบความสมบูรณ์เพื่อตรวจสอบว่าแอปพลิเคชันนั้นมีแนวโน้มที่จะสามารถใช้งานได้ การตรวจสอบสภาพเหล่านี้จะตรวจสอบทรัพยากรที่ไม่ได้แชร์กับเพียร์ของเซิร์ฟเวอร์ ดังนั้น การตรวจสอบมีแนวโน้มที่จะไม่ล้มเหลวพร้อมกันบนเซิร์ฟเวอร์ทั้งหลายในฟลีต การตรวจสอบสภาพเหล่านี้จะทดสอบสิ่งต่อไปนี้:

• การขาดความสามารถในการเขียนหรืออ่านจากดิสก์ ซึ่งอาจลวงให้เชื่อได้ว่าบริการที่ไม่มีสถานะนั้นไม่จำเป็นต้องมีดิสก์ที่เขียนได้ อย่างไรก็ตาม ที่ Amazon บริการของเรามีแนวโน้มจะใช้ดิสก์ของบริการเพื่อการตรวจสอบ การบันทึก และการเผยแพร่ข้อมูลการวัดระดับอะซิงโครนัส
• การหยุดทำงานหรือการทำลายกระบวนการที่สำคัญ บางบริการจะนำคำขอไปโดยใช้พร็อกซีบนเซิร์ฟเวอร์ (คล้ายกับ NGINX) และดำเนินการลอจิกทางธุรกิจในกระบวนการในเซิร์ฟเวอร์อื่น การตรวจสอบความสมบูรณ์อาจทดสอบว่ากระบวนการพร็อกซีทำงานอยู่หรือไม่เท่านั้น การตรวจสอบภายในอาจตรวจสอบตั้งแต่พร็อกซีไปจนถึงแอปพลิเคชันเพื่อตรวจสอบว่าทั้งสองอย่างนั้นทำงานและตอบรับคำขอได้อย่างถูกต้อง น่าสนใจตรงที่ ในตัวอย่างเว็บไซต์ตั้งแต่ตอนเริ่มบทความ การตรวจสอบสภาพที่มีอยู่นั้นละเอียดมากพอที่จะให้มั่นใจว่ากระบวนการแสดงผลภาพนั้นกำลังทำงานและตอบสนอง แต่ไม่ละเอียดมากพอที่จะตรวจสอบได้ว่ามีการตอบสนองอย่างถูกต้อง
• การขาดกระบวนการสนับสนุน โฮสต์ที่ขาด Daemons การตรวจสอบอาจทำให้ผู้ปฏิบัติงาน “ทำงานโดยไร้การมองเห็น” และไม่รู้ถึงสภาพของบริการของตน กระบวนการสนับสนุนอื่นๆ จะผลักให้มีการใช้การวัดระกับและการเรียกเก็บเงิน หรือรับการอัปเดตที่ได้รับการยอมรับ เซิร์ฟเวอร์ที่มีกระบวนการสนับสนุนที่เสียหายจะทำให้การทำงานตกอยู่ในความเสี่ยงที่ตรวจสอบได้อย่างและคลุมเครือ

การตรวจสอบสภาพการขึ้นต่อกัน

การตรวจสอบสภาพการขึ้นต่อกันจะเป็นการตรวจสอบความสามารถของแอปพลิเคชันในการโต้ตอบกับระบบใกล้เคียงอย่างถี่ถ้วน การตรวจสอบเหล่านี้จะจับปัญหาภายในเซิร์ฟเวอร์ เช่น การรับรองที่หมดอายุ ซึ่งจะทำให้เซิร์ฟเวอร์ไม่สามารถโต้ตอบกับการขึ้นต่อกัน แต่การตรวจสอบยังสามารถให้ผลลัพธ์ที่ผิดได้เมื่อมีปัญหากับการขึ้นต่อกันเอง และเนื่องด้วยผลลัพธ์ที่ผิดเหล่านั้น เราจะต้องระมัดระวังเกี่ยวกับวิธีที่เราโต้ตอบกับความล้มเหลวในการตรวจสอบสภาพการขึ้นต่อกัน การตรวจสอบสภาพการขึ้นต่อกันอาจทดสอบสิ่งต่อไปนี้:

• การกำหนดค่าที่ไม่ดีหรือข้อมูลเมตาเก่า ถ้ากระบวนการมองการอัปเดตสำหรับข้อมูลเมตาหรือการกำหนดค่าแบบอะซิงโครนัส แต่กลไกการอัปเดตกลับเสียหายบเซิร์ฟเวอร์ เซิร์ฟเวอร์สามารถออกจากซิงค์กับเพียร์อย่างมีนัยสำคัญ และทำงานผิดปกติอย่างที่ไม่ได้รับการตรวจสอบและไม่สามารถคาดเดาได้ อย่างไรก็ตาม เมื่อเซิร์ฟเวอร์ไม่พบการอัปเดตเป็นระยะเวลาหนึ่ง เซิร์ฟเวอร์จะไม่รู้ว่ากลไกการอัปเดตนั้นเสียหายหรือระบบการอัปเดตส่วนกลางหยุดเผยแพร่การอัปเดตสู่เซิร์ฟเวอร์ทั้งหมดหรือไม่
• การขาดความสามารถในการสื่อสารกับเซิร์ฟเวอร์ของพียร์หรือการขึ้นต่อกัน เป็นที่รู้กันว่าพฤติกรรมของเครือข่ายที่ผิดปกติจะส่งผลต่อความสามารถของชุดย่อยของเซิฟร์เวอร์ในฟลีตที่จะสนทนากับการขึ้นต่อกันโดยไม่ส่งผลต่อความสามารถในการรับส่งข้อมูลที่ส่งไปยังเซิร์ฟเวอร์ ปัญหาด้านซอฟต์แวร์เช่นการติดตายหรือบั๊กในกลุ่มการเชื่อมต่อจะสามารถขัดขวางการติดต่อสื่อสารของเครือข่ายได้
• บั๊กซอฟต์แวร์ที่ผิดปกติอื่นๆ ที่จะเป็นต้องมีการแจ้งเตือนการดำเนินการ การติดตาย การรั่วไหล หรือหน่วยความจำ หรือบั๊กที่เป็นจุดบกพร่องของสถานะสามารถทำให้เกิดเซิร์ฟเวอร์ที่มีข้อผิดพลาด 

Anomaly Detection

Anomaly Detection จะดูทั่วทั้งเซิร์ฟเวอร์ในฟลีตเพื่อระบุว่ามีเซิร์ฟเวอร์ใดที่มีพฤติกรรมผิดปกติเมื่อเปรียบเทียบกับเพียร์หรือไม่ โดยการรวบรวมข้อมูลการตรวจสอบในแต่ละเซิร์ฟเวอร์ เราสามารถเปรียบเทียบอัตราข้อผิดพลาด ข้อมูลเวลาแฝง หรือคุณลักษณะอื่นได้อย่างต่อเนื่องเพื่อค้นหาเซิร์ฟเวอร์ที่ผิดปกติและเอาออกจากบริการได้โดยอัตโนมัติ Anomaly Detection สามารถค้นหาความแตกต่างในฟลีตที่เซิร์ฟวเวอร์ไม่สามารถตรวจจับเกี่ยวกับตนเองได้ เช่นดังต่อไปนี้:

• นาฬิกาคลาดเคลื่อน โดยเฉพาะอย่างยิ่งเมื่อมีโหลดในปริมาณที่มาก นาฬิกาจึงมักจะคลาดเคลื่อนอย่างกระทันหันและอย่างมาก มาตรการรักษาความปลอดภัย เช่นมาตรการที่ถูกใช้สำหรับประเมินการขอที่มีการลงชื่อไปยัง AWS นั้นจำเป็นต้องมีเวลาบนนาฬิกาของไคลเอ็นต์ช้าเร็วไม่เกินห้านาทีจากเวลาจริง ถ้าไม่เช่นนั้น คำขออาจส่งไปไม่ถึงบริการของ AWS
• โค้ดเก่า ถ้าเซิร์ฟเวอร์ขาดการเชื่อมต่อจากเครือข่ายหรือปิดเครื่องอยู่เป็นเวลานาน และเมื่อกลับมาออนไลน์อีกครั้ง เซิร์ฟเวอร์อาจะเรียกใช้โค้ดที่หมดอายุที่เป็นอันตรายที่ไม่สามารถใช้ร่วมกับฟลีตที่เหลือได้
• โหมดความล้มเหลวที่ไม่คาดคิด บางครั้งเซิร์ฟเวอร์จะล้มเหลวในรูปแบบที่จะส่งกลับข้อผิดพลาดโดยระบุว่าเป็นข้อผิดพลาดของไคลเอ็นต์ และไม่ใช่ของเซิร์ฟเวอร์เอง (HTTP 400 แทนที่จะเป็น 500) เซิร์ฟเวอร์อาจทำงานช้าลงแทนที่จะล้มเหลว หรืออาจตอบสนองกับเพียร์เร็วขึ้น ซึ่งเป็นสัญญาณว่าเซิร์ฟเวอร์ได้ส่งกลับการตอบกลับที่ผิดไปยังผู้เรียกใช้ Anomaly Detection เป็น CatchAll ที่น่าทึ่งสำหรับโหมดความล้มเหลวที่ไม่คาดคิด

ต่อไปนี้คือข้อเท็จจริงบางประการเกี่ยวกับ Anomaly Detection ที่ทำงานในทางปฏิบัติ:

• เซิร์ฟเวอร์ควรจะทำงานคล้ายๆ กัน ในกรณีที่เรากำหนดเส้นทางชนิดการรับส่งข้อมูลที่แตกต่างกับเซิร์ฟเวอร์ชนิดต่างๆ อย่างชัดเจน เซิร์ฟเวอร์อาจไม่ทำงานเหมือนพอที่จะตรวจจับจุดค่าผิดปกติ อย่างไรก็ตาม ในกรณีที่เราใช้โหลดบาลานเซอร์เพื่อกำหนดเส้นทางการรับส่งข้อมูลไปยังเซิร์ฟเวอร์ มีแนวโน้มว่าเซิร์ฟเวอร์จะตอบสนองในลักษณะที่คล้ายคลึงกัน
• ฟลีตไม่ควรจะมีรูปแบบที่คล้ายคลึงจนเกินไป ในฟลีตที่ประกอบด้วยประเภทอินสเตนซ์ต่างๆ บางอินสแตนซ์อาจช้ากว่าอินสแตนซ์อื่น ซึ่งอาจทริกเกอร์การตรวจจับเซิร์ฟเวอร์ที่ไม่ดีเชิงรับได้อย่างผิดพลาด เมื่อต้องการแก้ไขปัญหาสถานการณ์นี้ชั่วคราว เราเปรียบเทียบตัววัดตามประเภทของอินสแตนซ์
• ข้อผิดพลาดหรือความแตกต่างในพฤติกรรมจะต้องถูกรายงาน เนื่องจากเราพึ่งพาเซิร์ฟเวอร์ในการรายงานข้อผิดพลาด จะเกิดอะไรขึ้นเมื่อระบบตรวจสอบเสียหายด้วยเช่นกัน โชคดีที่ไคลเอ็นต์ของบริการเป็นจุดที่ดีในการเพิ่มเครื่องมือ โหลดบาลานเซอร์อย่าง Application Load Balancer จะเผยแพร่บันทึกการเข้าถึงที่แสดงว่าเซิร์ฟเวอร์แบ็คเอนด์ใดที่ถูกติดต่อในทุกการขอ เวลาการตอบกลับ และแสดงว่าคำขอนั้นสำเร็จหรือล้มเหลว 

การตอบสนองต่อความล้มเหลวในการตรวจสอบสภาพอย่างปลอดภัย

เมื่อเซิร์ฟเวอร์ระบุว่าล้มเหลว มีการดำเนินการสองแบบที่เซิร์ฟเวอร์จะดำเนินการ ในกรณีที่ร้ายแรงที่สุด เซิร์ฟเวอร์จะสามารถตัดสินใจจะภายใจได้ว่าไม่ควรทำงานต่อและหยุดการทำงานของตนเองโดยทำให้การตรวจสภาพโหลดบาลานเซอร์ล้มเหลว หรือหยุดตรวจสอบคิว อีกทางหนึ่งที่เซิร์ฟเวอร์อาจตอบสนองก็คือ แจ้งไปยังหน่วยควบคุมศูนย์กลางว่าเซิร์ฟเวอร์มีปัญหาและให้ระบบส่วนกลางตัดสินใจว่าจะจัดการกับปัญหาอย่างไร ระบบส่วนกลางสามารถแก้ไขปัญหาได้อย่างปลอดภัยโดยไม่ต้องให้การทำงานอัตโนมัติหยุดการทำงานของฟลีตทั้งหมด

มีหลายวิธีที่จะปรับใช้งานและตอบสนองกับการตรวจสอบสภาพ ส่วนนี้จะอธิบายถึงรูปแบบสองสามแบบที่เราใช้ที่ Amazon

การเปิดต่อไปแม้ขัดข้อง

โหลดบาลานเซอร์บางตัวสามารถทำหน้าที่เป็นหน่วยควบคุมส่วนกลางอัจฉริยะ เมื่อเซิร์ฟเวอร์เฉพาะไม่สามารถตรวจสอบสภาพได้ โหลดบาลานเซอร์จะหยุดส่งการรับส่งข้อมูลถึงเซิร์ฟเวอร์ แต่เมื่อเซิร์ฟเวอร์ทั้งหมดไม่สามารถตรวจสอบสภาพได้ในเวลาเดียวกัน โหลดบาลานเซอร์จะไม่สามารถเปิดได้ ซึ่งทำให้การรับส่งข้อมูลไปสู่เซิร์ฟเวอร์ทั้งหมด เราสามารถใช้โหลดบาลานเซอร์เพื่อสนับสนุนการปรับใช้งานการตรวจสอบสภาพการขึ้นต่อกันที่ปลอดภัยได้ และอาจรวมถึงการตรวจสอบสภาพที่สืบค้นฐานข้อมูลและตรวจสอบให้แน่ใจว่ากระบวนการสนับสนุนที่ไม่สำคัญนั้นยังคงทำงานอยู่

ตัวอย่างเช่น Network Load Balancer ของ AWS ไม่สามารถเปิดได้ถ้าไม่มีบริการรายงานว่าปกติดี และจะยุติปริมาณการใช้งานใน Availability Zone ที่สภาพไม่สมบูรณ์ ถ้าเซิร์ฟเวอร์ทั้งหมดใน Availability Zone รายงานว่าไม่สมบูรณ์ (สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการใช้ Network Load Balancer เพื่อตรวจสอบสภาพ ดูที่เอกสารประกอบ Elastic Load Balancing) Application Load Balancer ของเรายังสนับสนุนการเปิดต่อไปแม้ขัดข้อง เช่นเดียวกับ Amazon Route 53 (สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดค่าการตรวจสอบสภาพด้วย Route 53 ดูที่เอกสารประกอบ Route 53)

เมื่อเราพึ่งพาพฤติกรรมที่เปิดต่อไปแม้ขัดข้อง เราได้ตรวจสอบให้มั่นใจว่าได้ตรวจสอบโหมดความล้มเหลวของการตรวจสอบสภาพการขึ้นต่อกัน ตัวอย่างเช่น พิจารณาบริการในจุดที่บริการได้เชื่อมต่อกับพื้นที่เก็บข้อมูลที่แชร์ ถ้าพื้นที่เก็บข้อมูลทำงานช้าหรือตอบกลับด้วยอัตราข้อผิดพลาดที่ต่ำ เซิร์ฟเวอร์อาจทำให้การตรวจสอบสภาพการขึ้นต่อกันล้มเหลวลงได้บางครั้ง สภาพนี้จะทำให้เซิร์ฟเวอร์ทำงานได้และไม่ได้สลับกัน แต่จะไม่ทริกเกอร์เกณฑ์เริ่มต้นที่เปิดต่อไปแม้ขัดข้อง การหาคำตอบด้วยเหตุผลและทดสอบข้อผิดพลาดบางส่วนของการขึ้นต่อกันด้วยการตรวจสอบสภาพเหล่านี้เป็นสิ่งที่ที่สำคัญเพื่อหลีกเลี่ยงสถานการณ์ที่ข้อผิดพลาดอาจทำให้การตรวจสอบสภาพอย่างละเอียดก่อให้เกืดปัญหาที่แย่ลง

ในขณะที่การเปิดต่อไปแม้ขัดข้องเป็นพฤติกรรมที่มีประโยชน์ ที่ Amazon เรามีแนวโน้มจะสงสัยสิ่งต่างๆ ที่เราไม่สามารถหาเหตุผลได้อย่างกระจ่างหรือทดสอบสถานการณ์ทั้งหมด เรายังไม่มีการพิสูจน์ทั่วไปที่ระบุว่าการเปิดต่อไปแม้ขัดข้องจะทริกเกอร์ตามที่เราหวังไว้สำหรับโหลดที่มากเกินไปทุกประเภท การล้มเหลวบางส่วน หรือการล้มเหลวที่ก้ำกึ่งในระบบหรือในการขึ้นต่อกันของระบบ เนื่องจากข้อจำกัดเช่นนี้ ทีมของ Amazon มีแนวโน้มว่าจะจำกัดการตรวจสอบสภาพของโหลดบาลานเซอร์ที่ทำงานอย่างรวดเร็วไว้เฉพาะการตรวจสอบสภาพภายใน และพึ่งพาระบบส่วนกลางเพื่อตอบสนองกับการตรวจสอบสภาพการขึ้นต่อกันที่ลึกซึ้งขึ้นอย่างรอบคอบ โดยนี่ไม่ใช่การบอกว่าเราจะไม่ใช้พฤติกรรมที่เปิดต่อไปแม้ขัดข้อง หรือพิสูจน์ว่าพฤติกรรมนั้นใช้งานได้ในบางกรณี แต่เมื่อลอจิกสามารถใช้งานได้บนเซิร์ฟเวอร์จำนวนมากได้อย่างรวดเร็ว เราจึงจะมัดระวังกับลอจิกนั้นอย่างมาก

การตรวจสอบสภาพโดยไม่มีเซอร์กิตเบรกเกอร์

การอนุญาตให้เซิร์ฟเวอร์ตอบสนองกับปัญหาของพวกมันเองอาจะเป็นหนทางที่เร็วที่สุดและง่ายดายที่สุดในการกู้คืน อย่างไรก็ตาม มันก็ยังเป็นหนทางที่เสี่ยงที่สุดหากเซิร์ฟเวอร์เข้าใจสภาพของตนผิดไป หรือไม่เห็นภาพรวมของสิ่งที่เกิดขึ้นทั่วทั้งฟลีต เมื่อเซิร์ฟเวอร์ทั้งหมดทั่วทั้งฟลีตตัดสินใจผิดพลาดแบบเดิมพร้อมกัน อาจทำให้เกิดข้อผิดพลาดที่ซ้อนทับตลอดถึงบริการข้างเคียง ความเสี่ยงนี้ทำให้เราเห็นถึงการแลกเปลี่ยน ถ้ามีช่องว่างในการตรวจสอบสภาพและการตรวจสอบ เซิร์ฟเวอร์อาจลดความพร้อมใช้งานของบริการจนกว่าจะตรวจจับปัญหาได้ อย่างไรก็ตาม สถานการณ์นี้จะหลีกเลี่ยงไม่ให้ทั้งบริการหยุดทำงานเนื่องจากพฤติกรรมการตรวจสอบสภาพทั่วทั้งฟลีต

ต่อไปนี้เป็นแนวปฏิบัติที่เราปฏิบัติตามเพื่อปรับใช้การตรวจสอบสภาพเมื่อเราไม่มีเซอร์กิตเบรกเกอร์ภายใน

• กำหนดค่าผู้ผลิตงาน (โหลดบาลานเซอร์ เธรดการตรวจสอบคิว) เพื่อทำการตรวจสอบสภาพภายในและความสมบูรณ์ เซิร์ฟเวอร์จะถูกหยุดทำงานโดยอัตโนมัติโดยโหลดบาลานเซอร์เท่านั้นถ้าเซิร์ฟเวอร์มีปัญหาที่เกิดในเซิร์ฟเวอร์อย่างแน่นอน เช่น ดิสก์ที่ไม่ดี
• กำหนดค่าระบบการตรวจสอบอื่นๆ เพื่อทำการตรวจสอบการขึ้นต่อกันและ Anomaly Detection ระบบเหล่านี้สามารถพยายามยกเลิกอินสแตนซ์โดยอัตโนมัติ หรือแจ้งเตือนหรือเข้าไปเกี่ยวข้องกับผู้ปฏิบัติงาน

เมื่อเราสร้างระบบเพื่อตอบสนองโดยอัตโนมัติกับความผิดพลาดในการตรวจสอบสภาพการขึ้นต่อกัน เราต้องสร้างเกณฑ์เริ่มต้นในปริมาณที่ถูกต้องเพื่อป้องกันระบบอัตโนมัติไม่ให้ดำเนินการที่รุนแรงโดยไม่คาดคิด ทีมที่ Amazon ที่ดำเนินการเซิร์ฟเวอร์ที่มีสถานะอย่าง Amazon DynamoDB, Amazon S3 และ Amazon Relational Database Service (Amazon RDS) มีข้อกำหนดด้านความคงทนที่สำคัญเกี่ยวกับการแทนที่เซิร์ฟเวอร์ พวกเขายังได้สร้างอัตราการระมัดระวังและลูปคำติชมการควบคุมเพื่อให้การทำงานอัตโนมัติหยุดทำงานและติดต่อกับมนุษย์เมื่อเกณฑ์เริ่มต้นถูกขัดขวาง เมื่อเราสร้างการทำงานอัตโนมัติเช่นนั้น เราจะต้องแน่ใจว่าเราสังเกตว่าเซิร์ฟเวอร์จะไม่สามารถตรวจสอบสภาพการขึ้นต่อกันเมื่อไร สำหรับตัววัดบางรายการ เราพึ่งพาเซิร์ฟเวอร์ให้รายงานสถานะเฉพาะด้วยตัวเองให้กับระบบตรวจสอบส่วนกลาง เมื่อต้องการชดเชยให้กับกรณีที่เซิร์ฟเวอร์เสียหายอย่างหนักจนไม่สามารถรายงานสภาพตนเองได้ เราจะเข้าถึงเซิร์ฟเวอร์ด้วยตนเองเพื่อตรวจสอบสภาพ 

จัดลำดับความสำคัญสภาพของคุณ

โดยเฉพาะอย่างยิ่งในสภาพโอเวอร์โหลด โดยสำคัญเป็นอย่างมากสำหรับเซิร์ฟเวอร์ที่จะให้ความสำคัญกับการตรวจสอบสภาพมากกว่างานประจำ ในสถานการณ์เช่นนี้ การล้มเหลวหรือตอบกลับที่ไปยังการตรวจสอบสภาพที่ล่าช้าอาจทำให้สถานการณ์หยุดทำงานที่แย่อยู่แล้วแย่ลงไปอีก 

เมื่อเซิร์ฟเวอร์ไม่สามารถตรวจสอบสภาพโหลดบาลานเซอร์ได้ เซิร์ฟเวอร์จะขอให้โหลดบาลานเซอร์หยุดการทำงานของบริการโดยทันที และอาจใช้เวลานาน เมื่อเซิร์ฟเวอร์เดี่ยวล้มเหลว ซึ่งไม่เป็นปัญหาแต่อย่างใด แต่สำหรับการรับส่งข้อมูลที่เพิ่มสูงขึ้นสู่บริการ สิ่งสุดท้ายที่เราต้องการคือการลดขนาดบริการ การให้เซิร์ฟเวอร์หยุดทำงานระหว่างโอเวอร์โหลดอาจทำให้สถานการณ์แย่ลง การบังคับให้เซิร์ฟเวอร์ที่เหลืออยู่รับการรับส่งข้อมูลมากขึ้นอาจทะให้เซิร์ฟเวอร์เกิดการโอเวอร์โหลด และทำให้ไม่สามารถตรวจสอบสภาพ และอาจะลดขนาดฟลีตมากขึ้นอีก

ปัญหาไม่ได้อยู่ที่เซิร์ฟเวอร์โอเวอร์โหลดส่งคืนข้อผิดพลาดเมื่อโอเวอร์โหลด ปัญหาอยู่ที่เซิร์ฟเวอร์ไม่ได้ตอบสนองต่อการขอปิงโหลดบาลานเซอร์ได้ทันเวลา อย่างไรก็ตาม การตรวจสภาพโหลดบาลานเซอร์จะถูกกำหนดค่าด้วยการหมดเวลา เหมือนกับการเรียกบริการทางระยะไกลอื่นๆ บริการที่หยุดทำงานจะตอบกลับได้ช้าเนื่องด้วยเหตุผลหลายประการ ซึ่งรวมถึงความขัดแย้งระหว่าง CPU ที่สูง รอบตัวรวบรวมขยะที่ยาวนาน หรืออาจเป็นเพราะกรณีที่เธรดผู้ปฏิบัติงานหมด บริการจะต้องถูกกำหนดค่าเพื่อเผื่อทรัพยากรไว้สำหรับตอบกลับการตรวจสอบสภาพได้ทันท่วงที แทนที่จะรับคำขอเพิ่มเติมมากเกินไป

โชคดีที่ยังมีแนวปฏิบัติที่ดีที่สุดด้านการกำหนดค่าที่ตรงไปตรงมาบางประการที่เราปฏิบัติตามเพื่อช่วยป้องกันสถานการณ์ที่แย่ลงเช่นนี้ เครื่องมืออย่าง iptables และโหลดบาลานเซอร์บางตัวสนับสนุนแนวคิด “การเชื่อมต่อสูงสุด” ในกรณีนี้ OS (หรือโหลดบาลานเซอร์) จะจำกัดจำนวนการเชื่อมต่อสู่เซิร์ฟเวอร์เพื่อให้การดำเนินการของเซิร์ฟเวอร์ไม่ถูกโถมด้วยการขอพร้อมๆ กันที่อาจทำให้เซิร์ฟเวอร์ทำงานช้าลง

เมื่อบริการถูกนำด้วยพร็อกซีหรือโหลดบาลานเซอร์ที่สนับสนุนการเชื่อมต่อสูงสุด การทำให้จำนวนเธรดผู้ทำงานบนเซิร์ฟเวอร์ HTTP ตรงกับการเชื่อมต่อสูงสุดในพร็อกซีดูเหมือนจะเป็นวิธีที่สมเหตุสมผล อย่างไรก็ตาม การกำหนดค่านี้จะตั้งค่าเซิร์ฟเวอร์สำหรับปัญหาที่แย่ลงในระหว่างที่หยุดทำงาน การตรวจสอบสภาพพร็อกซีจำเป็นต้องมีการเชื่อมต่อเช่นกัน ดังนั้นการทำให้กลุ่มผู้ปฏิบัติงานของเซิร์ฟเวอร์มีขนาดใหญ่พอที่จะรองรับการขอตรวจสอบสภาพเพิ่มเติมนั้นจึงเป็นเรื่องสำคัญ ผู้ปฏิบัติงานที่ไม่ได้ใช้งานนั้นมีราคาถูก เราจึงกำหนดค่าผู้ปฏิบัติงานพิเศษมากกว่า: ไม่ว่าจะเป็นผู้ปฏิบัติงานพิเศษจำนวนไม่กี่คนเพื่อทวีคูณจำนวนการเชื่อมต่อสูงสุดของพร็อกซีที่ถูกกำหนดค่า

กลยุทธ์หนึ่งที่เราใช้เพื่อให้ความสำคัญกับการตรวจสอบสภาพก็คือการให้เซิร์ฟเวอร์ปรับใช้การบังคับใช้คำขอพร้อมกันในจำนวนสูงสุดของเซิร์ฟเวอร์ ในกรณีนี้ การตรวจสอบสภาพโหลดบาลานเซอร์จะถูกอนุญาตเสมอ แต่การขอปกติจะถูกปฏิเสธถ้าเซิร์ฟเวอร์กำลังสร้างเกณฑ์เริ่มต้นอยู่ การปรับใช้งานไปทั่วทั้ง Amazon ตั้งแต่อุปกรณ์สัญญาณธรรมดาใน Java ไปจนถึงการวิเคราะห์ที่ซับซ้อนของแนวโน้มในประสิทธิภาพการใช้งาน CPU

อีกวิธีหนึ่งที่จะช่วยให้มั่นใจว่าบริการจะตอบกลับได้ทันกับการขอปิงการตรวจสอบสภาพคือการใช้ลอจิกสำหรับการตรวจสอบสภาพการขึ้นต่อกันในเธรดเบื้องหลังและอัปเดตค่าสถานะ isHealthy ที่ลอจิกปิงตรวจสอบ ในกรณีนี้ เซิร์ฟเวอร์จะตอบกลับการตรวจสอบสภาพทันที และการตรวจสอบสภาพการขึ้นต่อกันจะสร้างโหลดที่สามารถคาดเดาได้บนระบบภายนอกถ้ามีการโต้ตอบ เมื่อทีมทำเช่นนี้ ทีมจะจับตาเพื่อตรวจจับข้อผิดพลาดของเธรดการตรวจสอบสภาพเป็นพิเศษ ถ้ามีเธรดเบื้องหลังดังกล่าวอยู่ เซิร์ฟเวอร์จะไม่ตรวจจับความล้มเหลวของเซิร์ฟเวอร์ในอนาคต (หรือการกู้คืน!)

การรรักษาสมดุลการตรวจสอบสภาพการขึ้นต่อกันด้วยขอบเขตผลกระทบ

การตรวจสอบสภาพการขึ้นต่อกันนั้นน่าดึงดูดเพราะการตรวจสอบจะทำหน้าที่เป็นการทดสอบสภาพของเซิร์ฟเวอร์ที่ถี่ถ้วน ข้อเสียคือการตรวจสอบอาจเป็นอันตรายได้เนื่องจากการขึ้นต่อกันอาจทำให้เกิดความล้มเหลวทั่วทั้งระบบพร้อมกัน

เราสามารถสร้างข้อมูลเชิงลึกเกี่ยวกับการจัดการการขึ้นต่อกันของการตรวจสอบสภาพโดยดูที่สถาปัตยกรรมที่มุ่งเน้นการให้บริการของ Amazon แต่ละบริการของ Amazon ถูกออกแบบมาเพื่อทำหน้าที่ไม่กี่อย่าง ไม่มีบริการขนาดใหญ่ที่ทำทุกอย่าง มีเหตุผลหลายประการที่เรามักจะสร้างบริการเช่นนี้ขึ้นมา ซึ่งรวมถึงการสร้างนวัตกรรมที่รวดเร็วขึ้นด้วยทีมขนาดเล็ก และลดขอบเขตผลกระทบถ้ามีปัญหาขึ้นในบริการใดบริการหนึ่ง การออกแบบสถาปัตยกรรมสามารถนำไปใช้กับการตรวจสอบสภาพด้วย

เมื่อบริการหนึ่งเรียกใช้บริการหนึ่ง จะมีการใช้การขึ้นต่อกันบนบริการนั้น ถ้าบริการเรียกใช้การขึ้นต่อกันแค่บางครั้ง เราอาจพิจารณาให้การขึ้นต่อกันเป็น “การขึ้นต่อกันที่ยืดหยุ่นได้” เนนื่องจากบริการยังสามารถทำงานได้บางประเภทแม้จะไม่สามารถติดต่อกับการขึ้นต่อกันได้ หากไม่มีการป้องกันแบบเปิดต่อไปแม้ขัดข้อง การปรับใช้การตรวจสอบสภาพที่ทดสอบการขึ้นต่อกันจะเปลี่ยนการขึ้นต่อกันนั้นเป็น “การขึ้นต่อกันที่ไม่ยืดหยุ่น” ถ้าการขึ้นต่อกันหยุดทำงาน บริการก็จะหยุดทำงานด้วย โดยก่อให้เกิดความล้มเหลวพร้อมๆ กันพร้อมขยายขอบเขตผลกระทบให้กว้างขึ้น

แม้ว่าเราจะแยกการทำงานเป็นบริการต่างๆ แต่บริการแต่ละประเภทมีแนวโน้มจะทำงานให้กับ API หลายตัว บางครั้ง API บนบริการก็มีการขึ้นต่อกันเป็นของตนเอง ถ้า API หนึ่งตัวได้รับผลกระทบ เรามักจะให้บริการทำงานต่อใน API อื่น ตัวอย่างเช่น บริการทั้งเป็นทั้ง Control Plane (เช่น CRUD API ที่ถูกเรียกใช้เป็นบางครั้งบนทรัพยากรที่มีอายุขัยนาน) และ Data Plane (API ที่มีความสำคัญมากทางธุรกิจที่มีอัตราความเร็วสูง) เราต้องการให้ API ของ Data Plane ยังคงดำเนินการต่อถ้า API ของ Control Plane มีปัญหาในการติดต่อกับการขึ้นต่อกัน

เช่นเดียวกัน แม้ API เดี่ยวจะมีพฤติกรรมที่แตกต่างออกไปตามแต่ละการป้อนเข้าหรือสถานะของข้อมูล รุปแบบทั่วไปคือ API การอ่านที่สืบค้นฐานข้อมูลแต่จะจับการตอบกลับภายในบางครั้ง ถ้าฐานข้อมูลหลุดทำงาน บริการจะยังคงให้บริการการอ่านที่แคชไว้จนกระทั่งฐานข้อมูลกลับมาออนไลน์ ความล้มเหลวในการตรวจสอบสภาพเฉพาะเมื่อเส้นทางโค้ดตัวใดตัวหนึ่งที่ไม่ปกตินั้นจะเพิ่มขอบเขตผลกระทบของปัญหาที่ติดต่อกับการขึ้นต่อกัน

การสนทนาเกี่ยวกับการขึ้นต่อกันกับการตรวจสอบสภาพทำให่เกิดคำถามที่น่าสนใจเกี่ยวกับการแลกเปลี่ยนระหว่างไมโครเซอร์วิสและบริการที่มีขนาดค่อนข้างใหญ่ ซึ่งไม่ค่อยมีกฎที่ชัดเจนกำหนดว่ามีหน่วยที่ติดตั้งใช้จริงหรือตำแหน่งข้อมูลจำนวนเท่าใดในการแยกบริการ แต่คำถามที่ว่า “การขึ้นต่อกันใดที่ต้องตรวจสอบสภาพ” และ “แล้วความล้มเหลวเพิ่มขอบเขตผลกระทบหรือไม่” นั้นเป็นเลนส์ขยายที่น่าสนใจเพื่อใช้กำหนดว่าจะต้องเป็นไมโครหรือแมโครเท่าให้เพื่อสร้างบริการ 

สิ่งผิดปกติที่แท้จริงกับการตรวจสอบสภาพ

ทั้งหมดนี้ฟังดูสมเหตุสมผลในทางทฤษฎี แต่จะเกิดอะไรขึ้นกับระบบในทางปฏิบัติเมื่อระบบไม่ได้รับการตรวจสภาพที่ถูกต้อง เราดูที่รูปแบบในเรื่องราวจากลูกค้าของ AWS และจากทั่วทั้ง Amazon เพื่อช่วยให้เห็นภาพได้ใหญ่ขึ้น เรายังดูที่ปัจจัยชดเชย ซึ่งคล้ายกับ “การใช้วิธีหลายวิธีเพื่อให้ได้ผลลัพธ์ที่ต้องการ” ที่ทีมได้ปรับใช้เพื่อป้องกันไม่ให้จุดอ่อนในการตรวจสอบสภาพก่อให้เกิดปัญหาในวงกว้าง

การปรับใช้

รูปแบบหนึ่งของปัญหาการตรวจสอบสภาพนั้นคือการปรับใช้ ระบบการปรับใช้เช่น AWS CodeDeploy จะผลักให้โค้ดใหม่เป็นชุดย่อยหนึ่งของฟลีตในช่วงเวลาดังกล่าว โดยจะรอให้คลื่นการปรับใช้เสร็จสิ้นก่อนเคลื่อนย้ายไปรายการถัดไป กระบวนการนี้จะพึ่งพาเซิร์ฟเวอร์ที่รายงานกลับมายังระบบการปรับใช้เมื่อเปิดใช้งานและทำงานด้วยโค้ดใหม่ ถ้าเซิร์ฟเวอร์ไม่รายงานกลับมา ระบบการปรับใช้จะมองว่ามีบางอย่างผิดปกติกับโค้ดใหม่และจะเรียกคืนการปรับใช้

การเขียนคำสั่งปรับใช้สตาร์ทอัพของบริการที่พื้นฐานที่สุดก็คือการเจาะลงในกระบวนการของเซิร์ฟเวอร์และตอบกลับว่า “เสร็จสิ้นการปรับใช้” ให้ระบบการปรับใช้ทันที อย่างไรก็ตาม กรณีนี้อันตรายเนื่องจากมีหลายสิ่งที่อาจผิดปกติได้เนื่องจากโค้ดใหม่: โค้ดใหม่อาจหยุดทำงานทันทีที่เปิดตัว ทำงานช้าและไม่สามารถเริ่มเชื่อฟังซ็อกเก็ตเซิร์ฟเวอร์ ไม่สามารถโหลดการกำหนดค่าที่จำเป็นสำหรับการดำเนินการคำขอให้สมบูรณ์ หรือพบกับบั๊ก เมื่อระบบการปรับใช้ไม่ได้ถูกกำหนดค่าให้ทดสอบการตรวจสอบสภาพการขึ้นต่อกัน โดยไม่รู้ว่าระบบกำลังใช้การปรับใช้ที่ไม่ดี โดยเกิดขึ้นพร้อมกับการทำลายเซิร์ฟเวอร์ไปเรื่อยๆ

ยังดีที่ในแนวปฏิบัติของทีม Amazon ได้ปรับใช้ระบบที่มีปัญหาน้อยลงเพื่อป้องกันเหตุการณ์เช่นนี้ไม่ให้ทำลายฟลีตทั้งหมดก่อน การลดปัญหาดังกล่าวมีหน้าที่กำหนดค่าการแจ้งเตือนที่ทริกเกอร์ทุกครั้งที่ขนาดของฟลีตโดยรวมนั้นเล็กเกินไปหรือเรียกใช้โหลดมากเกินไป หรือเมื่อมีเวลาแฝงหรืออัตราข้อผิดพลาดสูง ถ้าการแจ้งเตือนเหล่านี้ทริกเกอร์ ระบบการปรับใช้จะหยุดการปรับใช้และดึงกลับ

การลดปัญหาอีกประเภทหนึ่งคือการใช้การปรับใช้แบบเป็นระยะ แทนที่จะปรับใช้กับทั้งฟลีตในการปรับใช้เดียว บริการสามารถถูกกำหนดค่าเพื่อปรับใช้ชุดย่อย ซึ่งอาจเป็น Availability Zone ก่อนที่จะหยุดแล้วเรียกใช้ชุดทดสอบการผสานกับโซน การปฏิบัติตามการปรับใช้ต่อ Availability Zone นั้นง่ายดายเพราะบริการได้รับการออกแบบมาให้สามารถทำงานได้ต่อไปถ้ามีปัญหากับ Availability Zone เดี่ยว

และแน่นอนว่าก่อนการปรับใช้ผลิตภัณฑ์ ทีม Amazon จะผลักดันการเปลี่ยนแปลงเหล่านั้นผ่านสภาพแวดล้อมการทดสอบและเรียกใช้การทดสอบการผสานอัตโนมัติที่จะตรวจจับการล้มเหลวประเภทนี้ อย่างไรก็ตาม อาจมีความแตกต่างบางๆ ที่ไม่สามารถหลีกเลี่ยงได้ระหว่างผลิตภัณฑ์และสภาพแวดล้อม ดังนั้น การรวมความปลอดภัยในการปรับใช้ไว้หลายชั้นเพื่อจับปัญหาทุกชนิดก่อนที่จะส่งผลกระทบต่อผลิตภัณฑ์จึงเป็นเรื่องสำคัญ ในขณะที่การตรวจสอบสภาพนั้นสำคัญต่อการป้องกันบริการจากการปรับใช้ที่ไม่ดี เราก็ไม่ได้หยุดยั้งเพียงเท่านั้น เราคิดถึงแนวทางปฏิบัติ “การใช้วิธีหลายวิธีเพื่อให้ได้ผลลัพธ์ที่ต้องการ” ที่จะทำหน้าที่เป็นตัวหยุดเพื่อป้องกันฟลีตจากการปรับใช้ที่ไม่ดีและข้อผิดพลาดอื่นๆ

โปรเซสเซอร์แบบอะซิงโครนัส

การล้มเหลวอีกรูปแบบหนึ่งนั้นเกี่ยวกับการประมวลผลข้อความแบบอะซิงโครนัส เช่น บริการที่ทำงานโดยตรวจสอบคิว SQS หรือสตรีม Amazon Kinesis จะไม่มีการตรวจสอบสภาพการดำเนินงานโดยอัตโนมัติเพื่อลบเซิร์ฟเวอร์ออกจากบริการ ซึ่งไม่เหมือนในระบบที่รับการขอจากโหลดบาลานเซอร์

เมื่อบริการไม่มีการตรวจสอบสภาพที่ละเอียดเพียงพอ เซิร์ฟเวอร์ผู้ปฏิบัติงานคิวแต่ละรายการอาจเกิดการล้มเหลวได้ เช่น ดิสก์เต็มหรือมีตัวบอกไฟล์ไม่พอ ปัญหานี้จะไม่หยุดให้เซิร์ฟเวอร์ดึงงานออกจากคิว แต่จะหยุดเซิร์ฟเวอร์ให้ไม่สามารถประมวลข้อความได้สำเร็จ ปัญหานี้จะส่งผลให้การประมวลข้อความเป็นไปอย่างล่าช้า ซึ่งเซิร์ฟเวอร์ที่ไม่ดีจะดึงงานออกจากคิวอย่างรวดเร็วและไม่สามารถรับมือได้

ในสถานการณ์เช่นนี้ มักจะมีปัจจัยชดเชยมาช่วยจำกัดผลกระทบ ตัวอย่างเช่น ถ้าเซิร์ฟเวอร์ไม่สามารถประมวลผลข้อความที่ดึงมาจาก SQS ได้ SQS จะส่งข้อความดังกล่าวใหม่อีกครั้งไปยังอีกเซิร์ฟเวอร์หนึ่งหลังจากที่หมดเวลาแสดงผลข้อความที่กำหนดค่า เวลาแฝงตั้งแต่ต้นถึงหลายทางจะเพิ่มขึ้น แต่ข้อความจะไม่ถูกละทิ้ง ปัจจัยชดเชยอีกประการหนึ่งคือการแจ้งเตือนที่หยุดลงเมื่อมีข้อผิดพลาดในการประมวลข้อความมากเกินไป ซึ่งเป็นการแจ้งเตือนให้ผู้ปฏิบัติงานตรวจสอบ

ดิสก์เต็ม

การล้มเหลวอีกระดับหนึ่งที่เราเห็นคือดิสก์บนโฟลเดอร์เต็ม ทำให้การประมวลผลและการบันทึกนั้นล้มเหลว การล้มเหลวนี้อาจนำไปสู่ช่องว่างในการแสดงผลการตรวจสอบ เนื่องจากเซิร์ฟเวอร์อาจไม่สามารถรายงานการผิดพลาดนี้ให้กับระบบการตรวจสอบได้

ระบบช่วยลดปัญหาต่างๆ จะทำให้เซิร์ฟเวอร์ไม่ต้อง “ทำงานโดยไร้การมองเห็น” และลดผลกระทบได้อย่างรวดเร็ว ระบบที่นำด้วยพร็อกซีเช่น Application Load Balancer หรือ API Gateway จะมีอัตราข้อผิดพลาดและตัววัดเวลาแฝงที่เกิดจากพร็อกซี ในกรณีนี้ การแจ้งเตือนจะแจ้งแม้เซิร์ฟเวอร์จะไม่ได้รายงาน สำหรับระบบตามคิว บริการอย่าง Amazon Simple Queue Service (Amazon SQS) จะรายงานตัววัดที่ระบุว่าการดำเนินการจะถูกทำให้ล่าช้าสำหรับบางข้อความ

สิ่งที่โซลูชันเหล่านี้มีเหมือนกันก็คือ มีการตรวจสอบหลายชั้น เซิร์ฟเวอร์จะรายงานข้อผิดพลาดเอง และระบบภายนอกก็จะทำเช่นเดียวกัน แนวปฏิบัติเดียวกันนี้มีความสำคัญในการตรวจสอบสภาพ ระบบภายนอกสามารถทดสอบสภาพของระบบที่ระบุไว้ได้แม่นยำมากกว่าที่ทดสอบตนเอง นั่นคือเหตุผลว่าทำไมเมื่อมี AWS Auto Scaling ทีมจะกำหนดค่าโหลดบาลานเซอร์เพื่อตรวจสอบสภาพปิงภายนอก

ทีมยังเขียนการตรวจสอบสภาพแบบกำหนดเองเพื่อถามแต่ละเซิร์ฟเวอร์เป็นระยะๆ ว่าปกติดีหรือไม่ และรายงานให้กับ AWS Auto Scaling เมื่อเซิร์ฟเวอร์ผิดปกติ การปรับใช้ระบทั่วไปแบบหนึ่งประกอบด้วยฟังก์ชัน Lambda ที่จะเรีกยใช้ทุกๆ หนึ่งนาที โดยทดสอบสภาพของทุกเซิร์ฟเวอร์ การตรวจสอบสภาพเหล่านี้สามารถช่วยรักษาสถานะระหว่างการเรียกใช้แต่ละครั้งในบางสิ่งอย่าง DynamoDB เพื่อให้การตรวจสอบทำเครื่องหมายว่ามีเซิร์ฟเวอร์ที่ทำงานผิดปกติมาเกินไปในครั้งเดียว

ซอมบี้

ปัญหาอีกรูปแบบหนึ่งนั่นก็คือเซิร์ฟเวอร์ซอมบี้ เซิร์ฟเวอร์อาจขาดการเชื่อมต่อจากเครือข่ายเป็นระยะเวลาหนึ่งแต่ยังคงทำงานอยู่ หรือปิดเครื่องเป็นระยะเวลาหนึ่งแล้วรีบูตในภายหลัง

เมื่อเซิร์ฟเวอร์ซอมบี้กลับมามีชีวิตอีกครั้ง เซิร์ฟเวอร์อาจตัดขาดการซิงค์กับฟลีตที่เหลือโดยสิ้นเชิง ซึ่งอาจก่อให้เกิดปัญหาร้ายแรงได้ ตัวอย่างเช่น ถ้าเซิร์ฟเวอร์ซอมบี้ใช้งานซอฟต์แวร์เวอร์ชันที่เก่าและใช้ร่วมกันไม่ได้ อาจทำให้เกิดความล้มเหลวเมื่อเซิร์ฟเวอร์พยายามติดต่อกับฐานข้อมูลด้วยสคีมาที่แตกต่างออกไป หรือใช้การกำหนดค่าที่ไม่ถูกต้อง

เมื่อต้องการจัดการกับซอมบี้ ระบบมักจะตอบกลับการตรวจสอบสภาพด้วยซอฟต์แวร์เวอร์ชันล่าสุดที่ใช้งานอยู่ จากนั้นตัวแทนการตรวจสอบส่วนกลางจะเปรียบเทียบการตอบกลับทั่วทั้งฟลีตเมื่อค้นหาสิ่งที่เรียกใช้เวอร์ชันที่เก่าโดยไม่คาดคิด และป้องกันไม่ให้เซิร์ฟเวอร์เหล่านี้กลับมาทำงานได้อีก

สรุป

เซิร์ฟเวอร์และซอฟต์แวร์ที่ทำงานอยู่บนเซิร์ฟเวอร์อาจล้มเหลวด้วยเหตุผลประหลาดๆ และฮาร์ดแวร์มักจะเสียหายทางกายภาพเสมอ ในฐานะนักพัฒนาซอฟต์แวร์ เรามักจะเขียนบั๊กเช่นอย่างที่ผมอธิบายไว้ด้านบน ซึ่งจะทำให้ซอฟต์แวร์อยู่ในสภาพเสียหาย การตรวจสอบหลายชั้น ไม่ว่าจะเป็นการตรวจสอบความสมบูรณ์ที่ใช้พื้นที่น้อยหรือการตรวจสอบเชิงรับของตัววัดต่อหนึ่งเซิร์ฟเวอร์ ทั้งหมดจะทำหน้าที่จับโหมดล้มเหลวที่ไม่คาดคิดทุกประเภท

เมื่อความล้มเหลวเหล่านี้เกิดขึ้น การตรวจจับความล้มหลวและหยุดการทำงานของเซิร์ฟเวอร์ที่ได้รับผลกระทบจึงเป็นเรื่องสำคัญ อย่างไรก็ตาม เมื่อเป็นการทำงานอัตโนมัติในฟลีต เราเพิ่มการจำกัดอัตรา เกณฑ์เริ่มต้น และเซอร์กิตเบรกเกอร์ที่ปิดการทำงานอัตโนมัติ และให้มนุษย์เข้ามามีส่วนร่วมในสถานการณ์ที่ไม่แน่นอนหรือสุดขั้ว การเปิดต่อไปแม้ขัดข้องและตัวดำเนินการแบบศูนย์กลางเป็นกลยุทธ์สำหรับการรับประโยชน์จากการตรวจสอบสภาพอย่างละเอียดด้วยความปลอดภัยของการทำงานอัตโนมัติแบบจำกัดอัตรา

แล็บฝึกปฏิบัติจริง

ลองใช้หลักการที่คุณได้เรียนรู้ที่นี่ด้วยแล็บฝึกปฏิบัติจริง


เกี่ยวกับผู้เขียน

David Yanacek เป็นวิศวกรหลักอาวุโสที่ทำงานเกี่ยวกับ AWS Lambda David เป็นนักพัฒนาซอฟต์แวร์ที่ Amazon ตั้งแต่ปี 2006 โดยก่อนหน้านี้ทำงานเกี่ยวกับ Amazon DynamoDB และ AWS IoT รวมถึงเฟรมเวิร์กบริการเว็บภายในและระบบปฏิบัติการฟลีตอัตโนมัติ กิจกรรมการทำงานอย่างหนึ่งที่ David โปรดปรานคือการวิเคราะห์บันทึกและตรวจสอบตัวชี้วัดการดำเนินงานอย่างใกล้ชิดเพื่อหาวิธีที่จะทำให้ระบบทำงานได้ราบรื่นยิ่งๆ ขึ้นไป

การหมดเวลา การลองใหม่ และการถอยกลับที่มีความผันแปร