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

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง
- ความล้มเหลวในระบบไอทีถือเป็นเรื่องปกติที่หลีกเลี่ยงไม่ได้
- การใช้ระบบฉันทามติช่วยป้องกันปัญหา Split-Brain
- การอัปเดตโค้ดต้องคำนึงถึงความเข้ากันได้ของฐานข้อมูลทั้งสองทาง
แนวคิดเรื่องระบบที่ทำงานตลอดเวลาหรือ "Never stops running" ในทางปฏิบัติจริงถือเป็นเรื่องที่เป็นไปได้ยาก เนื่องจากฮาร์ดแวร์ทุกชิ้นย่อมมีวันเสื่อมสภาพ หน่วยความจำในซอฟต์แวร์มีวันหมดลง และการปรับปรุงโค้ดใหม่อยู่เสมอก็เข้ามาแทนที่โค้ดเก่า สถาปัตยกรรมที่แข็งแกร่งจึงไม่ใช่ระบบที่ออกแบบมาเพื่อป้องกันความล้มเหลวไม่ให้เกิดขึ้นเลย แต่เป็นการออกแบบให้ความล้มเหลวกลายเป็นเหตุการณ์ปกติที่ระบบสามารถเอาตัวรอดได้โดยไม่ทำให้บริการหยุดชะงักหรือเกิดไฟฟ้าดับในภาพรวม
แนวคิดพื้นฐานที่หลายทีมมักเข้าใจผิดคือการรันระบบทุกอย่างเป็นสองชุด ซึ่งจำเป็นแต่ยังไม่เพียงพอ ทีมพัฒนาหลายทีมมักประสบปัญหาภาวะสมองแยก หรือ Split-Brain ที่โหนดทั้งสองต่างเชื่อมั่นว่าตนเองเป็นโหนดเดียวที่ยังมีชีวิตอยู่ และต่างเปิดรับการเขียนข้อมูลพร้อมกัน ส่งผลให้ข้อมูลมีความขัดแย้งกันและต้องมานั่งแก้ไขด้วยมือกันตอนตีสี่

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง
ภาวะ Split-Brain ถือเป็นฝันร้ายของวิศวกรระบบ เพราะทำให้ข้อมูลสูญเสียความน่าเชื่อถือโดยอัตโนมัติ การทำความเข้าใจชั้นฉันทามติจึงเป็นหัวใจสำคัญในการสร้างระบบกระจายศูนย์ (Distributed Systems) ที่มีความเสถียรสูง
สิ่งที่ระบบจำเป็นต้องมีคือชั้นฉันทามติหรือ consensus layer ทำหน้าที่กำหนดว่าใครคือผู้มีอำนาจสั่งการในขณะนั้นโดยอิงจากข้อเท็จจริงที่ระบบทั้งหมดเห็นพ้องต้องกัน ซึ่งโปรโตคอลในกลุ่ม Raft และ Paxos ถูกพัฒนาขึ้นมาเพื่อวัตถุประสงค์นี้โดยเฉพาะ โดยมีเครื่องมืออย่าง etcd หรือ Consul เป็นตัวช่วยรับประกันว่าในทุกช่วงเวลาจะมีโหนดอย่างน้อยหนึ่งโหนดทำหน้าที่เป็นผู้นำอย่างชัดเจน
นอกจากนี้ การจัดการกับปัญหาเมื่อบริการปลายทางตอบสนองไม่ทันก็เป็นสิ่งสำคัญ เครื่องมือมาตรฐานที่นิยมใช้คือ Circuit Breaker ซึ่งจะตัดการทำงานทันทีหากพบว่าบริการภายนอกล้มเหลวซ้ำๆ เพื่อไม่ให้เธรดทั้งหมดในกระบวนการต้องค้างรออย่างไร้จุดหมาย
ในฝั่งของกระบวนการทำงาน การอัปเดตระบบแบบ Rolling Deploys เป็นทางออกโดยการสร้างอินสแตนซ์ใหม่ขึ้นมาแทนที่ตัวเก่าทีละส่วน แทนที่จะปิดระบบทั้งหมดพร้อมกัน ความท้าทายที่ยากกว่าคือการใช้งานโค้ดเก่าและโค้ดใหม่บนชุดข้อมูลเดียวกันในช่วงรอยต่อของการอัปเดต
การเปลี่ยนแปลงโครงสร้างฐานข้อมูลหรือ Schema จึงต้องมีความเข้ากันได้ย้อนหลังทั้งสองทาง โดยแบ่งการปรับปรุงออกเป็นหลายขั้นตอน เช่น เพิ่มคอลัมน์ใหม่แบบรองรับค่าว่าง นำโค้ดที่เขียนข้อมูลลงทั้งสองคอลัมน์ขึ้นระบบ ทำการย้อนข้อมูล และค่อยนำโค้ดที่อ่านจากคอลัมน์ใหม่ออกมาใช้งาน ก่อนจะลบทิ้งในภายหลัง
การตรวจสอบสถานะสุขภาพของระบบหรือ Health Checks ควรสะท้อนสถานะที่แท้จริง มากกว่าการตอบกลับรหัส 200 เพียงเพราะกระบวนการยังทำงานอยู่ เนื่องจากปัญหาที่พบบ่อยคือกระบวนการยังรับการเชื่อมต่อได้ แต่อาจเกิดอาการติดขัดกับบริการอื่นหรือหน่วยความจำรั่วไหลจนใกล้ถึงจุดวิกฤต
ที่มา: Dev.to
พบข้อมูลผิดพลาดในบทความนี้? แจ้งปัญหาบทความนี้
ความคิดเห็น
แสดงความคิดเห็น