Robinhood บริการโหลดบาลานซ์ภายในองค์กรของ Dropbox
(dropbox.tech)- Robinhood คือบริการโหลดบาลานซ์ภายในของ Dropbox ที่เริ่มใช้งานในปี 2020
- บริการนี้ทำหน้าที่กำหนดเส้นทางทราฟฟิกภายในระหว่างเซิร์ฟเวอร์เพื่อกระจายโหลดของบริการอย่างสมดุล
- ก่อนมี Robinhood บริการส่วนใหญ่ของ Dropbox ประสบปัญหาจากการกระจายโหลดระหว่างแบ็กเอนด์ที่ไม่สมดุล
- ความแตกต่างของฮาร์ดแวร์และข้อจำกัดของอัลกอริทึมโหลดบาลานซ์แบบเดิมทำให้เกิดปัญหาด้านความน่าเชื่อถือจากอินสแตนซ์ที่โอเวอร์โหลด
- เพื่อแก้ปัญหานี้ จำเป็นต้องโปรวิชัน service fleet เกินความต้องการ ซึ่งนำไปสู่ต้นทุนฮาร์ดแวร์ที่สูงขึ้น
ความสามารถใหม่ของ Robinhood
- มีการนำคอนโทรลเลอร์ PID (Proportional-Integral-Derivative) มาใช้ ทำให้จัดการความไม่สมดุลของโหลดได้รวดเร็วและมีประสิทธิภาพมากขึ้น
- สิ่งนี้นำไปสู่การปรับปรุงความน่าเชื่อถือของโครงสร้างพื้นฐานและลดต้นทุนฮาร์ดแวร์ได้อย่างมาก
- เมื่อเวิร์กโหลด AI ที่ขับเคลื่อนความสามารถอัจฉริยะสมัยใหม่เพิ่มขึ้น การจัดการอุปสงค์ต่อทรัพยากร GPU อย่างมีประสิทธิภาพจึงสำคัญกว่าที่เคย
ความท้าทายของการทำโหลดบาลานซ์ที่ Dropbox
- ระบบ service discovery ของ Dropbox สามารถสเกลไปยังโฮสต์หลายแสนเครื่องที่กระจายอยู่ในดาต้าเซ็นเตอร์ทั่วโลก
- บริการบางอย่างของ Dropbox มีไคลเอนต์หลายล้านราย แต่ไม่สามารถอนุญาตให้ไคลเอนต์แต่ละรายเชื่อมต่อกับทุกเซิร์ฟเวอร์อินสแตนซ์ได้
- เพราะจะสร้างแรงกดดันต่อหน่วยความจำของเซิร์ฟเวอร์มากเกินไป และเมื่อเซิร์ฟเวอร์รีสตาร์ตอาจเกิดโอเวอร์โหลดจาก TLS handshake ได้
- ดังนั้นจึงใช้ระบบ service discovery เพื่อมอบชุดย่อยของเซิร์ฟเวอร์ที่ไคลเอนต์ควรเชื่อมต่อให้กับไคลเอนต์แต่ละราย
- กลยุทธ์โหลดบาลานซ์ที่ดีที่สุดที่ไคลเอนต์สามารถใช้ได้คือทำ round-robin กับรายการที่อยู่จากระบบ service discovery
- แต่ด้วยวิธีนี้ โหลดของแต่ละเซิร์ฟเวอร์อินสแตนซ์อาจไม่สมดุลกันมาก
- การเพิ่มขนาดของชุดย่อยเป็นวิธีบรรเทาที่ทำได้ง่าย แต่ไม่ได้ขจัดความไม่สมดุลทั้งหมด และเพียงเพิ่มพารามิเตอร์อีกตัวให้เจ้าของบริการต้องดูแล
- ปัญหาที่ลึกกว่านั้นคือ ถึงแม้จะส่งคำขอไปยังแต่ละเซิร์ฟเวอร์ในจำนวนเท่ากัน ฮาร์ดแวร์พื้นฐานของแต่ละเซิร์ฟเวอร์ก็อาจแตกต่างกัน
- กล่าวคือ คำขอเดียวกันอาจใช้ทรัพยากรไม่เท่ากันบนฮาร์ดแวร์แต่ละคลาส
- ประเด็นสำคัญคือไคลเอนต์มองไม่เห็นโหลดของเซิร์ฟเวอร์
- ในอดีต Dropbox เคยพยายามแก้ปัญหานี้โดยให้เซิร์ฟเวอร์แนบข้อมูลโหลดไว้ใน response header
- จากนั้นไคลเอนต์สามารถทำโหลดบาลานซ์เองได้โดยเลือกเอนด์พอยต์ที่มีโหลดต่ำที่สุดจากชุดย่อยของที่อยู่
- แม้ผลลัพธ์จะดูมีแนวโน้มที่ดี แต่ก็ยังมีข้อเสียบางประการ
- เนื่องจากทั้งฝั่งเซิร์ฟเวอร์และไคลเอนต์ต้องแก้โค้ดเพื่อรองรับ load header แบบพิเศษ จึงยากต่อการนำไปใช้ทั่วทั้งระบบ
- ผลลัพธ์ดี แต่ยังดีไม่พอ
การตัดสินใจสร้าง Robinhood
- ในปี 2019 มีการตัดสินใจอย่างเป็นทางการให้สร้าง Robinhood
- บริการใหม่นี้ถูกสร้างขึ้นบนระบบ service discovery ภายในที่มีอยู่เดิม โดยรวบรวมข้อมูลโหลดจากเซิร์ฟเวอร์และแนบเข้ากับข้อมูลการกำหนดเส้นทาง
- Robinhood ใช้ Endpoint Discovery Service ของ Envoy เพื่อผสานข้อมูลโหลดเข้ากับน้ำหนักของเอนด์พอยต์ ทำให้ไคลเอนต์สามารถทำ weighted round-robin ได้
- ชุมชน gRPC กำลังรับเอาโปรโตคอล Envoy xDS มาใช้ ทำให้ Robinhood ใช้งานร่วมได้ทั้งกับ Envoy และไคลเอนต์ gRPC
- ในเวลานั้นไม่มีโซลูชันโหลดบาลานซ์ที่มีอยู่ซึ่งตอบโจทย์ความต้องการของ Dropbox ได้ จึงตัดสินใจสร้างบริการใหม่ขึ้นมา
ผลลัพธ์ของ Robinhood
- หลังใช้งานในโปรดักชันมาหลายปี พบผลลัพธ์ที่น่าพอใจ
- สามารถลดขนาด fleet ของบริการขนาดใหญ่บางส่วนลงได้ 25% ส่งผลให้ประหยัดต้นทุนฮาร์ดแวร์ต่อปีได้อย่างมาก
- ความน่าเชื่อถือก็ดีขึ้นด้วย เพราะมีโปรเซสที่ถูกใช้งานหนักเกินไปน้อยลง
สถาปัตยกรรมของ Robinhood
- ในแต่ละดาต้าเซ็นเตอร์จะมีการดีพลอยอินสแตนซ์ของ Robinhood ซึ่งประกอบด้วย 3 ส่วน ได้แก่ บริการโหลดบาลานซ์ พร็อกซี และฐานข้อมูลเส้นทาง
บริการโหลดบาลานซ์ (LBS)
- เป็นแกนหลักของ Robinhood
- มีหน้าที่รวบรวมข้อมูลโหลดและสร้างข้อมูลการกำหนดเส้นทางที่มีน้ำหนักของเอนด์พอยต์
- เนื่องจากมีหลายอินสแตนซ์อัปเดตข้อมูลการกำหนดเส้นทางของบริการพร้อมกัน จึงใช้ shard manager ภายในเพื่อกำหนด worker หลักให้แต่ละบริการ
- เพราะแต่ละบริการเป็นอิสระจากกัน จึงสามารถแบ่ง LBS ตามบริการและสเกลแนวนอนได้
พร็อกซี
- ทำหน้าที่ส่งข้อมูลโหลดของบริการไปยังพาร์ทิชัน LBS ที่เกี่ยวข้องภายในดาต้าเซ็นเตอร์
- การใช้พร็อกซียังช่วยลดจำนวนการเชื่อมต่อโดยตรงเข้าสู่โปรเซส LBS
- หากไม่มีพร็อกซี ทุกโปรเซส LBS จะต้องเชื่อมต่อกับทุกโหนดในโครงสร้างพื้นฐาน
- แต่เมื่อให้โปรเซส LBS เชื่อมต่อเฉพาะกับพร็อกซี แรงกดดันต่อหน่วยความจำของ LBS ก็ลดลงอย่างมาก
- พร็อกซีเชื่อมต่อเฉพาะกับโหนดภายในดาต้าเซ็นเตอร์เดียวกัน จึงสามารถสเกลแนวนอนได้
- แพตเทิร์นนี้ถูกใช้ในหลายส่วนของโครงสร้างพื้นฐานเพื่อป้องกันไม่ให้บริการต้องรับการเชื่อมต่อ TLS มากเกินไป
ฐานข้อมูลเส้นทาง
- เป็นฐานข้อมูลบน ZooKeeper/etcd สำหรับเก็บข้อมูลการกำหนดเส้นทางของบริการ เช่น ชื่อโฮสต์ ที่อยู่ IP และค่าน้ำหนักที่ LBS สร้างขึ้น
- ZooKeeper และ etcd สามารถแจ้งการเปลี่ยนแปลงของโหนด/คีย์ให้กับ watcher ทั้งหมดได้แบบเรียลไทม์ และเหมาะมากกับกรณีใช้งาน service discovery ที่เน้นการอ่านของ Dropbox
- ความสอดคล้องแบบ eventual consistency ที่ ZooKeeper/etcd รับประกันนั้นเพียงพอสำหรับ service discovery เช่นกัน
เจาะลึกบริการโหลดบาลานซ์
- เป้าหมายของการทำโหลดบาลานซ์คือทำให้การใช้งานของทุกโหนดเท่ากับค่าเฉลี่ยของการใช้งาน
- ใช้คอนโทรลเลอร์ PID เพื่อรักษาการใช้งานของแต่ละโหนดให้ใกล้เคียงกับค่าเฉลี่ยมากที่สุด
- LBS จะสร้างคอนโทรลเลอร์ PID สำหรับแต่ละโหนด และใช้ค่าเฉลี่ยของการใช้งานเป็น setpoint
- LBS ใช้ผลลัพธ์ของคอนโทรลเลอร์ PID เป็น delta สำหรับค่าน้ำหนักของเอนด์พอยต์ และทำ normalization ของน้ำหนักระหว่างทุกเอนด์พอยต์ของบริการ
- แม้โหนดใหม่จะต้องใช้การปรับหลายครั้งกว่าจะเข้าใกล้ค่าเฉลี่ยของการใช้งาน แต่คอนโทรลเลอร์ PID ก็มีประสิทธิภาพมากในการทำโหลดบาลานซ์
สถานการณ์การทำงานของ LBS
- LBS ถูกออกแบบมาให้จัดการกับสถานการณ์หลากหลายที่อาจส่งผลต่อการทำโหลดบาลานซ์ ตั้งแต่การรีสตาร์ตโหนดไปจนถึงการขาดหายของรายงานโหลด
- เพื่อคงประสิทธิภาพที่เหมาะสม LBS จึงมีการใช้กลยุทธ์หลายอย่างเพื่อจัดการกรณียกเว้นเหล่านี้
การเริ่มต้น LBS
- LBS เก็บข้อมูลโหลดและสถานะของคอนโทรลเลอร์ PID ไว้ในหน่วยความจำ
- ระหว่างการรีสตาร์ต LBS จะยังไม่เริ่มอัปเดตค่าน้ำหนักในทันที แต่จะรอสักครู่จนกว่ารายงานโหลดจะเข้ามา
- สำหรับค่าน้ำหนักของคอนโทรลเลอร์ PID นั้น LBS จะอ่านค่าน้ำหนักของเอนด์พอยต์จากฐานข้อมูลเส้นทางเพื่อกู้คืนกลับมา
โหนด Cold Start
- เนื่องจากมีโหนดใหม่เข้าร่วมใน service fleet อยู่บ่อยครั้ง การป้องกันปัญหา Thundering Herd จึงสำคัญ
- เพราะการใช้งานเริ่มต้นของโหนดใหม่มักเป็น 0 LBS จึงตั้งค่าน้ำหนักของโหนดใหม่ไว้ที่น้ำหนักเอนด์พอยต์ต่ำ และปล่อยให้คอนโทรลเลอร์ PID ค่อยๆ ดึงโหนดนั้นขึ้นสู่ค่าเฉลี่ยของการใช้งาน
รายงานโหลดที่หายไป
- ในสภาพแวดล้อมของระบบกระจาย ความขัดข้องเป็นเรื่องปกติ
- จากความแออัดของเครือข่ายหรือความเสียหายของฮาร์ดแวร์ รายงานโหลดของบางโหนดอาจมาช้าหรือไม่มาถึงเลย
- LBS จะข้ามโหนดเหล่านี้ระหว่างการอัปเดตค่าน้ำหนัก ทำให้น้ำหนักของเอนด์พอยต์ของโหนดนั้นไม่เปลี่ยนแปลง
- อย่างไรก็ตาม หากรายงานโหลดหายไปจำนวนมาก การคำนวณค่าเฉลี่ยของการใช้งานอาจไม่แม่นยำ
- เพื่อความปลอดภัย LBS จะข้ามขั้นตอนการอัปเดตค่าน้ำหนักทั้งหมดในกรณีนี้
เมตริกการใช้งาน
- การใช้งาน CPU เป็นเมตริกโหลดบาลานซ์ที่ใช้แพร่หลายที่สุดที่ Dropbox
- สำหรับบริการที่ไม่ได้ติดคอขวดที่ CPU จำนวนคำขอที่กำลังดำเนินการอยู่เป็นตัวชี้วัดทางเลือกที่ดี
- LBS ถูกพัฒนาให้รองรับการทำโหลดบาลานซ์โดยอิงจาก CPU และ/หรือจำนวนคำขอที่กำลังดำเนินการอยู่
ข้อจำกัด
- คอนโทรลเลอร์ PID สร้าง feedback loop เพื่อคงการใช้งานของโหนดให้อยู่ใกล้ค่าเป้าหมาย (ค่าเฉลี่ยของการใช้งาน)
- หากมี feedback น้อยมาก เช่น บริการที่มีทราฟฟิกต่ำมาก หรือคำขอที่มี latency สูงมากซึ่งวัดเป็นระดับนาที การทำโหลดบาลานซ์จะไม่มีประสิทธิภาพ
- บริการที่มีคำขอ latency สูงควรเป็นแบบ asynchronous
การกำหนดเส้นทางข้ามดาต้าเซ็นเตอร์
- อินสแตนซ์ LBS จัดการโหลดบาลานซ์ภายในดาต้าเซ็นเตอร์
- ส่วนการกำหนดเส้นทางข้ามดาต้าเซ็นเตอร์มีปัจจัยที่ต้องพิจารณาแตกต่างออกไป
- ตัวอย่างเช่น ต้องการกำหนดเส้นทางคำขอไปยังดาต้าเซ็นเตอร์ที่ใกล้ที่สุดเพื่อลดเวลาไป-กลับของคำขอ
- เพื่อให้ทำได้ Dropbox จึงเพิ่มการตั้งค่า locality ที่กำหนดการแบ่งทราฟฟิกระหว่างดาต้าเซ็นเตอร์ปลายทาง
การประเมินประสิทธิภาพของตัวโหลดบาลานซ์
- ประสิทธิภาพของการโหลดบาลานซ์วัดด้วยอัตราส่วน max/avg
- หากเจ้าของบริการเลือกการโหลดบาลานซ์โดยอิงตาม CPU จะใช้ maxCPU/avgCPU เป็นตัวชี้วัดประสิทธิภาพ
- โดยทั่วไปเจ้าของบริการจะจัดสรรทรัพยากรให้บริการโดยอิงตามอัตราการใช้งานสูงสุดระหว่างโหนด เนื่องจากเป้าหมายหลักของการโหลดบาลานซ์คือการลดขนาดของฟลีต
- กลยุทธ์การโหลดบาลานซ์ด้วย PID controller สามารถรักษาอัตราส่วน max/avg ให้ใกล้ 1 ได้
กราฟประเมินประสิทธิภาพการโหลดบาลานซ์
- กราฟที่แสดงค่า max/avg CPU และ p95/avg CPU ของคลัสเตอร์ Envoy proxy ที่ใหญ่ที่สุด
- หลังเปิดใช้งานการโหลดบาลานซ์ที่อิง PID controller เมตริกทั้งสองลดลงมาใกล้ 1
- อัตราส่วน max/avg ลดจาก 1.26 เหลือ 1.01 แสดงให้เห็นการปรับปรุง 20%
- กราฟที่แสดงการวิเคราะห์เปอร์เซ็นไทล์ของอัตราการใช้ CPU รายโหนด
- หลังเปิดใช้งานการโหลดบาลานซ์ที่อิง PID controller ค่า max, p95, avg และ p5 แทบจะรวมเป็นเส้นเดียวกัน
- อีกกราฟหนึ่งที่แสดงค่า max/avg CPU และ p95/avg CPU ของคลัสเตอร์ฐานข้อมูลฟรอนต์เอนด์ที่ใหญ่ที่สุด
- หลังเปิดใช้งานการโหลดบาลานซ์ที่อิง PID controller เมตริกทั้งสองลดลงมาใกล้ 1
- อัตราส่วน max/avg ลดจาก 1.4 เหลือ 1.05 แสดงให้เห็นการปรับปรุง 25%
- อีกกราฟหนึ่งที่แสดงการวิเคราะห์เปอร์เซ็นไทล์ของอัตราการใช้ CPU รายโหนด
- หลังเปิดใช้งานการโหลดบาลานซ์ที่อิง PID controller ค่า max, p95, avg และ p5 กลับมารวมเป็นเส้นเดียวกันอีกครั้ง
เหตุผลที่สร้าง Config Aggregator
- Robinhood มีหลายตัวเลือกให้เจ้าของบริการเลือกใช้ และยังสามารถนำการเปลี่ยนแปลงไปใช้แบบไดนามิกได้
- เจ้าของบริการสร้างและอัปเดตการตั้งค่า Robinhood ของบริการจาก service directory ภายใน codebase
- การตั้งค่าเหล่านี้ถูกเก็บไว้ในบริการจัดการคอนฟิก ซึ่งเป็นไลบรารีที่สะดวกสำหรับรับการเปลี่ยนแปลงของคอนฟิก Robinhood แบบเรียลไทม์
- อย่างไรก็ตาม ด้วยปัญหาบางประการ จึงไม่สามารถ build และ push mega config ของ Robinhood จาก codebase ได้เป็นประจำ
- หากการเปลี่ยนแปลงถูกนำเข้ามาผ่านการ push คอนฟิก การกดปุ่ม rollback มีความเสี่ยง
- เพราะไม่อาจทราบได้ว่ามีบริการอื่นเปลี่ยนไปมากน้อยเพียงใดนับจากการ push ครั้งล่าสุด
- ทีมที่เป็นเจ้าของ Robinhood ต้องรับผิดชอบต่อการ push mega config แต่ละครั้งด้วย
- ซึ่งหมายความว่าทีม Robinhood ต้องมีส่วนร่วมกับทุกการ push คอนฟิกที่เปลี่ยนแปลง และนั่นเป็นการสิ้นเปลืองเวลาเชิงวิศวกรรม
- เพราะ incident ส่วนใหญ่เจ้าของบริการสามารถแก้ไขได้เอง
- เพื่อให้ความเสี่ยงที่อาจเกิดขึ้นต่ำที่สุด การ push แต่ละครั้งใช้เวลาหลายชั่วโมงในการ deploy ไปยังหลายดาต้าเซ็นเตอร์
- หากการเปลี่ยนแปลงถูกนำเข้ามาผ่านการ push คอนฟิก การกดปุ่ม rollback มีความเสี่ยง
- เพื่อแก้ปัญหาเหล่านี้ จึงสร้างบริการขนาดเล็กอีกตัวหนึ่งชื่อ Config Aggregator
Config Aggregator
- Config Aggregator รวบรวมคอนฟิกแยกตามบริการทั้งหมด และประกอบเป็น mega config ที่ LBS จะใช้งาน
- Config Aggregator เฝ้าติดตามคอนฟิกของแต่ละบริการ และกระจายการเปลี่ยนแปลงไปยัง mega config แบบเรียลไทม์
- Config Aggregator ยังมีความสามารถ tombstone เพื่อป้องกันไม่ให้คอนฟิก Robinhood ของบริการถูกลบโดยไม่ตั้งใจ
- หากเจ้าของบริการ push การเปลี่ยนแปลงที่ลบบริการออกจากคอนฟิก Robinhood, Config Aggregator จะทำเครื่องหมาย tombstone แทนการลบรายการบริการทันที
- การลบจริงจะเกิดขึ้นหลังจากนั้นอีกหลายวัน
- ฟีเจอร์นี้ยังช่วยแก้ race condition ที่อาจเกิดจากรอบการ push ที่ต่างกันระหว่างคอนฟิก Robinhood กับคอนฟิกการกำหนดเส้นทางอื่น ๆ (เช่น คอนฟิก Envoy)
- ข้อเสียของบริการจัดการคอนฟิกคือปัจจุบันไม่มีการจัดการเวอร์ชัน
- จึงสำรอง mega config เป็นระยะ เผื่อจำเป็นต้องย้อนคอนฟิก LBS กลับไปยังสถานะที่ทราบว่าปลอดภัย
กลยุทธ์การย้ายระบบ
- การสลับกลยุทธ์การโหลดบาลานซ์ทั้งหมดในคราวเดียวอาจมีความเสี่ยง
- นี่คือเหตุผลที่ Robinhood อนุญาตให้กำหนดหลายกลยุทธ์การโหลดบาลานซ์สำหรับบริการได้
- Dropbox มี feature gate แบบอิงเปอร์เซ็นต์ จึงนำกลยุทธ์แบบผสมมาใช้ โดยให้ไคลเอนต์ใช้ผลรวมถ่วงน้ำหนักของค่าน้ำหนักที่สร้างจากสองกลยุทธ์การโหลดบาลานซ์เป็นค่าน้ำหนักของ endpoint
- วิธีนี้ทำให้ย้ายไปสู่กลยุทธ์การโหลดบาลานซ์ใหม่ได้อย่างค่อยเป็นค่อยไป โดยที่ไคลเอนต์ทั้งหมดมองเห็นการกำหนดค่าน้ำหนักเดียวกันสำหรับ endpoint
สิ่งที่ได้เรียนรู้
- ระหว่างการออกแบบและพัฒนา Robinhood ได้รับบทเรียนสำคัญหลายข้อเกี่ยวกับสิ่งที่ได้ผลและสิ่งที่ไม่ได้ผล
- การให้ความสำคัญกับความเรียบง่าย ลดการเปลี่ยนแปลงฝั่งไคลเอนต์ให้เหลือน้อยที่สุด และวางแผนการย้ายระบบตั้งแต่แรก ช่วยให้การพัฒนาและ deploy LBS ง่ายขึ้น และหลีกเลี่ยงกับดักที่มีต้นทุนสูงได้
คอนฟิกควรเรียบง่ายที่สุดเท่าที่เป็นไปได้
- Robinhood เพิ่มตัวเลือกจำนวนมากให้เจ้าของบริการตั้งค่าได้
- แต่ในกรณีส่วนใหญ่ สิ่งที่พวกเขาต้องการคือค่าเริ่มต้นที่มีให้
- คอนฟิกเริ่มต้นที่ดีและเรียบง่าย (หรือถ้าดีกว่านั้นคือไม่ต้องมีคอนฟิกเลย) สามารถประหยัดเวลาเชิงวิศวกรรมได้มหาศาล
การเปลี่ยนแปลงฝั่งไคลเอนต์ก็ควรรักษาให้เรียบง่ายเช่นกัน
- การ rollout การเปลี่ยนแปลงไปยังไคลเอนต์ภายในอาจใช้เวลาหลายเดือน
- deployment ส่วนใหญ่ถูก push ทุกสัปดาห์ แต่หลายระบบ deploy เพียงเดือนละครั้ง หรือบางครั้งไม่ deploy เลยเป็นเวลาหลายปี
- ยิ่งย้ายการเปลี่ยนแปลงไปไว้ที่ LBS ได้มากเท่าไรยิ่งดี
- ตัวอย่างเช่น ในช่วงแรกได้ตัดสินใจใช้ weighted round robin ในการออกแบบไคลเอนต์ และหลังจากนั้นก็ไม่เปลี่ยนอีกเลย
- สิ่งนี้ช่วยเพิ่มความเร็วของการดำเนินงานอย่างมาก
- การจำกัดการเปลี่ยนแปลงส่วนใหญ่ไว้ที่ LBS ยังช่วยลดความเสี่ยงด้านเสถียรภาพด้วย
- เพราะหากจำเป็น การเปลี่ยนแปลงใน LBS สามารถ rollback ได้ภายในไม่กี่นาที
การย้ายระบบควรถูกวางแผนตั้งแต่ขั้นตอนออกแบบโครงการ
- การย้ายระบบใช้เวลาเชิงวิศวกรรมมหาศาล
- และยังมีความเสี่ยงด้านเสถียรภาพที่ต้องคำนึงถึง
- แม้จะไม่ใช่งานที่สนุก แต่เป็นงานสำคัญ
- เมื่อต้องออกแบบบริการใหม่ ควรพิจารณาให้เร็วที่สุดว่าจะย้าย use case เดิมไปยังบริการใหม่อย่างราบรื่นได้อย่างไร
- ยิ่งมีข้อกำหนดที่ต้องให้เจ้าของบริการทำมากเท่าไร การย้ายระบบก็ยิ่งกลายเป็นฝันร้าย
- โดยเฉพาะเมื่อเป็นคอมโพเนนต์โครงสร้างพื้นฐานพื้นฐาน
- กระบวนการย้ายระบบของ Robinhood ไม่ได้ถูกออกแบบไว้อย่างดีตั้งแต่แรก จึงใช้เวลามากกว่าที่คาดไว้มากในการนำกระบวนการกลับมาออกแบบใหม่และออกแบบคอนฟิกใหม่
- เวลาทางวิศวกรรมที่ต้องใช้ในการย้ายระบบควรเป็นตัวชี้วัดสำคัญของความสำเร็จ
ผลลัพธ์ของ Robinhood
- หลังใช้งานในโปรดักชันมาราว 1 ปี สามารถกล่าวได้ว่า Robinhood เวอร์ชันล่าสุดสามารถแก้ปัญหาการโหลดบาลานซ์ที่ Dropbox เผชิญมานานได้อย่างมีประสิทธิภาพ
- อัลกอริทึม PID controller ซึ่งเป็นแกนหลัก แสดงผลลัพธ์ที่น่าสนใจ และแสดงการปรับปรุงประสิทธิภาพอย่างมีนัยสำคัญในบริการขนาดใหญ่ที่สุด
- ยังได้รับข้อมูลเชิงลึกอันมีค่าเกี่ยวกับการออกแบบและการปฏิบัติการบริการโหลดบาลานซ์ในระดับขนาดของ Dropbox
เชิงอรรถ
-
ให้ N, M และ s แทนจำนวนเซิร์ฟเวอร์ จำนวนไคลเอนต์ และขนาดของส่วนย่อยของที่อยู่ตามลำดับ จำนวนไคลเอนต์ที่เซิร์ฟเวอร์เชื่อมต่ออยู่เป็นไปตามตัวอย่างของการแจกแจงทวินาม B(M, s/n) ดังที่กล่าวไว้ก่อนหน้านี้ ไคลเอนต์ทำ simple round robin กับชุดที่อยู่ที่ service discovery ให้มา ดังนั้นหากไคลเอนต์แต่ละตัวส่งคำขอในปริมาณใกล้เคียงกัน การกระจายโหลดฝั่งเซิร์ฟเวอร์จะมีลักษณะคล้ายการแจกแจงทวินาม
-
ขยายระบบ service discovery เดิมเพื่อรองรับโปรโตคอล gRPC xDS (A27) ณ เวลาที่เขียนบล็อกนี้ gRPC client ยังไม่รองรับ weighted round robin สำหรับค่าน้ำหนัก endpoint จาก control plane จึงได้พัฒนา custom weighted round robin picker โดยอิงจากการจัดตารางแบบ earliest deadline first
-
มีกรณีที่น่าสนใจซึ่งบริการเกิดอาการค้างเป็นช่วง ๆ เพราะ I/O ที่ประสิทธิภาพลดลง ในสถานการณ์นี้ CPU ของโหนดดังกล่าวจะยังคงต่ำ และ LBS จะเริ่มเพิ่มค่าน้ำหนักของโหนดเพื่อดัน CPU ขึ้นสู่ค่าเฉลี่ย จนนำไปสู่ dead spiral วิธีแก้คือใช้ค่าสูงสุดของ CPU และจำนวนคำขอที่กำลังดำเนินการอยู่เป็นตัววัดโหลดเพื่อทำให้บริการสมดุล
ความเห็นของ GN⁺
- Robinhood ดูเป็นบริการที่ยอดเยี่ยมซึ่งแก้ปัญหาโหลดบาลานซ์ของ Dropbox ได้อย่างมีประสิทธิภาพ การนำ PID controller มาใช้เป็นจุดที่น่าประทับใจ
- นี่เป็นกรณีศึกษาที่แสดงให้เห็นได้ชัดว่าโหลดบาลานซ์ในโครงสร้างพื้นฐานระดับโลกขนาดใหญ่นั้นเป็นโจทย์ที่ยากเพียงใด มีหลายปัจจัยที่ต้องคำนึงถึง เช่น ความแตกต่างของฮาร์ดแวร์ การกระจายโหลดที่ไม่สมดุล และความหนาแน่นของเครือข่าย
- ดูเหมือนว่าสิ่งสำคัญคือการออกแบบให้ทุกคอมโพเนนต์เชื่อมโยงกันอย่างเป็นระบบและทำงานร่วมกันได้ดี แม้ LBS, พร็อกซี และ routing DB จะแยกจากกัน แต่ก็โต้ตอบกันอย่างใกล้ชิดแบบเรียลไทม์
- กราฟที่ใช้ประเมินประสิทธิภาพโหลดบาลานซ์เชิงปริมาณและแสดงภาพการปรับปรุงต่าง ๆ น่าประทับใจมาก โดยเฉพาะการแสดงให้เห็นอย่างชัดเจนว่าการรักษาอัตราส่วน max/avg ให้ใกล้ 1 มีความสำคัญต่อการปรับขนาด fleet ให้เหมาะสม
- การนำ Config Aggregator มาใช้เพื่อแยกการตั้งค่าตามแต่ละบริการก็ดูเป็นไอเดียที่ดี ช่วยให้เจ้าของบริการสามารถจัดการการเปลี่ยนแปลงของตนเองได้อย่างอิสระ
- การมีมาตรการป้องกันอย่าง tombstone ก็เป็นรายละเอียดที่ใส่ใจเช่นกัน การป้องกันไม่ให้การตั้งค่าถูกลบโดยความผิดพลาดเป็นเรื่องสำคัญ
- บทเรียนเกี่ยวกับกลยุทธ์การย้ายระบบก็ดูมีประโยชน์ หากไม่คำนึงถึงการย้ายระบบตั้งแต่แรก ภายหลังก็อาจต้องเสียเวลาไปมาก
- โดยรวมแล้ว Robinhood ดูเป็นโซลูชันที่เป็นระบบและออกแบบมาอย่างประณีตสำหรับการทำโหลดบาลานซ์ในระดับของ Dropbox และเป็นกรณีศึกษาที่บริษัทอื่นซึ่งมีโครงสร้างพื้นฐานขนาดใหญ่สามารถนำไปอ้างอิงได้
โซลูชันที่คล้ายกัน:
- Elastic Load Balancing (ELB) ของ AWS และ Cloud Load Balancing ของ Google Cloud ก็มีบริการแบบ managed service สำหรับการทำโหลดบาลานซ์ในระดับใหญ่เช่นกัน
- ในกรณีของ Kubernetes แม้จะมีโหลดบาลานเซอร์ของตัวเอง (
kube-proxy) แต่หากใช้โซลูชัน service mesh เช่น Istio หรือ Linkerd ก็จะสามารถใช้ความสามารถด้านโหลดบาลานซ์และการจัดการทราฟฟิกที่ทรงพลังยิ่งขึ้นได้ - Zuul ของ Netflix และ Envoy ของ Lyft ก็มีความสามารถด้านโหลดบาลานซ์แบบพร็อกซีเป็นฐานเช่นกัน
ข้อควรพิจารณาเมื่อเริ่มใช้งาน:
- จำเป็นต้องตรวจสอบความเข้ากันได้กับโครงสร้างพื้นฐานและบริการเดิม และหากต้องมีการย้ายระบบก็ควรวางกลยุทธ์ไว้
- ต้องทดสอบและมอนิเตอร์ผลกระทบต่อประสิทธิภาพและเสถียรภาพอย่างเพียงพอ บั๊กในตรรกะโหลดบาลานซ์อาจร้ายแรงได้
- ควรกำหนดขอบเขตและความเร็วในการนำมาใช้โดยพิจารณาจากศักยภาพของทีม การค่อย ๆ ใช้งานเป็นขั้นตอนน่าจะดีกว่าการนำไปใช้กับทั้งหมดอย่างเร่งรีบ
- ในระยะยาวจำเป็นต้องมีความพยายามในการปรับให้เหมาะสมและพัฒนาอย่างต่อเนื่อง เช่น การจูนอัลกอริทึมโหลดบาลานซ์ให้เหมาะกับสถานการณ์ และการกำจัดคอขวดจะช่วยได้
1 ความคิดเห็น
ได้ยินเรื่องตัวควบคุม PID ในฝั่งซอฟต์แวร์ด้วยแฮะ 55