งานสร้างแบบกระจาย

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

การแคชระยะไกล

การบิลด์แบบกระจายประเภทที่ง่ายที่สุดคือการบิลด์ที่ใช้ประโยชน์จากแคชระยะไกลเท่านั้น ซึ่งแสดงในรูปที่ 1

การสร้างแบบกระจายที่มีการแคชระยะไกล

รูปที่ 1 บิลด์แบบกระจายที่แสดงการแคชระยะไกล

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

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

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

การดำเนินการระยะไกล

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

ระบบการดำเนินการระยะไกล

รูปที่ 2 ระบบการดำเนินการระยะไกล

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

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

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

บิลด์แบบกระจายที่ Google

ตั้งแต่ปี 2008 Google ใช้ระบบบิลด์แบบกระจายที่ใช้ทั้ง การแคชระยะไกลและการดำเนินการระยะไกล ซึ่งแสดงในรูปที่ 3

ระบบบิลด์ระดับสูง

รูปที่ 3 ระบบบิลด์แบบกระจายของ Google

แคชระยะไกลของ Google เรียกว่า ObjFS โดยประกอบด้วยแบ็กเอนด์ที่จัดเก็บเอาต์พุตบิลด์ใน Bigtable ซึ่งกระจายอยู่ทั่วกลุ่มเครื่องที่ใช้ในการผลิต และแดมอน FUSE ของฟรอนต์เอนด์ชื่อ objfsd ที่ทำงานในเครื่องของนักพัฒนาซอฟต์แวร์แต่ละคน FUSE Daemon ช่วยให้วิศวกรเรียกดูเอาต์พุตการสร้างได้ราวกับว่าเอาต์พุตเหล่านั้นเป็นไฟล์ปกติที่จัดเก็บไว้ในเวิร์กสเตชัน แต่จะดาวน์โหลดเนื้อหาไฟล์ตามคำขอเฉพาะสำหรับไฟล์ไม่กี่ไฟล์ที่ผู้ใช้ขอโดยตรงเท่านั้น การแสดงเนื้อหาไฟล์ตามต้องการจะช่วยลดการใช้งานทั้งเครือข่ายและดิสก์ได้อย่างมาก และระบบจะสร้างได้เร็วขึ้นเป็น 2 เท่าเมื่อเทียบกับตอนที่เราจัดเก็บ เอาต์พุตการสร้างทั้งหมดไว้ในดิสก์ภายในของนักพัฒนาซอฟต์แวร์

ระบบการดำเนินการระยะไกลของ Google เรียกว่า Forge ไคลเอ็นต์ Forge ใน Blaze (เทียบเท่าภายในของ Bazel) ที่ชื่อ Distributor จะส่งคำขอสำหรับแต่ละการดำเนินการไปยังงานที่ทำงานในศูนย์ข้อมูลของเราที่เรียกว่า Scheduler ตัวกำหนดเวลารักษาแคชของผลลัพธ์การดำเนินการ ซึ่งช่วยให้สามารถส่งคืนการตอบกลับได้ทันทีหากผู้ใช้รายอื่นในระบบได้สร้างการดำเนินการ ไว้แล้ว หากไม่ได้ ระบบจะจัดคิวการดำเนินการ กลุ่มงาน Executor จำนวนมากจะอ่านการดำเนินการจากคิวนี้อย่างต่อเนื่อง ดำเนินการ และจัดเก็บผลลัพธ์ใน ObjFS Bigtable โดยตรง ผู้ดำเนินการจะใช้ผลลัพธ์เหล่านี้สำหรับดำเนินการในอนาคต หรือผู้ใช้ปลายทางจะดาวน์โหลดผลลัพธ์ผ่าน objfsd ก็ได้

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