วิธีการใช้งานสถาปัตยกรรมเว็บที่ทนทานต่อข้อผิดพลาดในแพลตฟอร์ม Mail.ru Cloud Solutions

วิธีการใช้งานสถาปัตยกรรมเว็บที่ทนทานต่อข้อผิดพลาดในแพลตฟอร์ม Mail.ru Cloud Solutions

สวัสดีฮับ! ฉันชื่อ Artem Karamyshev หัวหน้าทีมบริหารระบบ โซลูชันคลาวด์ Mail.Ru (MCS)- เรามีการเปิดตัวผลิตภัณฑ์ใหม่มากมายในปีที่ผ่านมา เราต้องการให้แน่ใจว่าบริการ API สามารถปรับขนาดได้ง่าย ทนทานต่อข้อผิดพลาด และพร้อมสำหรับการเติบโตอย่างรวดเร็วของปริมาณผู้ใช้ แพลตฟอร์มของเราใช้งานบน OpenStack และฉันต้องการแจ้งให้คุณทราบว่าปัญหาความทนทานต่อข้อผิดพลาดของส่วนประกอบใดบ้างที่เราต้องแก้ไขเพื่อให้ได้ระบบที่ทนทานต่อข้อผิดพลาด ฉันคิดว่านี่จะน่าสนใจสำหรับผู้ที่พัฒนาผลิตภัณฑ์บน OpenStack ด้วย

ความทนทานต่อข้อผิดพลาดโดยรวมของแพลตฟอร์มประกอบด้วยความยืดหยุ่นของส่วนประกอบต่างๆ ดังนั้นเราจะค่อยๆ ผ่านทุกระดับที่เราระบุความเสี่ยงและปิดมัน

เวอร์ชันวิดีโอของเรื่องราวนี้ แหล่งที่มาหลักคือรายงานในการประชุม Uptime วันที่ 4 ซึ่งจัดโดย มันซัมมาคุณสามารถดูได้ ในช่อง YouTube ของชุมชน Uptime.

ความยืดหยุ่นของสถาปัตยกรรมทางกายภาพ

ขณะนี้ส่วนสาธารณะของระบบคลาวด์ MCS ตั้งอยู่ในศูนย์ข้อมูลระดับ Tier III สองแห่ง โดยระหว่างศูนย์เหล่านั้นจะมีไฟเบอร์สีเข้มของตัวเอง ซึ่งสงวนไว้ในระดับกายภาพตามเส้นทางที่ต่างกัน โดยมีปริมาณงานอยู่ที่ 200 Gbit/s ระดับ III มอบระดับความทนทานต่อข้อผิดพลาดที่จำเป็นสำหรับโครงสร้างพื้นฐานทางกายภาพ

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

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

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

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

วิธีการใช้งานสถาปัตยกรรมเว็บที่ทนทานต่อข้อผิดพลาดในแพลตฟอร์ม Mail.ru Cloud Solutions
ความยืดหยุ่นของโครงสร้างพื้นฐานทางกายภาพ

สิ่งที่เราใช้สำหรับความทนทานต่อข้อผิดพลาดระดับแอปพลิเคชัน

บริการของเราสร้างขึ้นจากส่วนประกอบโอเพ่นซอร์สจำนวนหนึ่ง

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

HAProxy เป็นตัวจัดสรรภาระงานสูงที่ช่วยให้คุณสามารถกำหนดค่ากฎการปรับสมดุลการรับส่งข้อมูลที่ยืดหยุ่นมากในระดับต่างๆ ของโมเดล OSI เราใช้มันเพื่อสร้างสมดุลต่อหน้าบริการทั้งหมด: ฐานข้อมูล นายหน้าข้อความ บริการ API บริการบนเว็บ โครงการภายในของเรา - ทุกอย่างอยู่เบื้องหลัง HAProxy

แอปพลิเคชันเอพีไอ — เว็บแอปพลิเคชันที่เขียนด้วยภาษาไพธอน ซึ่งผู้ใช้จัดการโครงสร้างพื้นฐานและบริการของเขา

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

สถาปัตยกรรมแอปพลิเคชัน OpenStack มาตรฐาน

บริการส่วนใหญ่ที่พัฒนาขึ้นสำหรับ OpenStack พยายามใช้กระบวนทัศน์เดียว โดยทั่วไปบริการจะประกอบด้วย 2 ส่วน ได้แก่ API และผู้ปฏิบัติงาน (ตัวดำเนินการแบ็กเอนด์) ตามกฎแล้ว API คือแอปพลิเคชัน WSGI ใน python ซึ่งเปิดตัวเป็นกระบวนการอิสระ (daemon) หรือใช้เว็บเซิร์ฟเวอร์ Nginx หรือ Apache สำเร็จรูป API ประมวลผลคำขอของผู้ใช้และส่งคำแนะนำเพิ่มเติมไปยังแอปพลิเคชันของผู้ปฏิบัติงานเพื่อดำเนินการ การถ่ายโอนเกิดขึ้นโดยใช้นายหน้าข้อความ ซึ่งโดยทั่วไปคือ RabbitMQ ส่วนตัวอื่น ๆ ได้รับการสนับสนุนไม่ดี เมื่อข้อความส่งถึงนายหน้า พนักงานจะประมวลผลข้อความเหล่านั้น และจะตอบกลับหากจำเป็น

กระบวนทัศน์นี้เกี่ยวข้องกับจุดความล้มเหลวทั่วไปที่แยกได้: RabbitMQ และฐานข้อมูล แต่ RabbitMQ ถูกแยกออกมาภายในบริการเดียว และตามทฤษฎีแล้ว สามารถแยกเป็นรายบุคคลสำหรับแต่ละบริการได้ ดังนั้นที่ MCS เราจึงแยกบริการเหล่านี้ให้มากที่สุดเท่าที่จะเป็นไปได้ เราจึงสร้างฐานข้อมูล RabbitMQ แยกต่างหากสำหรับแต่ละโครงการ แนวทางนี้เป็นสิ่งที่ดีเพราะในกรณีที่เกิดอุบัติเหตุ ณ จุดเสี่ยงบางจุด บริการไม่ได้พังทั้งหมดแต่เพียงบางส่วนเท่านั้น

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

บริการบางอย่างจำเป็นต้องมีการประสานงานภายในบริการเมื่อมีการดำเนินการตามลำดับที่ซับซ้อนเกิดขึ้นระหว่าง API และผู้ปฏิบัติงาน ในกรณีนี้ มีการใช้ศูนย์ประสานงานแห่งเดียว ซึ่งเป็นระบบคลัสเตอร์ เช่น Redis, Memcache ฯลฯ ซึ่งช่วยให้พนักงานคนหนึ่งสามารถบอกอีกคนหนึ่งได้ว่างานนี้ได้รับมอบหมายให้เขา (“โปรดอย่ารับไป”) เราใช้ ฯลฯ ตามกฎแล้ว พนักงานจะสื่อสารกับฐานข้อมูล เขียนและอ่านข้อมูลจากที่นั่น เราใช้ mariadb เป็นฐานข้อมูลซึ่งอยู่ในคลัสเตอร์มัลติมาสเตอร์

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

จุดอ่อนในโครงการทั้งหมดคือ RabbitMQ และ MariaDB สถาปัตยกรรมของพวกเขาสมควรได้รับบทความแยกต่างหาก ในบทความนี้ ฉันต้องการเน้นที่ความทนทานต่อข้อบกพร่องของ API

วิธีการใช้งานสถาปัตยกรรมเว็บที่ทนทานต่อข้อผิดพลาดในแพลตฟอร์ม Mail.ru Cloud Solutions
สถาปัตยกรรมแอปพลิเคชัน OpenStack การปรับสมดุลและความทนทานต่อข้อผิดพลาดของแพลตฟอร์มคลาวด์

การทำให้ HAProxy balancer ทนทานต่อข้อผิดพลาดโดยใช้ ExaBGP

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

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

ExaBGP ช่วยให้คุณใช้กลไกในการตรวจสอบสถานะของบริการได้ เราใช้กลไกนี้เพื่อตรวจสอบการทำงานของ HAProxy และในกรณีที่เกิดปัญหา ให้ปิดใช้งานบริการ HAProxy จาก BGP

รูปแบบ ExaBGP+HAProxy

  1. เราติดตั้งซอฟต์แวร์ที่จำเป็น ExaBGP และ HAProxy บนเซิร์ฟเวอร์สามเครื่อง
  2. เราสร้างอินเทอร์เฟซแบบย้อนกลับบนแต่ละเซิร์ฟเวอร์
  3. บนเซิร์ฟเวอร์ทั้งสามเครื่อง เราได้กำหนดที่อยู่ IP สีขาวเดียวกันให้กับอินเทอร์เฟซนี้
  4. ที่อยู่ IP สีขาวถูกโฆษณาบนอินเทอร์เน็ตผ่าน ExaBGP

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

ในกรณีที่เกิดปัญหากับการทำงานของ HAProxy หรือเซิร์ฟเวอร์ล้มเหลว ExaBGP จะหยุดประกาศเส้นทาง และการรับส่งข้อมูลจะสลับไปยังเซิร์ฟเวอร์อื่นได้อย่างราบรื่น

ดังนั้นเราจึงสามารถทนต่อความผิดพลาดของบาลานเซอร์ได้

วิธีการใช้งานสถาปัตยกรรมเว็บที่ทนทานต่อข้อผิดพลาดในแพลตฟอร์ม Mail.ru Cloud Solutions
ความทนทานต่อข้อผิดพลาดของบาลานเซอร์ HAProxy

รูปแบบกลายเป็นความไม่สมบูรณ์แบบ: เราเรียนรู้วิธีจอง HAProxy แต่ไม่ได้เรียนรู้วิธีกระจายโหลดภายในบริการ ดังนั้นเราจึงขยายแผนนี้เล็กน้อย: เราก้าวไปสู่การสร้างสมดุลระหว่างที่อยู่ IP สีขาวหลายรายการ

การปรับสมดุลตาม DNS บวก BGP

ปัญหาของการทำโหลดบาลานซ์สำหรับ HAProxy ของเรายังคงไม่ได้รับการแก้ไข อย่างไรก็ตาม มันสามารถแก้ไขได้ค่อนข้างง่ายเหมือนที่เราทำที่นี่

เพื่อสร้างสมดุลให้กับเซิร์ฟเวอร์ 3 เครื่อง คุณจะต้องมีที่อยู่ IP สีขาว XNUMX รายการและ DNS เก่าที่ดี ที่อยู่แต่ละรายการเหล่านี้ถูกกำหนดบนอินเทอร์เฟซแบบวนกลับของ HAProxy แต่ละรายการและโฆษณาทางอินเทอร์เน็ต

ใน OpenStack ในการจัดการทรัพยากร จะใช้ไดเร็กทอรีบริการซึ่งระบุ API จุดสิ้นสุดของบริการเฉพาะ ในไดเร็กทอรีนี้ เราจดทะเบียนชื่อโดเมน - public.infra.mail.ru ซึ่งแก้ไขผ่าน DNS ด้วยที่อยู่ IP ที่แตกต่างกันสามแห่ง เป็นผลให้เราได้รับการกระจายโหลดระหว่างสามที่อยู่ผ่านทาง DNS

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

เราเริ่มส่งเส้นทางผ่าน ExaBGP ด้วยตัวชี้วัดที่แตกต่างกัน ตัวปรับสมดุลแต่ละตัวโฆษณาที่อยู่ IP สีขาวทั้งสามรายการ แต่หนึ่งในนั้นซึ่งเป็นที่อยู่หลักสำหรับตัวปรับสมดุลนี้ ได้รับการโฆษณาโดยใช้ตัวชี้วัดขั้นต่ำ ดังนั้นในขณะที่บาลานเซอร์ทั้งสามกำลังทำงานอยู่ การเรียกไปยังที่อยู่ IP แรกจะไปที่บาลานเซอร์ตัวแรก การเรียกไปยังตัวที่สองถึงตัวที่สอง และการโทรไปยังตัวที่สามถึงตัวที่สาม

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

วิธีการใช้งานสถาปัตยกรรมเว็บที่ทนทานต่อข้อผิดพลาดในแพลตฟอร์ม Mail.ru Cloud Solutions
ปรับสมดุล HAProxy ตาม DNS + BGP

ปฏิสัมพันธ์ระหว่าง ExaBGP และ HAProxy

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

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

ในการดำเนินการนี้ คุณต้องกำหนดค่าตัวตรวจสอบความสมบูรณ์ในการกำหนดค่า ExaBGP ซึ่งสามารถตรวจสอบสถานะของ HAProxy ได้ ในกรณีของเรา เราได้กำหนดค่าแบ็กเอนด์สถานภาพใน HAProxy และจากฝั่ง ExaBGP เราจะตรวจสอบด้วยคำขอ GET แบบง่ายๆ หากการประกาศหยุดเกิดขึ้น แสดงว่า HAProxy น่าจะใช้งานไม่ได้และไม่จำเป็นต้องโฆษณา

วิธีการใช้งานสถาปัตยกรรมเว็บที่ทนทานต่อข้อผิดพลาดในแพลตฟอร์ม Mail.ru Cloud Solutions
ตรวจสุขภาพ HAProxy

HAProxy Peers: การซิงโครไนซ์เซสชัน

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

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

HAProxy ใช้ Stick-Table เพื่อบันทึกเซสชันไคลเอ็นต์ของกลไกนี้ โดยจะบันทึกที่อยู่ IP ดั้งเดิมของลูกค้า ที่อยู่เป้าหมายที่เลือก (แบ็กเอนด์) และข้อมูลบริการบางอย่าง โดยทั่วไป ตารางสติ๊กใช้เพื่อจัดเก็บคู่ต้นทาง-IP + ปลายทาง-IP ซึ่งมีประโยชน์อย่างยิ่งสำหรับแอปพลิเคชันที่ไม่สามารถถ่ายโอนบริบทเซสชันผู้ใช้เมื่อสลับไปยังบาลานเซอร์อื่น ตัวอย่างเช่น ในโหมดการปรับสมดุล RoundRobin

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

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

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

ใน IaaS เรามีบริการที่สร้างขึ้นโดยใช้เทคโนโลยีเดียวกัน นี้ Load Balancer เป็นบริการสำหรับ OpenStackซึ่งเรียกว่าออคตาเวีย ขึ้นอยู่กับกระบวนการ HAProxy สองกระบวนการ และในขั้นต้นจะมีการสนับสนุนสำหรับเพียร์ด้วย พวกเขาได้พิสูจน์ตัวเองว่ายอดเยี่ยมในบริการนี้

รูปภาพแสดงการเคลื่อนไหวของตารางเพียร์ระหว่างอินสแตนซ์ HAProxy สามอินสแตนซ์ตามแผนผัง โดยจะเสนอการกำหนดค่าเกี่ยวกับวิธีการกำหนดค่า:

วิธีการใช้งานสถาปัตยกรรมเว็บที่ทนทานต่อข้อผิดพลาดในแพลตฟอร์ม Mail.ru Cloud Solutions
HAProxy Peers (การซิงโครไนซ์เซสชัน)

หากคุณใช้รูปแบบเดียวกัน จะต้องทดสอบการทำงานของมันอย่างระมัดระวัง ไม่ใช่ความจริงที่ว่ามันจะทำงานในลักษณะเดียวกัน 100% ของเวลาทั้งหมด แต่อย่างน้อยคุณจะไม่สูญเสีย Stick Table เมื่อคุณต้องการจดจำ IP ต้นทางของไคลเอ็นต์

การจำกัดจำนวนคำขอพร้อมกันจากไคลเอนต์เดียวกัน

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

ไม่ทางใดก็ทางหนึ่ง ต้องมีการป้องกันเพิ่มเติม วิธีแก้ปัญหาที่ชัดเจนคือการจำกัดจำนวนคำขอ API และไม่เสียเวลาของ CPU ในการประมวลผลคำขอที่เป็นอันตราย

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

สิ่งนี้มีลักษณะอย่างไรในทางปฏิบัติ? เรามีลูกค้าที่ใช้ API การปรับขนาดอัตโนมัติของเราตลอดเวลา พวกเขาสร้างเครื่องเสมือนประมาณสองถึงสามร้อยเครื่องในตอนเช้าและลบออกในตอนเย็น สำหรับ OpenStack การสร้างเครื่องเสมือนพร้อมบริการ PaaS นั้นจำเป็นต้องมีคำขอ API อย่างน้อย 1000 รายการ เนื่องจากการโต้ตอบระหว่างบริการก็เกิดขึ้นผ่าน API เช่นกัน

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

วิธีอัปเดต Codebase ของคุณโดยที่ผู้ใช้ไม่สังเกตเห็น

นอกจากนี้เรายังใช้ความทนทานต่อข้อผิดพลาดในระดับกระบวนการปรับใช้โค้ดอีกด้วย อาจมีข้อบกพร่องในระหว่างการเปิดตัว แต่ผลกระทบต่อความพร้อมใช้งานของบริการสามารถลดลงได้

เราอัปเดตบริการของเราอย่างต่อเนื่องและต้องแน่ใจว่าโค้ดเบสได้รับการอัปเดตโดยไม่ส่งผลกระทบต่อผู้ใช้ เราจัดการเพื่อแก้ไขปัญหานี้โดยใช้ความสามารถในการจัดการของ HAProxy และการใช้งาน Graceful Shutdown ในบริการของเรา

เพื่อแก้ไขปัญหานี้ จำเป็นต้องตรวจสอบให้แน่ใจว่ามีการควบคุมบาลานเซอร์และการปิดบริการ "ถูกต้อง":

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

ด้วยสองประเด็นนี้ อัลกอริธึมที่ปลอดภัยสำหรับการปรับใช้ของเราจึงมีลักษณะเช่นนี้

  1. นักพัฒนารวบรวมแพ็คเกจโค้ดใหม่ (สำหรับเรานี่คือ RPM) ทดสอบในสภาพแวดล้อม dev ทดสอบในสเตจ และปล่อยไว้ในที่เก็บสเตจ
  2. นักพัฒนากำหนดงานสำหรับการปรับใช้พร้อมคำอธิบายโดยละเอียดที่สุดของ "สิ่งประดิษฐ์": เวอร์ชันของแพ็คเกจใหม่ คำอธิบายฟังก์ชันใหม่และรายละเอียดอื่น ๆ เกี่ยวกับการปรับใช้หากจำเป็น
  3. ผู้ดูแลระบบเริ่มการอัพเดต เปิดตัว Playbook Ansible ซึ่งจะทำสิ่งต่อไปนี้:
    • รับแพ็กเกจจากที่เก็บสเตจและใช้เพื่ออัปเดตเวอร์ชันของแพ็กเกจในที่เก็บผลิตภัณฑ์
    • รวบรวมรายการแบ็กเอนด์ของบริการที่อัปเดต
    • ปิดบริการแรกที่จะได้รับการอัปเดตใน HAProxy และรอให้กระบวนการทำงานเสร็จสิ้น ต้องขอบคุณการปิดระบบอย่างค่อยเป็นค่อยไป เรามั่นใจว่าคำขอของลูกค้าปัจจุบันทั้งหมดจะเสร็จสมบูรณ์ได้สำเร็จ
    • หลังจากที่ API และผู้ปฏิบัติงานหยุดทำงานโดยสมบูรณ์ และปิด HAProxy แล้ว โค้ดก็จะได้รับการอัปเดต
    • บริการเรียกใช้ Ansible
    • สำหรับแต่ละบริการ ระบบจะดึง "แฮนเดิล" บางส่วนออก ซึ่งทำการทดสอบหน่วยกับการทดสอบคีย์ที่กำหนดไว้ล่วงหน้าจำนวนหนึ่ง มีการตรวจสอบรหัสใหม่ขั้นพื้นฐาน
    • หากไม่พบข้อผิดพลาดในขั้นตอนก่อนหน้า ระบบจะเปิดใช้งานแบ็กเอนด์
    • มาดูแบ็กเอนด์ถัดไปกันดีกว่า
  4. หลังจากอัปเดตแบ็กเอนด์ทั้งหมดแล้ว การทดสอบการทำงานจะเริ่มขึ้น หากไม่มีหายไป นักพัฒนาจะพิจารณาฟังก์ชันใหม่ที่เขาสร้างขึ้น

การดำเนินการนี้ทำให้การติดตั้งใช้งานเสร็จสมบูรณ์

วิธีการใช้งานสถาปัตยกรรมเว็บที่ทนทานต่อข้อผิดพลาดในแพลตฟอร์ม Mail.ru Cloud Solutions
รอบการอัพเดตบริการ

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

ข้อสรุป

การแบ่งปันความคิดของตัวเองเกี่ยวกับสถาปัตยกรรมเว็บที่ทนทานต่อข้อผิดพลาด ฉันอยากจะทราบประเด็นสำคัญอีกครั้ง:

  • ความอดทนต่อความผิดพลาดทางกายภาพ
  • ความทนทานต่อข้อผิดพลาดของเครือข่าย (บาลานเซอร์, BGP);
  • ความทนทานต่อข้อผิดพลาดของซอฟต์แวร์ที่ใช้และพัฒนา

ทุกคนมีสถานะการออนไลน์ที่มั่นคง!

ที่มา: will.com

เพิ่มความคิดเห็น