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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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