डिस्ट्रिब्यूट किए गए बिल्ड

बड़ा कोडबेस होने पर, डिपेंडेंसी की चेन काफ़ी गहरी हो सकती है. यहां तक कि सामान्य बाइनरी भी अक्सर हज़ारों बिल्ड टारगेट पर निर्भर हो सकती हैं. इस स्तर पर, एक ही मशीन पर इतने समय में निर्माण पूरा कर पाना नामुमकिन है: मशीन के हार्डवेयर पर लगाए गए भौतिकी के बुनियादी नियमों को कोई बिल्ड सिस्टम नहीं बना सकता. ऐसा करने का सिर्फ़ एक तरीका है, एक ऐसे बिल्ड सिस्टम का इस्तेमाल करना जो डिस्ट्रिब्यूटेड बिल्ड के साथ काम करता हो. इसमें, सिस्टम से किए जा रहे काम की इकाइयां, मशीन की आर्बिट्रेरी और स्केलेबल संख्या में फैली होती हैं. यह मानते हुए कि हमने सिस्टम के काम को छोटी-छोटी इकाइयों में बांट दिया है (इस बारे में ज़्यादा जानकारी बाद में दी गई है), इससे हम जितनी जल्दी हो सके किसी भी साइज़ का कोई भी बिल्ड पूरा कर सकते हैं. बड़े करने की इस क्षमता की वजह से हम आर्टफ़ैक्ट पर आधारित बिल्ड सिस्टम तय कर रहे हैं.

रिमोट कैशिंग

डिस्ट्रिब्यूटेड बिल्ड का सबसे आसान तरीका वह है जो सिर्फ़ रिमोट कैशिंग का इस्तेमाल करता है, जिसे पहली इमेज में दिखाया गया है.

रिमोट कैशिंग के साथ डिस्ट्रिब्यूट किया गया बिल्ड

पहला डायग्राम. डिस्ट्रिब्यूट किया गया बिल्ड, जिसमें रिमोट कैश मेमोरी दिखती है

बिल्ड करने वाला हर सिस्टम, जिसमें डेवलपर वर्कस्टेशन और लगातार इंटिग्रेशन सिस्टम, दोनों शामिल हैं. इसमें रिमोट कैश की सामान्य सेवा का रेफ़रंस दिया जाता है. यह सेवा तेज़ और स्थानीय कम समय के लिए स्टोरेज सिस्टम हो सकती है, जैसे कि Redis या Google Cloud Storage जैसी क्लाउड सेवा. जब भी किसी उपयोगकर्ता को सीधे तौर पर या किसी डिपेंडेंसी के तौर पर आर्टफ़ैक्ट बनाने की ज़रूरत होती है, तो सिस्टम सबसे पहले रिमोट कैश की मदद से जांच करता है कि वह आर्टफ़ैक्ट पहले से मौजूद है या नहीं. अगर ऐसा है, तो वह आर्टिफ़िशियल बनाने के बजाय उसे डाउनलोड कर सकता है. अगर ऐसा नहीं होता है, तो सिस्टम आर्टफ़ैक्ट बनाता है और नतीजे को वापस कैश में अपलोड करता है. इसका मतलब है कि ऐसी लो-लेवल डिपेंडेंसी, जो अक्सर बदलती नहीं हैं, उन्हें एक बार बनाया जा सकता है और सभी उपयोगकर्ताओं के बीच शेयर किया जा सकता है. इससे हर उपयोगकर्ता को फिर से बनाने की ज़रूरत नहीं पड़ती. Google में, कई आर्टफ़ैक्ट नए सिरे से बनाने के बजाय कैश मेमोरी से उपलब्ध कराए जाते हैं. इससे हमारे बिल्ड सिस्टम को चलाने में बहुत ज़्यादा लागत आती है.

रिमोट कैशिंग सिस्टम काम करे, इसके लिए बिल्ड सिस्टम को यह गारंटी देनी होगी कि बिल्ड पूरी तरह से फिर से जनरेट किए जा सकते हैं. इसका मतलब यह है कि किसी भी बिल्ड टारगेट के लिए यह ऐसा होना चाहिए कि उस टारगेट के लिए इनपुट के सेट को इस तरह से तय किया जा सके कि इनपुट का एक ही सेट किसी भी मशीन पर ठीक वही आउटपुट दे. यह पक्का करने का यही एक तरीका है कि किसी आर्टफ़ैक्ट को डाउनलोड करने के नतीजे और उसे खुद बनाने के नतीजे एक जैसे हों. ध्यान दें कि इसके लिए यह ज़रूरी है कि कैश में मौजूद हर आर्टफ़ैक्ट को उसके टारगेट और इनपुट के हैश, दोनों पर सेट किया गया हो. इस तरह, अलग-अलग इंजीनियर एक ही समय पर एक टारगेट में अलग-अलग बदलाव कर सकते हैं. साथ ही, रिमोट कैश, नतीजे मिलने वाले सभी आर्टफ़ैक्ट को स्टोर करेगा और बिना किसी रुकावट के उन्हें सही तरीके से इस्तेमाल करेगा.

बेशक, रिमोट कैश से फ़ायदा पाने के लिए ज़रूरी है कि किसी आर्टफ़ैक्ट को डाउनलोड करने की तुलना में, उसे तेज़ी से डाउनलोड किया जाए. हमेशा ऐसा नहीं होता है, खास तौर पर तब, जब कैश सर्वर उस मशीन से दूर हो जो बिल्ड कर रहा हो. बिल्ड के नतीजों को तेज़ी से शेयर करने के लिए, Google का नेटवर्क और बिल्ड सिस्टम ध्यान से तैयार किया जाता है.

रिमोट एक्ज़ीक्यूशन

रिमोट कैश मेमोरी, एक जगह पर डिलीवर नहीं होती है. अगर कैश मेमोरी में सेव नहीं किया जाता या आपने ऐसा छोटा-सा बदलाव किया है जिसके लिए सब कुछ फिर से बनाने की ज़रूरत है, तब भी आपको अपनी मशीन पर पूरा बिल्ड स्थानीय तौर पर करना होगा. इसका असल लक्ष्य दूर से एक्ज़ीक्यूशन की मदद करना है, जिसमें बिल्ड करने का असल काम कितने भी कर्मचारियों के बीच किया जा सके. इमेज 2 में, रिमोट तौर पर एक्ज़ीक्यूट करने का सिस्टम दिखाया गया है.

रिमोट एक्ज़ीक्यूशन सिस्टम

दूसरा डायग्राम. रिमोट एक्ज़ीक्यूशन सिस्टम

हर उपयोगकर्ता की मशीन पर चल रहा बिल्ड टूल (जहां उपयोगकर्ता या तो मैन्युअल तरीके से काम करने वाले इंजीनियर या ऑटोमेटेड बिल्ड सिस्टम हैं) एक सेंट्रल बिल्ड मास्टर को अनुरोध भेजता है. बिल्ड मास्टर अनुरोधों को कॉम्पोनेंट की कार्रवाइयों में बांट देता है और उन कार्रवाइयों को एक बड़े कर्मचारियों के पूल पर शेड्यूल करता है. हर वर्कर, उपयोगकर्ता के बताए गए इनपुट के साथ पूछी गई कार्रवाइयों को पूरा करता है और इन आर्टफ़ैक्ट को लिखता है. इन आर्टफ़ैक्ट को उन दूसरी मशीन के साथ शेयर किया जाता है जो इन कार्रवाइयों की ज़रूरत होती हैं. इन कार्रवाइयों को तब तक शेयर किया जाता है, जब तक कि फ़ाइनल आउटपुट बनाकर उपयोगकर्ता को नहीं भेजा जाता.

इस तरह के सिस्टम को लागू करने का सबसे मुश्किल हिस्सा कर्मचारियों, मास्टर, और उपयोगकर्ता की लोकल मशीन के बीच कम्यूनिकेशन को मैनेज करना है. काम करने वाले, दूसरे कर्मचारियों के बनाए गए इंटरमीडिएट आर्टफ़ैक्ट पर निर्भर हो सकते हैं. आखिरी आउटपुट को उपयोगकर्ता की लोकल मशीन पर वापस भेजना ज़रूरी होता है. ऐसा करने के लिए, हम पहले बताए गए डिस्ट्रिब्यूटेड कैश मेमोरी को बेहतर बना सकते हैं. इसके लिए, हर वर्कर को कैश मेमोरी से उन नतीजों को लिखने और उनसे मिलने वाली डिपेंडेंसी पढ़ने के लिए कहा जाएगा. मास्टर, कर्मचारियों को तब तक आगे बढ़ने से रोकता है, जब तक वे सब कुछ पूरा नहीं हो जाते. इस स्थिति में, वे कैश से अपने इनपुट पढ़ सकेंगे. फ़ाइनल प्रॉडक्ट को कैश मेमोरी में सेव भी किया जाता है, ताकि लोकल मशीन उसे डाउनलोड कर सके. ध्यान दें कि हमें उपयोगकर्ता के सोर्स ट्री में लोकल बदलावों को एक्सपोर्ट करने के लिए एक अलग तरीके की भी ज़रूरत होगी, ताकि टीम उन बदलावों को बनाने से पहले लागू कर सके.

यह काम करे, इसके लिए आर्टफ़ैक्ट पर आधारित बिल्ड सिस्टम के उन सभी हिस्सों को एक साथ लाना होगा जिनके बारे में पहले बताया गया था. बिल्ड एनवायरमेंट को पूरी तरह से खुद का ब्यौरा देना चाहिए, ताकि हम बिना किसी इंसान के काम करने के लिए कर्मचारियों की मदद कर सकें. बिल्ड प्रोसेस अपने-आप में पूरी तरह से शामिल होनी चाहिए, क्योंकि हो सकता है कि हर चरण को किसी अलग मशीन पर लागू किया जाए. आउटपुट को पूरी तरह से तय करना चाहिए, ताकि हर वर्कर, दूसरे वर्कर से मिलने वाले नतीजों पर भरोसा कर सके. किसी टास्क पर आधारित सिस्टम के लिए, इस तरह की गारंटी देना बहुत मुश्किल होता है. इससे, एक भरोसेमंद रिमोट एक्ज़ीक्यूशन सिस्टम बनाना संभव नहीं होता.

Google में डिस्ट्रिब्यूट किए गए बिल्ड

साल 2008 से Google, डिस्ट्रिब्यूटेड बिल्ड सिस्टम का इस्तेमाल कर रहा है. इसमें रिमोट कैशिंग और रिमोट एक्ज़ीक्यूशन, दोनों का इस्तेमाल किया जाता है. इमेज 3 में दिखाया गया है.

हाई-लेवल बिल्ड सिस्टम

तीसरी इमेज. Google का डिस्ट्रिब्यूटेड बिल्ड सिस्टम

Google की रिमोट कैश मेमोरी को ObjFS कहा जाता है. इसमें एक बैकएंड शामिल है, जो Bigtables में आउटपुट बनाता है. ये आउटपुट हमारी सभी मशीनों में डिस्ट्रिब्यूट होते हैं. साथ ही, objfsd नाम का एक फ़्रंटएंड FUSE डीमन भी होता है, जो हर डेवलपर की मशीन पर काम करता है. FUSE डीमन की मदद से इंजीनियर आउटपुट को इस तरह ब्राउज़ कर सकते हैं, जैसे कि वे वर्कस्टेशन पर सेव की गई सामान्य फ़ाइलें हों. हालांकि, फ़ाइल का कॉन्टेंट सिर्फ़ उन फ़ाइलों के लिए मांग पर डाउनलोड किया जा सकता है जिनका अनुरोध उपयोगकर्ता ने सीधे तौर पर किया हो. मांग पर फ़ाइल कॉन्टेंट दिखाने से नेटवर्क और डिस्क के इस्तेमाल में काफ़ी कमी आती है. साथ ही, डेवलपर की लोकल डिस्क पर सभी बिल्ड आउटपुट को स्टोर करने के मुकाबले, सिस्टम तेज़ी से कॉन्टेंट बना पाता है.

Google के रिमोट एक्ज़ीक्यूशन सिस्टम को Forge कहा जाता है. Blaze (बज़ेल का अंदरूनी समतुल्य) नाम का एक फ़ोर्ज क्लाइंट है. डिस्ट्रिब्यूटर, हमारे डेटासेंटर में चल रही जॉब को शेड्यूलर नाम की जॉब को हर कार्रवाई के लिए अनुरोध भेजता है. शेड्यूलर, कार्रवाई के नतीजों की कैश मेमोरी में सेव करता है. अगर सिस्टम के किसी दूसरे उपयोगकर्ता ने पहले ही कार्रवाई की है, तो यह तुरंत रिस्पॉन्स दे सकता है. अगर ऐसा नहीं है, तो यह कार्रवाई को सूची में रख देता है. एक्ज़ीक्यूटर जॉब का एक बड़ा पूल इस सूची से कार्रवाइयों को लगातार पढ़ता है, उन्हें एक्ज़ीक्यूट करता है, और नतीजों को सीधे ऑब्जेएफ़एस Bigtables में स्टोर करता है. ये नतीजे, आने वाले समय में की जाने वाली कार्रवाइयों या असली उपयोगकर्ता से objfsd डाउनलोड करने के लिए उपलब्ध कराए जा सकते हैं.

आखिरी नतीजा एक ऐसा सिस्टम है जो Google पर परफ़ॉर्म किए जाने वाले सभी बिल्ड के साथ बेहतर तरीके से काम करता है. Google के बिल्ड का दायरा काफ़ी बड़ा है: Google हर दिन करोड़ों टेस्ट केस का इस्तेमाल करके, लाखों टेस्ट केस चलाता है और बिल्ड आउटपुट के पेटाबाइट बनाता है. इस तरह के सिस्टम से, हमारे इंजीनियर आसानी से कॉम्प्लेक्स कोडबेस नहीं बना पाते. साथ ही, इससे हम बड़ी संख्या में ऐसे ऑटोमेटेड टूल और सिस्टम भी लागू कर पाते हैं जो हमारे बिल्ड पर निर्भर होते हैं.