क्योंकि जीवन आरेखों को पुनः बनाने के लिए बहुत छोटा है मैंने हाल ही में एक नई कंपनी में के तौर पर काम शुरू किया है। जैसा कि हमेशा होता है, मुझे शुरुआत से ही शुरुआत करनी पड़ी। जैसे कि: ऐप के लिए कोड कहाँ रहता है? इसे कैसे तैनात किया जाता है? कॉन्फ़िगरेशन कहाँ से आते हैं? शुक्र है, मेरे सहकर्मियों ने सब कुछ 'कोड के रूप में बुनियादी ढाँचा' बनाने का शानदार काम किया। इसलिए मैंने खुद को यह सोचते हुए पाया: सॉफ्टवेयर इंजीनियर अगर सब कुछ कोड में है, तो सभी बिंदुओं को जोड़ने के लिए कोई उपकरण क्यों नहीं है? यह उपकरण कोडबेस की समीक्षा करेगा और मुख्य पहलुओं पर प्रकाश डालते हुए एक एप्लिकेशन आर्किटेक्चर आरेख बनाएगा। एक नया इंजीनियर आरेख को देखकर कह सकता है, "आह, ठीक है, यह इस तरह काम करता है।" सबसे पहली बात चाहे मैंने कितनी भी मेहनत की हो, मुझे ऐसा कुछ नहीं मिला। मुझे सबसे करीबी मिलान ऐसी सेवाएँ मिलीं जो एक बुनियादी ढाँचा आरेख बनाती हैं। मैंने उनमें से कुछ को में शामिल किया है ताकि आप उन्हें करीब से देख सकें। आखिरकार, मैंने गूगल करना छोड़ दिया और कुछ नए शानदार सामान विकसित करने में अपने हाथ आजमाने का फैसला किया। इस समीक्षा सबसे पहले, मैंने Gradle, और Terraform के साथ एक सैंपल ऐप बनाया। GitHub एक्शन पाइपलाइन ऐप को Amazon Elastic Container Service पर तैनात करती है। यह रेपो उस टूल का स्रोत होगा जिसे मैं बनाऊँगा (कोड है)। Docker Java यहाँ दूसरा, मैंने एक बहुत ही उच्च-स्तरीय आरेख बनाया जो मैं परिणाम के रूप में देखना चाहता था: मैंने निर्णय लिया कि दो प्रकार के संसाधन होंगे: अवशेष मुझे शब्द बहुत ज़्यादा भारी लगा, इसलिए मैंने चुना। तो रेलिक क्या है? यह 90% ऐसी चीज़ है जिसे आप देखना चाहते हैं। इसमें शामिल हैं, लेकिन इन्हीं तक सीमित नहीं: आर्टिफैक्ट रेलिक कलाकृतियाँ (योजना पर नीले बक्से, यानी, जार, डॉकर छवियाँ), टेराफॉर्म संसाधनों को कॉन्फ़िगर करता है (योजना पर गुलाबी बॉक्स, यानी, EC2 इंस्टेंस, ECS, SQS कतारें), कुबेरनेट्स संसाधन, और भी बहुत कुछ हर रेलिक का एक नाम होता है (जैसे, my-shiny-app), वैकल्पिक प्रकार (जैसे, Jar), और कुंजी → मान युग्मों का एक सेट (जैसे, पथ → /build/libs/my-shiny-app.jar) जो रेलिक का पूरी तरह से वर्णन करता है। उन्हें कहा जाता है। रेलिक में जितनी अधिक परिभाषाएँ होंगी - उतना ही बेहतर होगा। परिभाषाएँ स्रोत दूसरा प्रकार है। स्रोत अवशेषों को परिभाषित, निर्मित या प्रावधानित करते हैं (उदाहरण के लिए, ऊपर पीले रंग के बक्से)। एक स्रोत किसी स्थान पर अवशेष का वर्णन करता है और यह बताता है कि यह कहाँ से आता है। जबकि स्रोत वे घटक हैं जिनसे हमें सबसे अधिक जानकारी मिलती है, वे आमतौर पर आरेख पर द्वितीयक अर्थ रखते हैं। आपको शायद टेराफ़ॉर्म या ग्रेडल से हर दूसरे अवशेष तक जाने के लिए बहुत सारे तीरों की आवश्यकता नहीं है। स्रोत अवशेष और स्रोत का संबंध अनेक-से-अनेक है। फूट डालो और राज करो कोड के हर हिस्से को कवर करना असंभव है। आधुनिक ऐप्स में कई फ्रेमवर्क, टूल या क्लाउड घटक हो सकते हैं। अकेले AWS के पास टेराफ़ॉर्म के लिए लगभग 950 संसाधन और डेटा स्रोत हैं! टूल को आसानी से विस्तार योग्य और डिज़ाइन द्वारा अलग किया जाना चाहिए ताकि अन्य लोग या कंपनियाँ योगदान दे सकें। जबकि मैं अविश्वसनीय रूप से प्लग करने योग्य टेराफॉर्म प्रदाताओं की वास्तुकला का बहुत बड़ा प्रशंसक हूं, मैंने इसे सरलीकृत करने के बावजूद इसे बनाने का फैसला किया: एक स्पष्ट जिम्मेदारी है: अनुरोधित स्रोत फ़ाइलों के आधार पर अवशेष बनाना। उदाहरण के लिए, *.gradle फ़ाइलों को पढ़ता है और , , या अवशेष लौटाता है। प्रत्येक प्रदाता उन प्रकारों के अवशेष बनाता है जिनके बारे में वे जानते हैं। प्रदाता अवशेषों के बीच बातचीत की परवाह नहीं करते हैं। वे अवशेषों को घोषणात्मक रूप से बनाते हैं, एक दूसरे से पूरी तरह से अलग। प्रदाता की GradleProvider Jar War Gz इस दृष्टिकोण के साथ, आप जितना चाहें उतना गहराई से जा सकते हैं। GitHub Actions इसका एक अच्छा उदाहरण है। एक सामान्य वर्कफ़्लो YAML फ़ाइल में दर्जनों चरण होते हैं, जो शिथिल युग्मित घटकों और सेवाओं का उपयोग करते हैं। एक वर्कफ़्लो एक JAR, फिर एक Docker छवि बना सकता है, और इसे पर्यावरण में तैनात कर सकता है। वर्कफ़्लो में हर एक चरण को उसके प्रदाता द्वारा कवर किया जा सकता है। इसलिए, मान लीजिए, के डेवलपर्स केवल उन चरणों से संबंधित एक प्रदाता बनाते हैं जिनकी उन्हें परवाह है। Docker Actions यह दृष्टिकोण किसी भी संख्या में लोगों को समानांतर रूप से काम करने की अनुमति देता है, जिससे टूल में अधिक तर्क जुड़ जाता है। अंतिम उपयोगकर्ता अपने प्रदाताओं को भी जल्दी से लागू कर सकते हैं (कुछ मालिकाना तकनीक के मामले में)। नीचे अनुकूलन के अंतर्गत अधिक देखें। विलय करना या न करना सबसे रोचक भाग में जाने से पहले आइए अगले जाल पर नज़र डालें। दो प्रदाता, जिनमें से प्रत्येक एक अवशेष बनाता है। यह ठीक है। लेकिन क्या होगा अगर इनमें से दो अवशेष दो स्थानों पर परिभाषित एक ही घटक का प्रतिनिधित्व करते हैं? यहाँ एक उदाहरण है। टास्क डेफ़िनेशन JSON को पार्स करता है और प्रकार के साथ एक Relic तैयार करता है। GitHub एक्शन वर्कफ़्लो में ECS से संबंधित चरण भी है, इसलिए दूसरा प्रदाता Relic बनाता है। अब, हमारे पास डुप्लिकेट हैं क्योंकि दोनों प्रदाता एक दूसरे के बारे में कुछ नहीं जानते हैं। इसके अलावा, उनमें से किसी के लिए यह मान लेना गलत है कि दूसरे ने पहले ही एक Relic बना लिया है। फिर क्या? AmazonECSProvider AmazonECSTask AmazonECSTaskDeployment हम किसी भी डुप्लिकेट को नहीं हटा सकते क्योंकि उनमें से प्रत्येक की अपनी परिभाषाएँ (विशेषताएँ) हैं। एकमात्र तरीका उन्हें मर्ज करना है। डिफ़ॉल्ट रूप से, अगला तर्क मर्जिंग निर्णय को परिभाषित करता है: relic1.name() == relic2.name() && relic1.source() != relic2.source() हम दो अवशेषों को मर्ज करते हैं यदि उनके नाम समान हैं, लेकिन वे विभिन्न स्रोतों में परिभाषित हैं (जैसे हमारे उदाहरण में, रिपो में JSON और कार्य परिभाषा संदर्भ गिटहब क्रियाओं में है)। जब हम विलय करते हैं, तो हम: एकल नाम चुनें सभी परिभाषाएँ (कुंजी → मान युग्म) मर्ज करें दोनों मूल स्रोतों का संदर्भ देते हुए एक संयुक्त स्रोत बनाएं एक रेखा खींचो मैंने जानबूझकर रेलिक के एक महत्वपूर्ण पहलू को छोड़ दिया। इसमें एक हो सकता है - और इसका होना बेहतर है! मैचर एक बूलियन फ़ंक्शन है जो एक तर्क लेता है और उसका परीक्षण करता है। मैचर लिंकिंग प्रक्रिया के महत्वपूर्ण हिस्से हैं। यदि कोई रेलिक किसी अन्य के रेलिक की किसी भी परिभाषा से मेल खाता है, तो उन्हें एक साथ जोड़ा जाएगा। मैचर याद है जब मैंने कहा था कि प्रदाताओं को अन्य प्रदाताओं द्वारा बनाए गए अवशेषों के बारे में कोई जानकारी नहीं है? यह अभी भी सच है। हालाँकि, एक प्रदाता एक अवशेष के लिए एक मिलानकर्ता को परिभाषित करता है। दूसरे शब्दों में, यह परिणामी आरेख पर दो बक्सों के बीच एक तीर के एक तरफ का प्रतिनिधित्व करता है। उदाहरण. Dockerfile में एक ENTRYPOINT निर्देश है. ENTRYPOINT java -jar /app/arch-diagram-sample.jar कुछ हद तक निश्चितता के साथ, हम कह सकते हैं कि Docker के अंतर्गत निर्दिष्ट की गई हर चीज़ को । इसलिए, Relic में एक सरल Matcher फ़ंक्शन है: . सबसे अधिक संभावना है कि परिभाषाओं में वाले कुछ Relics इससे मेल खाएँगे। यदि हाँ, तो और Relics के बीच एक तीर दिखाई देता है। ENTRYPOINT कंटेनराइज़ करता है Dockerfile entrypointInstruction.contains(anotherRelicsDefinition) arch-diagram-sample.jar Jar Dockerfile Jar मैचर परिभाषित होने के साथ, लिंकिंग प्रक्रिया बहुत सरल लगती है। लिंकिंग सेवा सभी अवशेषों पर पुनरावृत्ति करती है और उनके मैचर के फ़ंक्शन को कॉल करती है। क्या अवशेष A, अवशेष B की किसी परिभाषा से मेल खाता है? हाँ? परिणामी ग्राफ़ में उन अवशेषों के बीच एक किनारा जोड़ें। किनारे को नाम भी दिया जा सकता है। VISUALIZATION अंतिम चरण पिछले चरण के हमारे अंतिम ग्राफ को विज़ुअलाइज़ करना है। स्पष्ट PNG के अलावा, उपकरण अतिरिक्त प्रारूपों का समर्थन करता है, जैसे कि , और । ये टेक्स्ट प्रारूप कम आकर्षक लग सकते हैं, लेकिन बड़ा फायदा यह है कि आप उन टेक्स्ट को लगभग किसी भी विकी पेज में एम्बेड कर सकते हैं ( , और भी कई)। मरमेड प्लांट UML DOT GitHub , संगम हे नमूना रिपो का अंतिम आरेख इस प्रकार दिखता है: अनुकूलन कस्टम घटकों को प्लग इन करने या मौजूदा तर्क को बदलने की क्षमता आवश्यक है, खासकर जब कोई उपकरण अपने प्रारंभिक चरण में हो। अवशेष और स्रोत डिफ़ॉल्ट रूप से काफी लचीले होते हैं; आप उनमें जो चाहें डाल सकते हैं। हर दूसरा घटक अनुकूलन योग्य है। मौजूदा प्रदाता आपके लिए आवश्यक संसाधनों को कवर नहीं करते हैं? आसानी से अपना खुद का कार्यान्वयन करें। ऊपर वर्णित मर्जिंग या लिंकिंग लॉजिक से संतुष्ट नहीं हैं? कोई समस्या नहीं; अपना खुद का या जोड़ें। सब कुछ एक JAR फ़ाइल में पैक करें और इसे स्टार्टअप पर जोड़ें। और पढ़ें। LinkStrategy MergeStrategy यहाँ किया स्रोत कोड के आधार पर आरेख तैयार करने से संभवतः गति मिलेगी। और विशेष रूप से टूल (हाँ, यह उस टूल का नाम है जिसके बारे में मैं बात कर रहा था)। ! NoReDraw योगदानकर्ताओं का स्वागत है सबसे उल्लेखनीय लाभ (जो नाम से आता है) यह है कि घटकों के बदलने पर आरेख को फिर से बनाने की आवश्यकता नहीं होती है। इंजीनियरिंग ध्यान की कमी के कारण सामान्य रूप से दस्तावेज़ीकरण (और विशेष रूप से आरेख) पुराना हो जाता है। जैसे उपकरणों के साथ, यह अब कोई समस्या नहीं होनी चाहिए क्योंकि यह किसी भी PR/CI पाइपलाइन में आसानी से प्लग करने योग्य है। याद रखें, 😉 NoReDraw आरेखों को फिर से बनाने के लिए जीवन बहुत छोटा है