3.12

View in English

3.12 इवेंट-संचालित आर्किटेक्चर और मैसेजिंग

अवलोकन और प्रेरणा

इवेंट-संचालित आर्किटेक्चर (EDA) एक ऐसी शैली है जिसमें घटक एक-दूसरे को सीधे कॉल करने के बजाय इवेंट उत्पन्न करके और उन पर प्रतिक्रिया देकर संवाद करते हैं। एक इवेंट एक तथ्य है: कुछ ऐसा जो पहले ही घटित हो चुका है, जैसे “OrderPlaced” या “PaymentCaptured।” एक प्रोड्यूसर उस तथ्य की घोषणा करता है और आगे बढ़ जाता है, और कोई भी संख्या में उपभोक्ता अपने स्वयं के समय पर प्रतिक्रिया देते हैं, बिना प्रोड्यूसर को यह जाने कि कौन सुन रहा है। यह अध्याय 2.3 के रिक्वेस्ट-एंड-रिप्लाई कॉल से भिन्न मुद्रा है, जहाँ एक कॉलर किसी विशिष्ट सेवा से कुछ करने के लिए कहता है और उत्तर की प्रतीक्षा करता है।

एक बड़े संगठन के लिए, आकर्षण बड़े पैमाने पर डीकपलिंग है। जब आपके पास दर्जनों टीमें और सैकड़ों सेवाएँ हों, तो सब कुछ को डायरेक्ट पॉइंट-टू-पॉइंट कॉल से जोड़ना एक भंगुर जाल बनाता है जहाँ एक टीम का बदलाव दूसरी टीम को तोड़ देता है और कोई यह पता नहीं लगा पाता कि क्यों। इवेंट टीमों को एक-दूसरे के आंतरिक भागों के बजाय तथ्यों की एक साझा स्ट्रीम के माध्यम से एकीकृत होने देते हैं, और एक नया उपभोक्ता सब्सक्राइब करके शामिल हो जाता है, बिना प्रोड्यूसर द्वारा कोड की एक भी पंक्ति बदले। यह गुण, कच्चे थ्रूपुट से कहीं अधिक, वह कारण है कि इवेंट-संचालित दृष्टिकोण उद्यमों में उलझे हुए एकीकरण की जगह लेते हुए और सरकारों में उन एजेंसियों को जोड़ते हुए फैलते रहते हैं जो अपनी-अपनी प्रणालियों की मालिक हैं।

सार्वजनिक क्षेत्र को एक दूसरा लाभ मिलता है जिसे कम आँकना आसान है: जो कुछ हुआ उसका एक टिकाऊ, क्रमबद्ध रिकॉर्ड एक ऑडिट और पारदर्शिता की संपत्ति है। जब कोई नागरिक पूछता है कि कोई लाभ निर्णय उस तरह क्यों आया, तो उस निर्णय तक ले जाने वाले इवेंट का एक अपरिवर्तनीय लॉग सीधे उत्तर देता है। लेकिन इवेंट-संचालित डिज़ाइन मुफ़्त नहीं है और हमेशा सही नहीं है: अतुल्यकालिक (asynchronous) प्रवाहों को ट्रेस करना कठिन है, तर्क करना कठिन है, और अति-प्रयोग करना आसान है। यह अध्याय इस बारे में स्पष्ट राय रखता है कि डीकपलिंग और स्केल कब अतिरिक्त जटिलता की कीमत चुकाते हैं, और कब एक सामान्य सिंक्रोनस कॉल आपकी बेहतर सेवा करता। यह अध्याय 3.3 की वितरित-प्रणाली वास्तविकताओं पर निर्मित है, इसलिए यदि आपने अभी तक नहीं पढ़ा है तो पहले उसे पढ़ें।

मुख्य सिद्धांत

  • इवेंट तथ्य हैं, निर्देश नहीं। एक इवेंट बताता है कि क्या हुआ; एक कमांड किसी चीज़ के होने के लिए कहता है। इन्हें अलग रखें, और इवेंट के नाम भूतकाल में रखें।
  • डीकपलिंग ही मुद्दा है। प्रोड्यूसर को यह जानने या परवाह करने की आवश्यकता नहीं है कि उनके इवेंट का उपभोग कौन करता है। यदि वे करते हैं, तो आपके पास मैसेजिंग का वेश धारण किया हुआ कपलिंग है।
  • कम-से-कम एक बार (at-least-once) डिलीवरी के लिए डिज़ाइन करें। बिल्कुल-एक-बार (exactly-once) डिलीवरी एक मिथक है। हर उपभोक्ता को इडमपोटेंट बनाएँ ताकि डुप्लिकेट हानिरहित हों।
  • ऑर्डर एक ऐसी गारंटी है जिसकी आप कीमत चुकाते हैं। आपको एक पार्टीशन के भीतर ऑर्डरिंग मिलती है, पूरे टॉपिक में नहीं। पार्टीशन कुंजियाँ सोच-समझकर चुनें।
  • स्कीमा ही अनुबंध है। एक इवेंट का आकार एक सार्वजनिक इंटरफ़ेस है; इसे उतनी ही सावधानी से विकसित करें जितनी आप एक प्रकाशित API के साथ करेंगे।
  • अतुल्यकालिक होने का मतलब अनवलोकनीय (unobservable) होना नहीं है। यदि आप एक संदेश को अंत तक अनुसरण नहीं कर सकते, तो आप सिस्टम को संचालित नहीं कर सकते।
  • जटिलता अर्जित की जानी चाहिए। इवेंट सोर्सिंग, CQRS, और सागा शक्तिशाली और महँगे हैं; इनका सहारा तब लें जब समस्या इनकी माँग करे, डिफ़ॉल्ट रूप से नहीं।

सिफारिशें

कुछ भी बनाने से पहले इवेंट, कमांड और संदेशों में अंतर करें

ये तीन शब्द अक्सर एक-दूसरे के स्थान पर उपयोग किए जाते हैं, और यह भ्रम वास्तविक डिज़ाइन गलतियाँ पैदा करता है। एक कमांड कुछ करने का अनुरोध है (“CapturePayment”), जो एक हैंडलर की ओर निर्देशित है, और इसे अस्वीकार किया जा सकता है। एक इवेंट एक सूचना है कि कुछ पहले ही हो चुका है (“PaymentCaptured”), जो रुचि रखने वाले किसी को भी प्रसारित की जाती है, और इसे अस्वीकार नहीं किया जा सकता क्योंकि तथ्य पहले से ही सत्य है। एक संदेश (message) वह तटस्थ लिफ़ाफ़ा है जो इनमें से किसी को भी तार पर ले जाता है। यह अंतर कपलिंग को आकार देता है: कमांड भेजने वाले को एक विशिष्ट प्राप्तकर्ता और परिणाम से जोड़ते हैं, जबकि इवेंट यह नियंत्रण छोड़ देते हैं कि आगे क्या होता है। अपने इवेंट के नाम भूतकाल में रखें, और जब आप खुद को एक ऐसा “इवेंट” प्रकाशित करते हुए पाएँ जिसका वास्तव में मतलब है “कृपया यह विशिष्ट काम करो,” तो आपने एक कमांड को छद्म वेश में लिखा है।

कतारों (queues), लॉग और publish/subscribe को जानबूझकर चुनें

सारी मैसेजिंग एक ही आकार की नहीं होती, और गलत को चुनना एक सामान्य शुरुआती गलती है। एक मैसेज कतार (queue) हर संदेश को एक उपभोक्ता तक पहुँचाती है और आम तौर पर प्रोसेस होने के बाद उसे हटा देती है, जो कार्य वितरण में फिट बैठती है: कई वर्कर कार्य खींच रहे हैं, प्रत्येक एक बार किया गया। एक टिकाऊ इवेंट लॉग (एक स्ट्रीम) इवेंट को क्रम में रखता है और कई स्वतंत्र उपभोक्ताओं को अपनी गति से पढ़ने देता है, किसी भी बिंदु से इतिहास को रीप्ले करते हुए, जो इवेंट वितरण और ऑडिट में फिट बैठता है। Publish/subscribe में प्रोड्यूसर एक टॉपिक पर प्रकाशित करते हैं और कई सब्सक्राइबर में से हर एक को अपनी खुद की प्रति मिलती है। व्यावहारिक नियम: यदि संदेश एक ऐसा कार्य है जिसे एक वर्कर को पूरा करना चाहिए, तो एक कतार का सहारा लें; यदि यह एक ऐसा तथ्य है जिसकी परवाह कई पक्षों को अभी या बाद में हो सकती है, तो एक टिकाऊ लॉग का सहारा लें, जो आपको रिकवरी और नए उपभोक्ताओं को शामिल करने के लिए रीप्ले भी देता है। यह देखने के लिए कि ये विकल्प आपकी डेटा स्टोरेज रणनीति के साथ कैसे परस्पर क्रिया करते हैं, अध्याय 3.4 देखें।

स्वायत्तता के लिए कोरियोग्राफी को प्राथमिकता दें, नियंत्रण के लिए ऑर्केस्ट्रेशन को

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

इवेंट सोर्सिंग और CQRS का सहारा तभी लें जब वे इसके लायक हों

इवेंट सोर्सिंग स्थिति को एक वर्तमान स्नैपशॉट के बजाय जिसे आप ओवरराइट करते हैं, इवेंट के एक एपेंड-ओनली अनुक्रम के रूप में संग्रहीत करती है, और आप उन्हें रीप्ले करके वर्तमान स्थिति का पुनर्निर्माण करते हैं। फ़ायदा एक सटीक ऑडिट ट्रेल, किसी भी पिछली स्थिति को फिर से बनाने की क्षमता, और कालिक (temporal) क्वेरी हैं; लागत यह है कि आप इवेंट स्कीमा को हमेशा के लिए वर्जन करते हैं, रीप्ले और स्नैपशॉट को संभालते हैं, और एक ऐसा मानसिक मॉडल रखते हैं जिसका अधिकांश डेवलपर्स ने कभी उपयोग नहीं किया। CQRS (कमांड क्वेरी रिस्पॉन्सिबिलिटी सेग्रीगेशन) राइट मॉडल को एक या अधिक रीड मॉडल से अलग करता है ताकि रीड और राइट स्वतंत्र रूप से स्केल और विकसित हो सकें; यह इवेंट सोर्सिंग के साथ स्वाभाविक रूप से जुड़ता है लेकिन इसकी आवश्यकता नहीं है। दोनों उन डोमेन में चमकते हैं जिनकी वास्तविक ऑडिट, अनुपालन, या जटिल-क्वेरी आवश्यकताएँ हैं, यही कारण है कि विनियमित वित्त और सरकार इन्हें परेशानी के लायक पाते हैं। एक साधारण create-read-update-delete सेवा के लिए ये आकस्मिक जटिलता हैं जिनका आपको पछतावा होगा, इसलिए इन्हें अपने डोमेन के उस हिस्से पर लागू करें जिसे इनकी आवश्यकता है, प्रतिक्रियावश पूरे सिस्टम पर नहीं।

दो-चरण कमिट (two-phase commit) के बजाय सागा के साथ वितरित लेनदेन प्रबंधित करें

आप आम तौर पर कई सेवाओं और डेटाबेस के चारों ओर एक परमाणु लेनदेन नहीं लपेट सकते। वितरित टू-फेज़ कमिट नेटवर्क पर लॉक रखता है, उपलब्धता कम करता है, और खराब तरीके से स्केल करता है, इसलिए यह एक इवेंट-संचालित सिस्टम में शायद ही कभी फिट बैठता है। सागा पैटर्न इसकी जगह लेता है: लेनदेन को स्थानीय लेनदेन के एक अनुक्रम के रूप में मॉडल करें, प्रत्येक एक इवेंट उत्सर्जित करता है जो अगले को ट्रिगर करता है, और प्रत्येक चरण को एक क्षतिपूर्ति क्रिया (compensating action) दें जो बाद का कोई चरण विफल होने पर उसे पूर्ववत करता है। यदि “इन्वेंटरी आरक्षित करें” सफल होता है लेकिन “कार्ड चार्ज करें” विफल हो जाता है, तो एक क्षतिपूर्ति इन्वेंटरी को मुक्त कर देती है। सागा को कोरियोग्राफ या ऑर्केस्ट्रेट किया जा सकता है, और ऑर्केस्ट्रेशन आम तौर पर हर उस चीज़ के लिए जीतता है जिसकी आपको निगरानी करनी चाहिए। क्योंकि सागा अंतिम संगति (eventual consistency) को अपनाते हैं, सिस्टम अभिसरित होने से पहले मध्यवर्ती स्थितियों (“आरक्षित लेकिन भुगतान नहीं किया गया”) से गुज़रता है, इसलिए अपने उपयोगकर्ता अनुभव और ऑडिट ट्रेल को इस तरह डिज़ाइन करें कि वह “प्रगति में” और “क्षतिपूर्ति की गई” स्थितियों को ईमानदारी से दिखाए। अध्याय 3.3 वितरित-प्रणाली के कोण से इसी क्षेत्र को कवर करता है।

कम-से-कम एक बार डिलीवरी के लिए डिज़ाइन करें और उपभोक्ताओं को इडमपोटेंट बनाएँ

संदेश प्रणालियाँ विफलताओं में वास्तव में बिल्कुल-एक-बार डिलीवर नहीं कर सकतीं, क्योंकि “मैंने इसे प्रोसेस किया” कहने वाली पावती स्वयं खो सकती है, जिससे पुनर्वितरण बाध्य हो जाता है। आप जो हासिल कर सकते हैं वह है इडमपोटेंट प्रोसेसिंग के साथ कम-से-कम-एक-बार डिलीवरी, जो बिल्कुल-एक-बार प्रभाव उत्पन्न करती है। इडमपोटेंस का अर्थ है कि एक ही इवेंट को दो बार प्रोसेस करना उतना ही परिणाम छोड़ता है जितना इसे एक बार प्रोसेस करना; प्रत्येक इवेंट पर एक इडमपोटेंसी कुंजी और आपने पहले से क्या संभाला है इसका एक रिकॉर्ड रखकर वहाँ पहुँचें, ताकि एक डुप्लिकेट पहचाना जाए और छोड़ दिया जाए। कम-से-कम एक बार नहीं (at-most-once) डिलीवरी (फायर एंड फॉरगेट, कोई पुनर्वितरण नहीं) सरल है लेकिन चुपचाप संदेश खो देती है, इसलिए इसे उस डेटा के लिए आरक्षित रखें जिसे खोना आप वहन कर सकते हैं। कुछ विक्रेता जिस “बिल्कुल-एक-बार” लेबल का विज्ञापन करते हैं उसे संदेह के साथ मानें: इसका आम तौर पर मतलब विशिष्ट शर्तों के तहत एक सिस्टम की सीमा के भीतर बिल्कुल-एक-बार होता है, अंत-से-अंत गारंटी नहीं जिसका यह वाक्यांश दावा करता है।

पार्टीशन के साथ ऑर्डरिंग को नियंत्रित करें, और अपने उपभोक्ता समूहों को जानें

ऑर्डरिंग वैश्विक और मुफ़्त नहीं है; यह स्थानीय और भुगतान की गई है। एक स्ट्रीम को पार्टीशन में विभाजित किया जाता है, और आपको एक पार्टीशन के भीतर ऑर्डरिंग मिलती है, पूरे टॉपिक में नहीं। इवेंट एक पार्टीशन कुंजी के अनुसार एक पार्टीशन में रूट होते हैं, इसलिए वह कुंजी चुनना यह नियंत्रित करने का तरीका है कि क्या क्रमबद्ध रहता है: ग्राहक ID से कुंजी बनाएँ और एक ग्राहक के इवेंट एक-दूसरे के सापेक्ष क्रम में रहते हैं, जबकि अलग-अलग ग्राहक समानांतर में प्रोसेस होते हैं। उपभोक्ता समूह (consumer groups) वर्करों के एक समूह को एक टॉपिक के पार्टीशन साझा करने देते हैं, प्रत्येक पार्टीशन एक वर्कर द्वारा संभाला जाता है, जो थ्रूपुट को स्केल करते हुए प्रति-पार्टीशन ऑर्डर को संरक्षित रखने का तरीका है; यह वह जगह है जहाँ स्केलेबिलिटी शुद्धता से मिलती है, जो अध्याय 3.5 से जुड़ती है। एक पार्टीशन कुंजी चुनें जो आपकी वास्तविक ऑर्डरिंग आवश्यकता को दर्शाती है और लोड को समान रूप से फैलाती है, क्योंकि एक ऐसी कुंजी जो अधिकांश ट्रैफ़िक को एक पार्टीशन में फ़नल कर देती है, एक हॉट स्पॉट बनाती है जिसे कोई भी संख्या में वर्कर राहत नहीं दे सकते।

स्कीमा को रजिस्ट्री और विकास नियमों के साथ अनुबंध के रूप में मानें

एक इवेंट की संरचना एक प्रकाशित इंटरफ़ेस है जिसका उपभोग उन टीमों द्वारा किया जाता है जिनसे आप शायद कभी नहीं मिलेंगे, इसलिए इसे लापरवाही से बदलना उन्हें दूर से तोड़ देता है। अपने इवेंट स्कीमा को एक स्कीमा रजिस्ट्री में रखें, एक साझा कैटलॉग जो प्रत्येक स्कीमा को संग्रहीत करता है और जब कोई प्रोड्यूसर किसी को बदलने की कोशिश करता है तो संगतता नियम लागू करता है। एक स्पष्ट नीति अपनाएँ: पीछे-संगत (backward-compatible) बदलाव (एक वैकल्पिक फ़ील्ड जोड़ना) की अनुमति है; तोड़ने वाले बदलाव (एक फ़ील्ड हटाना, टाइप बदलना, नाम बदलना) को एक नए स्कीमा वर्जन और एक माइग्रेशन योजना की आवश्यकता है। यह प्रोड्यूसर को हर उपभोक्ता में समकालिक डिप्लॉय के बिना विकसित होने देता है, जो पूरा कारण है कि आपने इवेंट चुने। अध्याय 2.3 का वही इंटरफ़ेस-वर्जनिंग अनुशासन यहाँ लागू होता है, क्योंकि एक इवेंट स्कीमा दूसरे नाम से एक API है।

ट्रांज़ैक्शनल आउटबॉक्स के साथ डिलीवरी की गारंटी दें, और विफलताओं को स्पष्ट रूप से संभालें

एक क्लासिक बग: आपकी सेवा अपने डेटाबेस में लिखती है और फिर एक इवेंट प्रकाशित करती है, और यह दोनों के बीच क्रैश हो जाती है, इसलिए डेटाबेस बदल गया लेकिन इवेंट कभी बाहर नहीं गया। ट्रांज़ैक्शनल आउटबॉक्स इसे ठीक करता है, इवेंट को उसी डेटाबेस लेनदेन में एक आउटबॉक्स टेबल में लिखकर जिसमें स्थिति परिवर्तन होता है, ताकि वे साथ-साथ कमिट हों या विफल हों; एक अलग रिले तब आउटबॉक्स को पढ़ता है और ब्रोकर को प्रकाशित करता है, अक्सर डेटाबेस लॉग को अनुसरण करने के लिए चेंज डेटा कैप्चर का उपयोग करते हुए। उपभोग विफलताओं के लिए, एक डेड लेटर कतार उन संदेशों को रखती है जो बार-बार विफल होते हैं ताकि एक पॉइज़न संदेश (एक जो कभी सफल नहीं होगा, शायद इसलिए कि यह विकृत है) कतार को अपने पीछे हमेशा के लिए अवरुद्ध न करे। बैकप्रेशर जोड़ें ताकि एक तेज़ प्रोड्यूसर एक धीमे उपभोक्ता को अभिभूत न कर सके: अपनी कतारों को सीमित करें, और उनके भर जाने पर मेमोरी समाप्त करने के बजाय धीमा करें या लोड को हटाएँ। ये चार तंत्र एक डेमो को एक ऐसे सिस्टम से अलग करते हैं जिसे आप रात 3 बजे चला सकते हैं।

अतुल्यकालिक प्रवाहों को अंत-से-अंत अवलोकनीय बनाएँ

इवेंट-संचालित बनने की सबसे कठिन लागत यह है कि एक ही व्यावसायिक क्रिया अब प्रोड्यूसर, ब्रोकर और उपभोक्ताओं में बिखर जाती है, बिना किसी कॉल स्टैक के जो उन्हें जोड़े। हर इवेंट के माध्यम से एक सहसंबंध ID (correlation ID) प्रचारित करें ताकि आप एक तार्किक प्रवाह को हर हॉप के पार अनुसरण कर सकें, वही अनुशासन जो अध्याय 3.3 सिंक्रोनस कॉल के लिए निर्धारित करता है। उपभोक्ता लैग (consumer lag) (प्रत्येक उपभोक्ता वास्तविक समय से पढ़ने में कितना पीछे है) को एक प्रथम-श्रेणी मीट्रिक के रूप में ट्रैक करें, क्योंकि बढ़ता लैग परेशानी की आपकी सबसे शुरुआती चेतावनी है, और डेड लेटर कतार की गहराई, प्रोसेसिंग लेटेंसी और पुनर्वितरण दरों की निगरानी करें। इसके बिना, एक इवेंट जो चुपचाप उपभोग होने में विफल हो जाता है वह एक अदृश्य बग बन जाता है जो दिनों बाद गुम डेटा के रूप में सामने आता है।

ट्रेड-ऑफ़: पक्ष और विपक्ष

दृष्टिकोणपक्षविपक्ष / लागत
सिंक्रोनस रिक्वेस्ट/रिप्लाईतर्क करना सरल, तत्काल परिणाम, आसान ट्रेसिंगकड़ी कालिक कपलिंग, कैस्केडिंग विफलताएँ, सीमित स्केल
इवेंट-संचालित (लॉग पर pub/sub)डीकपलिंग, स्वतंत्र स्केलिंग, रीप्ले, ऑडिट ट्रेलअंतिम संगति, कठिन ट्रेसिंग, अधिक चलते हिस्से
मैसेज कतार (कार्य वितरण)लोड लेवलिंग, बफरिंग, बैकप्रेशर-अनुकूलप्रति संदेश एक उपभोक्ता, प्रसारण के लिए कम उपयुक्त
इवेंट सोर्सिंग + CQRSपूर्ण इतिहास, कालिक क्वेरी, रीड/राइट स्वतंत्र रूप से स्केलहमेशा के लिए स्कीमा वर्जनिंग, रीप्ले जटिलता, खड़ी सीखने की अवस्था
सागा (टू-फेज़ कमिट बनाम)स्केलेबल, उपलब्ध, कोई वितरित लॉक नहींअंतिम संगति, क्षतिपूर्ति तर्क, तर्क करना कठिन

केंद्रीय तनाव डीकपलिंग और बोधगम्यता (comprehensibility) के बीच है। आप जो भी इवेंट जोड़ते हैं वह प्रोड्यूसर और उपभोक्ता के बीच कपलिंग को ढीला करता है, टीम की स्वायत्तता और स्वतंत्र स्केलिंग खरीदता है, और साथ ही यह उस कहानी की एक पंक्ति हटा देता है जिसे एक सिंक्रोनस कॉल स्पष्ट रूप से बताती: प्रवाह उभरता हुआ बन जाता है, किसी एक फ़ाइल में नहीं बल्कि परस्पर क्रियाओं में रहता है। इसे चयनात्मक होकर हल करें: इवेंट का उपयोग वहाँ करें जहाँ डीकपलिंग वास्तव में लाभदायक है, जैसे टीम की सीमाओं के पार एकीकरण, कई उपभोक्ताओं में फैन-आउट, लोड स्पाइक की बफरिंग, और ऑडिट। सिंक्रोनस कॉल वहाँ रखें जहाँ आपको तत्काल उत्तर और एक सरल मानसिक मॉडल की आवश्यकता है, जैसे किसी पृष्ठ को प्रस्तुत करने के लिए डेटा पढ़ना। जिस विफलता मोड से बचना है वह है हर आंतरिक फ़ंक्शन कॉल को एक इवेंट में बदल देना और उसे आर्किटेक्चर कहना, वही आर्किटेक्चरल निर्णय जो अध्याय 3.2 हर उस पैटर्न से माँगता है जिसे आप अपनाते हैं।

अपनी टीम के साथ चर्चा करने के लिए प्रश्न

  1. इस विशिष्ट परस्पर क्रिया के लिए, क्या हमें वास्तव में एक इवेंट की आवश्यकता है, या एक सिंक्रोनस कॉल स्पष्ट और सुरक्षित होगी? इस प्रश्न को छोड़ देना ही है कि कैसे एक सिस्टम आकस्मिक जटिलता जमा करता है। ईमानदार परीक्षण यह है कि क्या प्रोड्यूसर को अभी एक परिणाम वापस चाहिए (एक कॉल) या एक तथ्य की घोषणा कर रहा है जिस पर अन्य अपने समय पर प्रतिक्रिया दे सकते हैं (एक इवेंट)। विशिष्ट परस्पर क्रिया लाएँ, एक सामान्य पसंद नहीं, और पूछें कि आप क्या डीकपलिंग प्राप्त करते हैं और क्या ट्रेसिंग स्पष्टता खोते हैं। यदि कॉलर “इवेंट” को प्रोसेस होने की प्रतीक्षा करते हुए अवरुद्ध होता है, तो आपने एक धीमी, डीबग करने में कठिन सिंक्रोनस कॉल बनाई है और इस विशेषाधिकार के लिए अतिरिक्त भुगतान किया है। आंतरिक, समान-टीम, अभी-उत्तर-चाहिए परस्पर क्रियाओं के लिए डिफ़ॉल्ट एक सीधा कॉल होना चाहिए; इवेंट को वहाँ आरक्षित रखें जहाँ ढीली कपलिंग अपनी लागत अर्जित करती है।

  2. जब कोई उपभोक्ता एक ही इवेंट को दो बार प्राप्त करता है तो क्या होता है, और क्या हमने वास्तव में इसका परीक्षण किया है? कम-से-कम-एक-बार डिलीवरी की गारंटी है कि डुप्लिकेट होंगे, इसलिए हर उपभोक्ता को इडमपोटेंट होना चाहिए, फिर भी इडमपोटेंसी का दावा करना आसान है और इसे गलत करना भी आसान है। एक वास्तविक उपभोक्ता के माध्यम से चलें और ठीक-ठीक ट्रेस करें कि दूसरा वितरण कैसे पहचाना और निष्क्रिय किया जाता है, चाहे एक इडमपोटेंसी कुंजी से, एक संसाधित-इवेंट लॉग से, या स्वाभाविक रूप से इडमपोटेंट ऑपरेशन से। एक वास्तविक परीक्षण के परिणाम लाएँ जहाँ आप एक बैच को पुनर्वितरित करते हैं और पुष्टि करते हैं कि कोई डबल चार्ज, डुप्लिकेट रिकॉर्ड, या दोहराई गई सूचनाएँ नहीं हैं। उन साइड इफेक्ट्स पर विशेष ध्यान दें जो आपके डेटाबेस से बाहर निकलते हैं, जैसे ईमेल, भुगतान, और तीसरे-पक्ष के कॉल, क्योंकि यही वह जगह है जहाँ गैर-इडमपोटेंट बग ग्राहकों को सीधे नुकसान पहुँचाते हैं। यदि आपकी टीम किसी ऐसे परीक्षण की ओर इशारा नहीं कर सकती जो डुप्लिकेट-सुरक्षा साबित करता है, तो मान लें कि आप डुप्लिकेट-सुरक्षित नहीं हैं।

  3. जब उत्पादन में एक इवेंट प्रवाह टूटता है, तो हमें पता चलने में कितना समय लगता है, और क्या हम एक संदेश को अंत तक ट्रेस कर सकते हैं? अतुल्यकालिक विफलताएँ शांत होती हैं, इसलिए एक उपभोक्ता जो चुपचाप प्रोसेस करना बंद कर देता है वह तब तक ध्यान में नहीं आ सकता जब तक गुम डेटा एक ग्राहक शिकायत या एक ऑडिट अंतराल नहीं बन जाता। पूछें कि आपका सबसे शुरुआती संकेत क्या है, और क्या आप उपभोक्ता लैग और डेड लेटर कतार की गहराई को अलर्टिंग मीट्रिक के रूप में निगरानी करते हैं न कि ऐसे डैशबोर्ड के रूप में जिन्हें कोई नहीं देखता। एक वास्तविक घटना या एक गेम-डे अभ्यास लाएँ और यह देखें कि प्रोड्यूसर, ब्रोकर और हर उपभोक्ता में एक सहसंबंध ID का अनुसरण करने में कितना समय लगता है। यदि उत्तर है “हम कई सेवाओं को ग्रेप करते हैं और अनुमान लगाते हैं,” तो आपकी अवलोकनीयता उस जटिलता के लिए तैयार नहीं है जो आपने अपनाई है। विनियमित क्षेत्रों में, यह पुनर्निर्माण करने में सक्षम होना कि एक संदेश ठीक-ठीक कैसे आगे बढ़ा, अक्सर एक अनुपालन आवश्यकता है, एक सुखद बात नहीं।

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

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

  6. ब्रोकर या इवेंट लॉग कौन चलाता है, और क्या हमने इसे संचालित करने की वास्तविक लागत की गणना एक प्रबंधित विकल्प के मुकाबले की है? मैसेजिंग बैकबोन कोई मुफ़्त इन्फ्रास्ट्रक्चर नहीं है जो एक बार आप इसे डायग्राम पर खींचते हैं तो दिखाई देता है: कोई इसे पैच करता है, इसके पार्टीशन को स्केल करता है, रिटेंशन को ट्यून करता है, रात 3 बजे पेज करने पर प्रतिक्रिया देता है, और इसकी क्षमता और इसकी विफलता मोड का मालिक है। एक ओपन-सोर्स ब्रोकर को स्वयं होस्ट करने और एक प्रबंधित सेवा खरीदने के बीच जानबूझकर निर्णय लें, नियंत्रण और डेटा निवास को परिचालन बोझ और लाइसेंस लागत के मुकाबले तौलते हुए, और ईमानदार रहें कि क्या आपकी टीम के पास एक वितरित लॉग को अच्छी तरह चलाने की गहराई है। कुल स्वामित्व लागत लाएँ: ऑन-कॉल लोड, आवश्यक विशेषज्ञ कौशल, रिटेंशन और स्टोरेज बिल, और एक ब्रोकर आउटेज हर निर्भर प्रवाह के साथ क्या करता है। एक उद्यम के लिए उत्तर एक प्लेटफ़ॉर्म टीम के जनादेश को आकार देता है, और एक सरकारी निकाय के लिए खरीद नियम, डेटा-संप्रभुता आवश्यकताएँ, और विक्रेता लॉक-इन से बचने की एक कठोर आवश्यकता सबसे सस्ते विकल्प को खारिज कर सकती है, इसलिए इन बाधाओं को उजागर करें इससे पहले कि आप एक ऐसी तकनीक के लिए प्रतिबद्ध हों जिसे आप एक दशक तक चलाएँगे।

क्षेत्र लेंस

स्टार्टअप। आपका सबसे दुर्लभ संसाधन इंजीनियरिंग ध्यान है, इसलिए तब तक सिंक्रोनस रहें जब तक फैन-आउट वास्तव में दर्द न दे। जब तीन चीज़ों को एक क्रिया पर प्रतिक्रिया देने की आवश्यकता हो, तो अपना खुद का ब्रोकर क्लस्टर खड़ा करने के बजाय एक प्रबंधित कतार या लॉग में एक एकल इवेंट (जैसे “OrderPlaced”) प्रकाशित करें, और भुगतान और किसी भी ऐसी चीज़ को जिससे आपको तत्काल उत्तर चाहिए, सीधे कॉल के रूप में रखें। परिष्कृत दिखने के लिए इवेंट सोर्सिंग, CQRS, या सागा को न अपनाएँ; वह जटिलता एक छोटी टीम से आगे निकल जाएगी और उसी पुनरावृत्ति को धीमा कर देगी जिस पर आप प्रतिस्पर्धा कर रहे हैं।

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

उद्यम। आपकी समस्या कई टीमों में एकीकरण लागत है, इसलिए फ़ायदा एक गवर्न्ड साझा प्लेटफ़ॉर्म है: एक टिकाऊ इवेंट लॉग, एक लागू संगतता नीति वाली स्कीमा रजिस्ट्री, स्पष्ट टॉपिक स्वामित्व, और मानक इडमपोटेंसी और आउटबॉक्स पैटर्न ताकि हर टीम इन्हें फिर से आविष्कार न करे। यह वह सेटिंग है जहाँ एक भंगुर एंटरप्राइज़ सर्विस बस या पॉइंट-टू-पॉइंट लिंक के जाल को बदलना वास्तविक बचत में संयोजित होता है, और जहाँ दृश्यमान स्थिति वाले ऑर्केस्ट्रेटेड सागा ऑपरेशन स्टाफ को बहु-चरण प्रक्रियाओं को प्रबंधित करने देते हैं। अवलोकनीयता और स्कीमा-गवर्नेंस निवेश को स्पष्ट रूप से बजट करें, क्योंकि इस पैमाने पर एक चुपचाप उपभोक्ता विफलता दर्जनों सिस्टमों में गुम डेटा बन जाती है।

सरकार। एक टिकाऊ, क्रमबद्ध इवेंट लॉग एक ऑडिट और पारदर्शिता संपत्ति है: यह “यह निर्णय इस तरह क्यों आया” का उत्तर तथ्यों के एक अपरिवर्तनीय अनुक्रम के साथ देता है, इसलिए जहाँ जवाबदेही की माँग हो वहाँ इवेंट सोर्सिंग का सहारा लें। अंतर-एजेंसी डेटा साझाकरण को एक स्थिर इवेंट ID पर डिडुप्लिकेशन के साथ कम-से-कम-एक-बार डिलीवरी की आवश्यकता है ताकि एक पुनर्वितरित रिकॉर्ड कभी डुप्लिकेट केस न बनाए, और खरीद को डेटा संप्रभुता, एक ब्रोकर की सीमाओं के प्रकटीकरण, और लॉक-इन के मुकाबले पोर्टेबिलिटी को तौलना चाहिए। जहाँ उपयुक्त हो, प्रकाशित करें कि प्रवाह कैसे काम करता है और एक नागरिक एक स्वचालित परिणाम को कैसे चुनौती दे सकता है, और इवेंट लॉग को उस रक्षात्मक रिकॉर्ड के रूप में रखें जिसका निरीक्षण करने वाले निकाय निरीक्षण करने के लिए कहेंगे।

उदाहरण

स्टार्टअप। एक छोटा ई-कॉमर्स स्टार्टअप एक सिंक्रोनस प्रवाह से शुरू होता है: चेकआउट भुगतान सेवा को कॉल करता है और प्रतीक्षा करता है। जैसे-जैसे यह बढ़ता है, यह ऑर्डर पुष्टिकरण ईमेल, इन्वेंटरी अपडेट, और एक लॉयल्टी प्रोग्राम चाहता है जो खरीद पर प्रतिक्रिया दे, और चेकआउट के भीतर प्रत्येक को एक और सिंक्रोनस कॉल के रूप में जोड़ना चेकआउट को धीमा और भंगुर बना देता है। टीम एक टिकाऊ लॉग में एक एकल “OrderPlaced” इवेंट प्रकाशित करती है और तीन स्वतंत्र उपभोक्ताओं को प्रतिक्रिया देने देती है, इसलिए चेकआउट फिर से तेज़ है और बाद में एक चौथी प्रतिक्रिया जोड़ने के लिए इसमें कोई बदलाव नहीं चाहिए। वे भुगतान कैप्चर को सिंक्रोनस रखते हैं, क्योंकि ऑर्डर की पुष्टि करने से पहले उन्हें हाँ-या-नहीं उत्तर चाहिए, जो ठीक वही रेखा है जो उनके आकार पर खींचनी सही है।

उद्यम। एक वैश्विक बीमाकर्ता पॉइंट-टू-पॉइंट एकीकरणों और एक पुराने एंटरप्राइज़ सर्विस बस (ESB) में डूब रहा है, एक केंद्रीय हब जिससे हर सिस्टम रूट होता है और जो एक बाधा और एकल विफलता बिंदु बन गया है। यह एक टिकाऊ इवेंट लॉग में माइग्रेट करता है जहाँ प्रत्येक डोमेन अपने तथ्य प्रकाशित करता है (पॉलिसी जारी, दावा दायर, भुगतान किया गया) और उपभोग करने वाली टीमें अपनी जरूरत की चीज़ों को सब्सक्राइब करती हैं। एक क्लेम सागा, इस तरह ऑर्केस्ट्रेटेड कि ऑपरेशन स्टाफ हर क्लेम की स्थिति देख सके, विफल होने वाले चरणों के लिए क्षतिपूर्ति के साथ बहु-चरण निपटान को समन्वित करता है। एक स्कीमा रजिस्ट्री पॉलिसी टीम को चालीस उपभोग करने वाले सिस्टमों में समकालिक डिप्लॉय के बिना अपने इवेंट विकसित करने देती है, ठीक वही भंगुरता जो पुराने ESB ने थोपी थी।

सरकार। एक राष्ट्रीय कर एजेंसी को नागरिकों और ऑडिटरों को “मेरा आकलन इस तरह क्यों आया” का एक रक्षात्मक उत्तर देना चाहिए। यह मूल्यांकन डोमेन को इवेंट सोर्सिंग के साथ मॉडल करती है, इसलिए हर बदलाव एक क्रमबद्ध लॉग में एक अपरिवर्तनीय इवेंट है और वर्तमान मूल्यांकन उन इवेंट का एक रीप्ले है; जब कोई नागरिक किसी आँकड़े पर विवाद करता है, तो एक केसवर्कर किसी भी पिछली तारीख पर सटीक स्थिति का पुनर्निर्माण करता है और उन तथ्यों का क्रम दिखाता है जिसने इसे उत्पन्न किया। अंतर-एजेंसी डेटा साझाकरण कम-से-कम-एक-बार डिलीवरी के साथ टिकाऊ टॉपिक पर चलता है, और प्रत्येक एजेंसी का उपभोक्ता एक इवेंट ID पर डिडुप्लिकेट करता है ताकि एक पुनर्वितरित रिकॉर्ड कभी डुप्लिकेट केस न बनाए। इवेंट लॉग उस ऑडिट ट्रेल के रूप में दोगुना काम करता है जिसकी निरीक्षण निकायों को आवश्यकता है, एक अनुपालन दायित्व को डिज़ाइन का एक उप-उत्पाद बनाते हुए।

व्यावसायिक मामला: प्रेरणाएँ, ROI, और TCO

इवेंट-संचालित आर्किटेक्चर पर रिटर्न एक चीज़ से हावी है: समय के साथ एकीकरण की लागत। पॉइंट-टू-पॉइंट एकीकरण उस लागत को कनेक्शन की संख्या के साथ बढ़ाता है, जो सिस्टम की संख्या से तेज़ी से बढ़ती है, इसलिए एकीकरण वह कर बन जाता है जो आपकी डिलीवरी क्षमता को खा जाता है। इवेंट इसे समतल करते हैं, क्योंकि टीमें तथ्यों की एक साझा स्ट्रीम के माध्यम से एकीकृत होती हैं, एक नया उपभोक्ता सब्सक्राइब करके शामिल होता है, और प्रोड्यूसर एक वर्जन वाले स्कीमा के पीछे विकसित होते हैं, इसलिए अगले एकीकरण की सीमांत लागत तेज़ी से गिरती है। यही नेतृत्व को बताने के लिए मुख्य ROI कहानी है: कच्चा प्रदर्शन नहीं, बल्कि कई टीमों में बदलाव की लागत में संयोजित कमी।

कुल स्वामित्व लागत को ईमानदारी से नाम दें ताकि आप पर विश्वास किया जाए। आप चलाने के लिए ब्रोकर इन्फ्रास्ट्रक्चर, बनाए रखने के लिए स्कीमा गवर्नेंस, और एक खड़ी परिचालन सीखने की अवस्था लेते हैं, क्योंकि अतुल्यकालिक सिस्टम वास्तव में डीबग करने में कठिन हैं, इसलिए अवलोकनीयता निवेश को पहले से बजट करें। इन्हें उस लागत के मुकाबले तौलें जो इवेंट को नहीं अपनाने की है जहाँ वे फिट बैठते हैं: एक जड़ हो चुकी एकीकरण परत जहाँ हर बदलाव एक बहु-टीम समन्वय परियोजना है, एक पुराना ESB जो एक ऐसी बाधा बन गया है जिसे कोई छूने की हिम्मत नहीं करता, और पुरानी क्षमताओं को बाधित किए बिना नई क्षमताएँ जोड़ने में असमर्थता। भंगुर पॉइंट-टू-पॉइंट वायरिंग बदलने वाले उद्यम और टिकाऊ ऑडिट ट्रेल बनाने वाली सरकार के लिए, फ़ायदा सबसे मज़बूत है जहाँ ऑडिट और डीकपलिंग आवश्यकताएँ वास्तविक हैं। जहाँ वे आवश्यकताएँ अनुपस्थित हैं, ईमानदार उत्तर यह है कि एक सरल सिंक्रोनस डिज़ाइन की TCO कम है, और आपको यह कहना चाहिए।

एंटी-पैटर्न और नुकसान

  • छद्म वेश में वितरित मोनोलिथ। ऐसी सेवाएँ जिन्हें सभी को एक साथ डिप्लॉय होना चाहिए और एक-दूसरे के आंतरिक इवेंट पर निर्भर होना चाहिए। आपने एक ब्रोकर जोड़ा लेकिन कपलिंग बनाए रखा, इसलिए आपके पास दोनों शैलियों के नुकसान हैं।
  • कमांड के रूप में इवेंट। ऐसे “इवेंट” प्रकाशित करना जिनका वास्तव में मतलब है “कृपया मेरे लिए यह विशिष्ट काम करो,” अतिरिक्त लेटेंसी और बदतर ट्रेसेबिलिटी के साथ कड़ी कपलिंग को फिर से बनाना।
  • बिल्कुल-एक-बार डिलीवरी मान लेना। ऐसे उपभोक्ता जो टूट जाते हैं, दोगुना चार्ज करते हैं, या रिकॉर्ड को डुप्लिकेट कर देते हैं जब ब्रोकर अनिवार्य रूप से एक संदेश को पुनर्वितरित करता है।
  • हर चीज़ की इवेंट सोर्सिंग। सरल create-read-update-delete डोमेन में इवेंट सोर्सिंग और CQRS लागू करना जिन्हें कभी इतिहास की आवश्यकता नहीं थी, बिना किसी लाभ के खड़ी जटिलता खरीदना।
  • कोई स्कीमा गवर्नेंस नहीं। प्रोड्यूसर स्वतंत्र रूप से इवेंट आकार बदलते हैं, बिना संगतता जाँच के डाउनस्ट्रीम उपभोक्ताओं को दूर से तोड़ते हुए।
  • आउटबॉक्स को नज़रअंदाज़ करना। डेटाबेस में लिखना और एक इवेंट प्रकाशित करना दो अलग चरणों के रूप में, इसलिए उनके बीच एक क्रैश चुपचाप इवेंट खो देता है या फैंटम इवेंट उत्सर्जित करता है।
  • कोई डेड लेटर हैंडलिंग नहीं। एक एकल पॉइज़न संदेश एक पार्टीशन को अवरुद्ध कर देता है, या विफल संदेश बिना किसी कतार के गायब हो जाते हैं जो उन्हें पकड़े और जाँचे।
  • अदृश्य प्रवाह। बिना सहसंबंध ID, बिना उपभोक्ता-लैग अलर्ट, और बिना ट्रेसिंग के अतुल्यकालिक प्रोसेसिंग, इसलिए विफलताएँ तब तक शांत रहती हैं जब तक वे गुम डेटा नहीं बन जातीं।

परिपक्वता मॉडल

  • स्तर 1, आरंभ: एकीकरण तदर्थ पॉइंट-टू-पॉइंट कॉल है, या एक ब्रोकर मौजूद है लेकिन सिंक्रोनस रिक्वेस्ट/रिप्लाई की तरह उपयोग किया जाता है। डुप्लिकेट उपभोक्ताओं को तोड़ते हैं, कोई स्कीमा अनुशासन या क्रॉस-हॉप ट्रेसिंग नहीं है, और विफल संदेश चुपचाप गायब हो जाते हैं।
  • स्तर 2, विकास: कुछ प्रवाहों के लिए एक ब्रोकर या लॉग वास्तविक उपयोग में है, और कुछ टीमों के पास बुनियादी प्रथाएँ हैं: उपभोक्ता इडमपोटेंट बन रहे हैं और डेड लेटर कतारें कुछ विफलताओं को पकड़ती हैं। लेकिन दृष्टिकोण टीमों में असंगत है, इवेंट और कमांड अभी भी मिश्रित हैं, स्कीमा अनौपचारिक समझौते से बदलती हैं, और अवलोकनीयता पतली है।
  • स्तर 3, मानकीकरण: पूरे संगठन में इवेंट, कमांड और संदेशों को जानबूझकर अलग किया जाता है। उपभोक्ता मानक रूप से इडमपोटेंट हैं, स्कीमा एक दस्तावेज़ीकृत और लागू संगतता नीति के साथ रजिस्ट्री में रहती हैं, और ट्रांज़ैक्शनल आउटबॉक्स डिलीवरी की गारंटी देता है। क्षतिपूर्ति वाले सागा बहु-सेवा लेनदेन को संभालते हैं, सहसंबंध ID हर हॉप में प्रचारित होते हैं, और इन पैटर्न को लिखा जाता है और लगातार लागू किया जाता है न कि हर टीम पर छोड़ा जाता है।
  • स्तर 4, प्रबंधन: इवेंट प्लेटफ़ॉर्म को बेसलाइन के मुकाबले डेटा के साथ मापा और नियंत्रित किया जाता है। उपभोक्ता लैग, डेड लेटर कतार की गहराई, पुनर्वितरण दरें, और प्रोसेसिंग लेटेंसी को सहमत सीमाओं के साथ अलर्टिंग मीट्रिक के रूप में ट्रैक किया जाता है, ऐसे डैशबोर्ड के रूप में नहीं जिन्हें कोई नहीं देखता; स्कीमा संगतता को स्वचालित रूप से सत्यापित किया जाता है इससे पहले कि कोई प्रोड्यूसर बदलाव शिप कर सके; रीप्ले, विफलता हैंडलिंग, और इडमपोटेंसी की एक निश्चित समय-सारणी पर जाँच की जाती है, आशा नहीं की जाती। क्या किसी दिए गए परस्पर क्रिया को एक इवेंट या सिंक्रोनस कॉल होना चाहिए इसका निर्णय साक्ष्य पर किया जाता है, और प्रत्येक ब्रोकर की क्षमता, रिटेंशन लागत, और विश्वसनीयता की लक्ष्यों के मुकाबले समीक्षा की जाती है।
  • स्तर 5, ऑर्केस्ट्रेशन: इवेंट-संचालित और सिंक्रोनस शैलियों को प्रति परस्पर क्रिया दूसरी प्रकृति के रूप में चुना जाता है, और इवेंट सोर्सिंग और CQRS को ठीक वहाँ लागू किया जाता है जहाँ ऑडिट और क्वेरी आवश्यकताएँ इन्हें उचित ठहराती हैं और कहीं नहीं। अतुल्यकालिक प्रवाह उतने ही अवलोकनीय हैं जितने सिंक्रोनस, प्लेटफ़ॉर्म निरंतर सुधरता है जैसे-जैसे आवश्यकताएँ बदलती हैं (मृत टॉपिक को सेवानिवृत्त करना, स्कीमा गवर्नेंस को विकसित करना, पार्टीशन को पुनर्संतुलित करना), और मैसेजिंग व्यापक आर्किटेक्चर और ऑडिट रणनीति के साथ एकीकृत है ताकि संगठन व्यवसाय और उसके दायित्वों के बदलने के साथ अपने इवेंट डिज़ाइन को अनुकूलित करे।

चर्चा के लिए विचार

  1. आपके वर्तमान “इवेंट” में से कौन से गुप्त रूप से कमांड हैं, और उन्हें ईमानदारी से मॉडल करके आप कौन सी कपलिंग हटाएँगे?
  2. यदि आपने कल एक पूरे दिन के इवेंट को अपने उपभोक्ताओं के माध्यम से पुनः चलाया, तो क्या टूट जाएगा, और यह आपकी इडमपोटेंसी और रीप्ले-सुरक्षा के बारे में क्या बताता है?
  3. आपके डोमेन के कौन से हिस्सों को वास्तव में इवेंट सोर्सिंग के ऑडिट ट्रेल की आवश्यकता है, और कौन से सरल स्थिति हैं जिन्हें आप सोर्सिंग करके ही जटिल बना देंगे?
  4. आप एक जोखिम भरे बिग-बैंग कटओवर के बिना एक विरासत एंटरप्राइज़ सर्विस बस या पॉइंट-टू-पॉइंट एकीकरणों के जाल से कैसे माइग्रेट करेंगे?
  5. आपकी सबसे महत्वपूर्ण बहु-सेवा प्रक्रिया के लिए, क्या यह क्षतिपूर्ति वाला एक वास्तविक ऑर्केस्ट्रेटेड सागा है, या एक उभरती हुई कोरियोग्राफी जिसे कोई एक स्थान वर्णित नहीं करता?

मुख्य निष्कर्ष

  • इवेंट-संचालित आर्किटेक्चर डीकपलिंग, स्वतंत्र स्केलिंग, रीप्ले, और ऑडिट ट्रेल खरीदता है, और इसकी कीमत बोधगम्यता और परिचालन जटिलता है, इसलिए इसे प्रति परस्पर क्रिया चुनें जहाँ लाभ वास्तविक हो।
  • इवेंट (जो तथ्य हुए), कमांड (कार्य करने के अनुरोध), और संदेश (लिफ़ाफ़ा) को अलग रखें, क्योंकि भ्रम वास्तविक कपलिंग गलतियाँ पैदा करता है।
  • कम-से-कम-एक-बार डिलीवरी के लिए डिज़ाइन करें और हर उपभोक्ता को इडमपोटेंट बनाएँ; बिल्कुल-एक-बार डिलीवरी एक मिथक है, और बिल्कुल-एक-बार प्रभाव एक इंजीनियरिंग उपलब्धि है।
  • ऑर्डरिंग प्रति पार्टीशन है, स्कीमा वे अनुबंध हैं जो एक रजिस्ट्री में रहते हैं, और आउटबॉक्स, डेड लेटर कतारें, और बैकप्रेशर वह प्लंबिंग है जो मैसेजिंग को उत्पादन-तैयार बनाती है।
  • टू-फेज़ कमिट के बजाय क्षतिपूर्ति वाले सागा का उपयोग करें, और इवेंट सोर्सिंग और CQRS का सहारा केवल वहाँ लें जहाँ ऑडिट और क्वेरी आवश्यकताएँ उनकी खड़ी लागत को उचित ठहराती हैं।
  • अतुल्यकालिक प्रवाह विफल होने पर शांत होते हैं, इसलिए सहसंबंध ID, उपभोक्ता-लैग निगरानी, और अंत-से-अंत ट्रेसिंग एक संचालन योग्य सिस्टम और एक अदृश्य सिस्टम के बीच का अंतर हैं।

संदर्भ और आगे पढ़ने के लिए

  • Martin Kleppmann, Designing Data-Intensive Applications
  • Gregor Hohpe and Bobby Woolf, Enterprise Integration Patterns
  • Chris Richardson, Microservices Patterns (सागा, ट्रांज़ैक्शनल आउटबॉक्स, CQRS)
  • Sam Newman, Building Microservices
  • Ben Stopford, Designing Event-Driven Systems
  • Adam Bellemare, Building Event-Driven Microservices
  • Vaughn Vernon, Implementing Domain-Driven Design (इवेंट सोर्सिंग और CQRS)
  • Martin Fowler, “Event Sourcing” and “CQRS” (martinfowler.com articles)
  • Hector Garcia-Molina and Kenneth Salem, “Sagas” (1987)