บล็อก

เราทำให้ deploy เหลือข้อผิดพลาด 502 เป็นศูนย์ได้อย่างไร

ทุกครั้งที่เรา deploy แบ็กเอนด์ของ Mythex จะมีคำขอไม่กี่รายการล้มเหลวด้วย 502 Bad Gateway ไม่มากนัก แต่ 502 ระหว่าง deploy หมายความว่าการคลิกของใครบางคนไม่ได้ผล หรือ build ที่เขาดูอยู่หยุดไปชั่วครู่ เราสืบจนพบสองปัญหาแยกกัน: watchdog ที่ซ่อมตัวเองซึ่งต่อสู้กับการ deploy และช่องว่างระหว่างเวลาที่เซิร์ฟเวอร์หยุดรับฟังกับเวลาที่ load balancer หยุดส่งทราฟฟิกไปให้ หลังการแก้ไข จำนวนติดต่อกันในสามการ deploy production ลดจาก 10 เป็น 6 และเป็น 0

การตั้งค่า

API และ orchestrator ของเรารันเป็น container บนกลุ่มเซิร์ฟเวอร์ขนาดเล็กหลัง Application Load Balancer (ALB) ของ AWS การ deploy อัปเดตเซิร์ฟเวอร์ทีละเครื่อง: มันระบาย container เก่า เริ่ม container ใหม่ แล้วไปเครื่องถัดไป watchdog บนแต่ละเซิร์ฟเวอร์ตรวจว่า container ทำงานอยู่ และรีสตาร์ตตัวที่ไม่ทำงาน มันมีไว้เพื่อให้โปรเซสที่ crash ตอนตีสามกลับมาทำงานได้โดยไม่มีใครต้องตื่นมา

ทั้งสองอย่างสมเหตุสมผลเมื่อแยกกันดู แต่เมื่อรวมกันแล้วไม่สมเหตุสมผล

ปัญหาที่ 1: watchdog แข่งกับการ deploy

watchdog ทำงานทุกนาทีและ "ซ่อม" เมื่อ health check ล้มเหลวหนึ่งครั้ง การ deploy จงใจระบายบริการนานถึง 150 วินาที ซึ่งระหว่างนั้น health check ควรจะล้มเหลว ดังนั้น watchdog จึงลงมือทุกครั้งที่มีการ deploy

ส่วนใหญ่มันแพ้การแข่งขันอย่างไม่เป็นอันตราย ครั้งหนึ่งมันชนะ: มันเขียนไฟล์ compose (คำอธิบายว่า container ใดควรรัน) ทับกลางการ deploy และทิ้งเซิร์ฟเวอร์ไว้โดยไม่มี container gateway เลย ขณะที่งาน deploy รายงานว่าสำเร็จ

การแก้ไข:

  • ล็อกเดียว ตอนนี้การ deploy ใช้ file lock เดียวกับสคริปต์ bootstrap ของเซิร์ฟเวอร์ ดังนั้น watchdog และการ deploy จะไม่รันพร้อมกันได้เลย
  • สี่ครั้ง ไม่ใช่หนึ่ง watchdog ต้องมี health check ที่ล้มเหลวติดต่อกันสี่ครั้งก่อนจะลงมือ บริการที่กำลังระบายจะไม่ดูเหมือนตายอีกต่อไป
  • นิยามเดียว ไฟล์ compose ตอนนี้มีแหล่งเดียว เผยแพร่ไปยังเซิร์ฟเวอร์ แทนที่จะเป็นสำเนาที่อาจเคลื่อนไปคนละทาง
  • ตรวจสอบ ไม่ใช่เชื่อ งาน deploy จะไม่ผ่านเพียงเพราะคำสั่งคืนค่าออกมา มันตรวจ API, orchestrator, gateway และ publish worker ของทุกเซิร์ฟเวอร์ก่อนจะสำเร็จได้

ปัญหาที่ 2: เซิร์ฟเวอร์ออกไปก่อนทราฟฟิก

ปัญหาที่สองเงียบกว่า เมื่อ deploy ระบายเซิร์ฟเวอร์ เซิร์ฟเวอร์จะเริ่มตอบ health endpoint ของมันด้วย 503 เพื่อให้ load balancer นำมันออกจากการหมุนเวียน ของเราทำอย่างนั้นเป็นเวลา 5 วินาที แล้วจึงปิดตัว

แต่ ALB ตรวจ health เป็นครั้งคราวเท่านั้น และต้องการการตรวจที่ล้มเหลวติดต่อกันหลายครั้งก่อนจะหยุดส่งเส้นทางไปยังเป้าหมาย รวมแล้วนานถึงราว 60 วินาที ดังนั้นประมาณ 55 วินาที load balancer ยังส่งคำขอจริงไปยังเซิร์ฟเวอร์ที่หยุดรับฟังไปแล้ว นั่นคือ 502 ของเรา

การแก้ไขคือทำให้สองเส้นเวลาตรงกัน:

  • target group ตอนนี้ตรวจทุก 5 วินาที และทำเครื่องหมาย target ว่าไม่พร้อมใช้งานหลังล้มเหลว 2 ครั้ง ซึ่งใช้เวลาราว 10 วินาทีในการรู้ตัว
  • การระบายยังให้บริการทราฟฟิกจริงต่ออีก 15 วินาที หลังจากเริ่มล้มเหลวการตรวจ health ดังนั้นจะมีการซ้อนทับเสมอ
  • การตั้งค่าเหล่านี้อยู่ในสคริปต์ที่จัดสรรโครงสร้างพื้นฐาน ไม่ใช่ในคอนโซลที่มีคนคลิกครั้งเดียว

ทำให้ตัวเลขยืนยันกันเอง

ค่า timeout แบบนี้ขึ้นอยู่กับกันและกัน การระบายต้องนานกว่าเวลาที่ balancer ใช้ในการรู้ตัว การระบายบวกการปิดตัวต้องเสร็จก่อนที่ container จะถูกฆ่าแบบบังคับ มันง่ายที่ใครสักคนจะเปลี่ยนตัวเลขหนึ่งตัวในหกเดือนต่อมาและนำบั๊กกลับมาโดยไม่รู้ตัว

ดังนั้นเราจึงเขียนความสัมพันธ์เหล่านั้นเป็น test: การระบายต้องยาวกว่าช่วงเวลาตรวจ health คูณด้วยจำนวนครั้งที่ล้มเหลวเพื่อตัดสิน เวลาที่จะกลับมาถูกมองว่าปกติต้องสั้น และการระบายทั้งหมดต้องพอดีกับ stop grace period ของ container เปลี่ยนตัวเลขหนึ่งตัวโดยไม่เปลี่ยนตัวอื่น แล้ว CI จะล้มเหลว เราทดสอบ mutation ตัว test เองด้วย โดยเปลี่ยนแต่ละตัวเลขเป็นค่าผิดและตรวจว่ามี test จับได้

การวัดการ deploy ทำผิดได้ง่าย

การวัดครั้งแรกของเราบอกว่า deploy ที่สะอาดเสียหายราว 3% มันไม่ได้เป็นอย่างนั้น เรากำลังนับทุกการตอบกลับที่ไม่ใช่ 200 และ 503 จาก health endpoint ระหว่างการระบายไม่ใช่ความล้มเหลว มันคือการระบายที่ทำหน้าที่ของมัน บอก balancer ว่าอย่าเลือกเซิร์ฟเวอร์นั้นในขณะที่มันยังให้บริการคำขอจริงต่อ

สิ่งที่ผู้ใช้รู้สึกคือ 502: คำขอไปถึงสิ่งที่ไม่มีอะไร การนับเฉพาะตรงนั้นให้ภาพที่ถูกต้อง: 10, แล้ว 6, แล้ว 0 ในสาม deploy production

สิ่งที่เราเรียนรู้

  • การซ่อมตัวเองต้องรู้เกี่ยวกับการหยุดทำงานที่วางแผนไว้ watchdog ที่แยกการ deploy ออกจากการ crash ไม่ได้ จะต่อสู้กับการ deploy ในที่สุด
  • การระบายคือการจับมือ เซิร์ฟเวอร์ต้องให้บริการต่อจนกว่า load balancer จะหยุดส่งทราฟฟิกอย่างพิสูจน์ได้ และการกำหนดเวลานั้นถูกตั้งบน balancer ไม่ใช่บนเซิร์ฟเวอร์
  • เข้ารหัสข้อกำหนดเป็น test ตัวเลขเชิงปฏิบัติการเคลื่อนไปเรื่อยๆ test ที่เกี่ยวโยงตัวเลขเข้าด้วยกันไม่เคลื่อน
  • ตัดสินใจว่าคุณกำลังวัดอะไรก่อนวัด "ข้อผิดพลาด" เป็นตัววัดที่ผิด "คำขอที่ไปถึงสิ่งที่ไม่มีอะไร" คือตัววัดที่ถูกต้อง

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

Mythex · Pricing · สร้างอะไรก็ได้ด้วย AI · เทมเพลตเว็บไซต์และแอป · เปรียบเทียบ Mythex · อภิธานศัพท์การสร้างแอปด้วย AI · เครื่องมือฟรีสำหรับสร้างแอปด้วย AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)