प्रतिनिधि इंटरव्यू विषय

बैकएंड इंटरव्यू: आप वेबहुक्स को सुरक्षित रूप से कैसे प्राप्त और प्रोसेस करते हैं?

बैकएंडकठिन
Offer.cc संपादकीय टीमप्रकाशित अपडेट किया गया

प्रश्न

एक पेमेंट इंटीग्रेशन कई प्रोवाइडर्स से वेबहुक प्राप्त करता है। पीक ट्रैफ़िक 2,000 रिक्वेस्ट प्रति सेकंड है; औसत बॉडी 10 KiB और अधिकतम 1 MiB है। प्रोवाइडर्स इवेंट्स को फिर से आज़मा (retry), डुप्लिकेट, विलंबित और रीऑर्डर कर सकते हैं। रिसीवर को 2 सेकंड के भीतर जवाब देना चाहिए, प्रामाणिकता सत्यापित करनी चाहिए, सीक्रेट रोटेशन का समर्थन करना चाहिए, और यह सुनिश्चित करना चाहिए कि स्वीकृत इवेंट न तो खोएं और न ही दो बार लागू हों। इनग्रेस, ड्यूरेबल स्वीकृति सीमा, एसिंक्रोनस प्रोसेसिंग, आइडेम्पोटेंसी, समाधान (reconciliation), विफलता प्रबंधन और परीक्षण डिज़ाइन करें।

समस्या और उपयोग के मामले (Use Cases)

रिसीवर एक अविश्वसनीय (untrusted) HTTP रिक्वेस्ट को एक ड्यूरेबल इंटरनल इवेंट में परिवर्तित करता है। सबसे कठिन हिस्सा उन स्थितियों के बीच की सीमा है। एक तेज़ 200 OK गलत है यदि इवेंट को सहेजने से पहले प्रक्रिया क्रैश हो सकती है। जवाब देने से पहले पेमेंट वर्कफ़्लो चलाना भी गलत है क्योंकि धीमी डिपेंडेंसी प्रोवाइडर रीट्रीज़ का कारण बनती है और लोड को बढ़ाती है।

इन इंटरव्यू मान्यताओं का उपयोग करें:

  • पीक ट्रैफ़िक 2,000 रिक्वेस्ट प्रति सेकंड है। औसत रॉ बॉडी 10 KiB है और अधिकतम 1 MiB है, इसलिए हेडर, रेप्लिकेशन और स्टोरेज ओवरहेड से पहले पीक पर औसत-बॉडी इनग्रेस लगभग 19.5 MiB/s है।
  • प्रोवाइडर 2 सेकंड के भीतर प्रतिक्रिया की अपेक्षा करता है। हेडरूम बनाए रखने के लिए हमारा आंतरिक लक्ष्य 500 ms p99 एक्नॉलेजमेंट (acknowledgment) है।
  • डिलीवरी कम से कम एक बार (at least once) और अव्यवस्थित (unordered) है। एक प्रोवाइडर एक ही लॉजिकल इवेंट को समवर्ती (concurrently) रूप से भेज सकता है, इसे बाद में पुनः प्रयास कर सकता है, या पहले एक नई ऑब्जेक्ट स्थिति वितरित कर सकता है।
  • एक स्वीकृत इवेंट को रिसीवर क्रैश से बचना चाहिए और अंततः एक टर्मिनल PROCESSED या FAILED स्थिति तक पहुंचना चाहिए। एक लॉजिकल इवेंट को एक ही व्यावसायिक म्यूटेशन (business mutation) को दो बार लागू नहीं करना चाहिए।
  • साइनिंग सीक्रेट बिना डाउनटाइम के रोटेट होते हैं। रिकवरी और ऑडिट के लिए रॉ पेलोड एन्क्रिप्ट किए जाते हैं और 30 दिनों के लिए बनाए रखे जाते हैं; आइडेम्पोटेंसी रिकॉर्ड कम से कम प्रोवाइडर की दस्तावेज़ीकृत रीडिलीवरी विंडो तक रहते हैं।

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

साक्षात्कारकर्ता क्या मूल्यांकन कर रहा है

पहला, साक्षात्कारकर्ता एक सटीक एक्नॉलेजमेंट अनुबंध चाहता है। 2xx का अर्थ है "इस रिसीवर ने इवेंट को ड्यूरेबल रूप से स्वीकार कर लिया है," न कि "प्रत्येक डाउनस्ट्रीम साइड इफ़ेक्ट पूरा हो गया है।" ड्यूरेबल राइट से पहले सफलता वापस करने से साइलेंट लॉस होता है। पहले से स्वीकृत डुप्लिकेट के लिए सफलता वापस करना सही है क्योंकि प्रोवाइडर पुनः प्रयास करना बंद कर सकता है।

दूसरा, वे सही क्रम में सुरक्षा चाहते हैं। रिसीवर मेथड, कंटेंट टाइप, हेडर और बॉडी साइज़ को सीमित करता है; सटीक रॉ बाइट्स को सुरक्षित रखता है; विश्वसनीय सीक्रेट वर्ज़न के साथ प्रोवाइडर-विशिष्ट सिग्नेचर को सत्यापित करता है; स्थिर समय (constant time) में MACs की तुलना करता है; और जब प्रोवाइडर इसे आपूर्ति करता है तो हस्ताक्षरित फ्रेशनेस मेटाडेटा की जांच करता है। सत्यापन से पहले JSON को पार्स और पुन: सीरियलाइज़ करने से व्हाइटस्पेस या की (key) का क्रम बदल सकता है और एक वैध सिग्नेचर अमान्य हो सकता है।

तीसरा, वे चाहते हैं कि उम्मीदवार रीप्ले की रोकथाम को रीट्री डिडुप्लिकेशन से अलग करे। एक हस्ताक्षरित टाइमस्टैम्प एक पुरानी कैप्चर की गई रिक्वेस्ट को अस्वीकार करता है। एक स्थिर प्रोवाइडर इवेंट या डिलीवरी ID एक वैध रीट्री को दो बार लागू होने से रोकती है। कुछ प्रोवाइडर्स लॉजिकल इवेंट ID को बनाए रखते हुए प्रत्येक प्रयास के लिए एक नया प्रयास टाइमस्टैम्प और सिग्नेचर उत्पन्न करते हैं। एक तंत्र सुरक्षित रूप से दूसरे की जगह नहीं ले सकता।

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

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

उत्तर देने से पहले स्पष्ट करने वाले प्रश्न

  • 2xx वास्तव में क्या वादा करता है? यहाँ इसका मतलब है कि सिग्नेचर पास हो गया है और इवेंट, या इसका पहले से स्वीकृत डुप्लिकेट, ड्यूरेबल है। यह वादा नहीं करता है कि ईमेल, लेज़र, या प्रोवाइडर API कॉल समाप्त हो गए हैं।
  • रीट्रीज़ में कौन सी प्रोवाइडर पहचान स्थिर है? प्रत्येक एडेप्टर को लॉजिकल इवेंट ID, प्रयास टाइमस्टैम्प, सिग्नेचर फ़ॉर्मेट, और क्या मैनुअल रीडिलीवरी समान ID को बनाए रखती है, का दस्तावेजीकरण करना चाहिए। केवल पेलोड हैश से कभी भी पहचान प्राप्त न करें।
  • क्या प्रोवाइडर रॉ बॉडी और मेटाडेटा पर हस्ताक्षर करता है? एडेप्टर कैनोनिकल हस्ताक्षरित बाइट्स को परिभाषित करता है। JSON मिडलवेयर चलने से पहले HTTP फ़्रेमवर्क को अछूते (untouched) बॉडी को उजागर करना चाहिए।
  • क्या ऑर्डरिंग जानकारी मौजूद है? एक प्रामाणिक (authoritative) ऑब्जेक्ट वर्ज़न या सीक्वेंस को प्राथमिकता दें। एक इवेंट निर्माण समय उपयोगी साक्ष्य है लेकिन स्वचालित रूप से एक सख्त क्रम नहीं है। जब कोई वर्ज़न मौजूद न हो, तो स्थिति-निर्धारण (state-setting) इवेंट्स के लिए वर्तमान प्रोवाइडर स्थिति प्राप्त करें।
  • रीडिलीवरी कितने समय तक हो सकती है? आइडेम्पोटेंसी प्रतिधारण और पुराने-सीक्रेट ओवरलैप को प्रोवाइडर के दस्तावेज़ीकृत व्यवहार और उत्पाद की मैनुअल रीप्ले नीति को कवर करना चाहिए। इस समस्या में 30-दिवसीय रॉ-इवेंट प्रतिधारण एक उत्पाद धारणा है, न कि एक सार्वभौमिक विक्रेता नियम।
  • किन विफलताओं के कारण पुनः प्रयास होना चाहिए? यदि प्रामाणिकता स्थापित नहीं की जा सकती है या ड्यूरेबल स्टोरेज अनुपलब्ध है, तो स्वीकार न करें। ड्यूरेबल स्वीकृति के बाद, वर्कर आउटेज को HTTP प्रतिक्रिया नहीं बदलनी चाहिए।
  • कौन सा डेटा संवेदनशील है? रॉ बॉडीज़ को एन्क्रिप्ट करें, एक्सेस प्रतिबंधित करें, लॉग्स को रिडैक्ट करें, और विलोपन अपवादों को परिभाषित करें। एक सिग्नेचर प्रामाणिकता और अखंडता की पुष्टि करता है; यह पेलोड को एन्क्रिप्ट नहीं करता है।

30-सेकंड उत्तर फ़्रेमवर्क

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

स्टेप-बाय-स्टेप डीप डाइव

प्रत्येक प्रोवाइडर को एक एडेप्टर दें, लेकिन एक रिसीवर पाइपलाइन रखें। एडेप्टर अनुमत इवेंट प्रकार, अधिकतम बॉडी साइज़, हेडर पार्सिंग, कैनोनिकल हस्ताक्षरित बाइट्स, एल्गोरिदम, विश्वसनीय सीक्रेट वर्ज़न, फ्रेशनेस नीति, और लॉजिकल इवेंट ID का निष्कर्षण प्रदान करता है। सीक्रेट्स एक प्रबंधित सीक्रेट स्टोर से आते हैं और केवल एक सीमित अवधि के लिए कैश किए जाते हैं। एक रिक्वेस्ट को कभी भी एक अविश्वसनीय हेडर के माध्यम से अपनी सत्यापन की नहीं चुननी चाहिए।

इनग्रेस क्रम सुविचारित है:

text
1. Require HTTPS POST; apply endpoint and provider rate limits.
2. Validate bounded headers and Content-Length when present.
3. Read at most 1 MiB into raw bytes; reject overflow while streaming.
4. Parse signature metadata without parsing the JSON body.
5. Verify current and previous trusted secret versions in constant time.
6. Check the signed attempt timestamp against the provider-specific tolerance.
7. Parse the verified body and validate the event envelope and allowed type.
8. Durably accept under a unique logical-event key, then acknowledge.

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

सत्य के स्रोत के रूप में इनबॉक्स का उपयोग करें:

text
WebhookInbox(
  inbox_id, provider, endpoint_id, provider_event_id,
  event_type, object_id, object_version, provider_created_at,
  received_at, raw_payload_ref, payload_hash, matched_secret_version,
  status, attempt_count, next_attempt_at, lease_until, last_error
)

WebhookOutbox(outbox_id, inbox_id, topic, created_at, published_at)

UNIQUE(provider, endpoint_id, provider_event_id)

एक डेटाबेस लेनदेन के अंदर, इनबॉक्स पंक्ति और उसकी आउटबॉक्स अधिसूचना डालें। यदि अद्वितीय की पहले से मौजूद है, तो उसकी स्वीकृति स्थिति पढ़ें और अधिक काम बनाए बिना 2xx लौटाएं। यह एक एटॉमिक इन्सर्ट है, न कि "क्वेरी फिर इन्सर्ट"। स्वीकार करने से पहले कमिट करें। यदि डेटाबेस अनुपलब्ध है या कमिट परिणाम अज्ञात है, तो एक रीट्री-योग्य गैर-2xx लौटाएं; यदि पहला कमिट वास्तव में सफल रहा तो बाद का डुप्लिकेट अद्वितीय पंक्ति पर कन्वर्ज हो जाएगा।

डेटाबेस-प्लस-आउटबॉक्स डिज़ाइन सहेजने और कतारबद्ध करने के बीच के अंतर को पाटता है। एक रिले बार-बार अप्रकाशित आउटबॉक्स पंक्तियों को प्रकाशित करता है और उन्हें प्रकाशित चिह्नित करता है। प्रकाशन दो बार हो सकता है, इसलिए कतार उपभोक्ता अभी भी inbox_id द्वारा डिडुप्लिकेट करते हैं। एक सरल कार्यान्वयन ब्रोकर को छोड़ सकता है और वर्कर्स को लीज के साथ देय इनबॉक्स पंक्तियों का दावा करने की अनुमति दे सकता है, जैसे FOR UPDATE SKIP LOCKED। थ्रूपुट और परिचालन आवश्यकताओं के आधार पर चुनें, लेकिन इनबॉक्स को ड्यूरेबल स्वीकृति और ऑडिट सीमा के रूप में रखें।

वर्कर्स एक छोटी लीज का दावा करते हैं, वर्ज़न किए गए इवेंट को पार्स करते हैं, और केवल समर्थित प्रकारों को रूट करते हैं। उसी डेटाबेस में एक म्यूटेशन के लिए, व्यावसायिक पंक्ति को अपडेट करें, प्रोसेस किए गए इवेंट को रिकॉर्ड करें, और एक लेनदेन में इनबॉक्स को PROCESSED चिह्नित करें। प्रोसेस की गई इवेंट टेबल में समान स्थिर प्रोवाइडर की होती है, इसलिए एक वर्कर रीट्री नो-ऑप (no-op) बन जाता है। किसी अन्य सेवा को कॉल करने के लिए, अपनी आइडेम्पोटेंसी की के रूप में inbox_id के साथ एक स्थानीय आउटबॉक्स प्रविष्टि लिखें। मनमाने नेटवर्क पर सटीक रूप से एक बार (exactly-once) डिलीवरी असंभव बनी हुई है; स्थिर पहचान और आइडेम्पोटेंट रिसीवर कम से कम एक बार निष्पादन को सुरक्षित बनाते हैं।

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

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

सीक्रेट रोटेशन प्रोवाइडर रीडिलीवरी व्यवहार से प्राप्त एक सीमित ओवरलैप के लिए वर्तमान और पिछले वर्ज़न को विश्वसनीय रखता है। रिकॉर्ड करें कि कौन सा वर्ज़न मेल खाता है, लेकिन सीक्रेट या सिग्नेचर को कभी लॉग न करें। नए सीक्रेट दोनों सिरों पर कॉन्फ़िगर किए जाते हैं, उत्पादन में देखे जाते हैं, और पुराने वर्ज़न को स्पष्ट रूप से रिटायर कर दिया जाता है। आपातकालीन समझौते के लिए तत्काल रिटायरमेंट और प्रोवाइडर से रीप्ले की आवश्यकता हो सकती है, इसलिए रोटेशन रनबुक को नियोजित ओवरलैप को घटना प्रतिक्रिया से अलग करना चाहिए।

2,000 रिक्वेस्ट/s और 10 KiB औसत पर, इनग्रेस लगभग 19.5 MiB/s रॉ बॉडीज़ देखता है। क्षमता योजना में TLS और HMAC CPU, डेटाबेस लेनदेन दर, रेप्लिकेशन, कतार प्रवर्धन, और बर्स्ट अवधि शामिल है। स्टेटलेस इनग्रेस को क्षैतिज रूप से स्केल करें, यदि आवश्यक हो तो प्रोवाइडर और समय के अनुसार इनबॉक्स इंडेक्स को विभाजित करें, अपनी स्वामित्व सीमा के भीतर यूनीक की को विश्व स्तर पर लागू करने योग्य रखें, और जब डेटाबेस पंक्तियां बहुत बड़ी हो जाएं तो रॉ एन्क्रिप्टेड बॉडीज़ को ऑब्जेक्ट स्टोरेज में रखें।

स्वीकृत, डुप्लिकेट, अमान्य-सिग्नेचर, बासी, बड़े आकार और असमर्थित-इवेंट दरों को अलग से मापें। एक्नॉलेजमेंट p50/p95/p99, डेटाबेस कमिट लेटेंसी, सबसे पुरानी अनप्रोसेस्ड इनबॉक्स आयु, वर्कर सफलता और पुनः प्रयास दरें, FAILED काउंट, आउटबॉक्स रिले लैग, और मेल खाने वाले सीक्रेट वर्ज़न को ट्रैक करें। अलर्ट में लैग और ड्यूरेबल स्थिति का उपयोग करना चाहिए, केवल कतार की गहराई का नहीं। एक समाधान कार्य (reconciliation job) स्वीकृत इनबॉक्स पंक्तियों की तुलना संसाधित रिकॉर्ड और आउटबॉक्स प्रकाशन से करता है, फिर सुरक्षित लापता काम को फिर से कतारबद्ध करता है।

रॉ HTTP बाइट्स से अंदर की ओर परीक्षण करें। प्रोवाइडर द्वारा प्रकाशित सिग्नेचर वैक्टर का उपयोग करें, फिर एक बाइट, व्हाइटस्पेस, ID या टाइमस्टैम्प बदलें। लापता और डुप्लिकेट हेडर, बॉडी-साइज़ सीमाओं, क्लॉक तिरछापन (clock skew), वर्तमान/पिछले सीक्रेट्स और रिटायरमेंट का परीक्षण करें। एक इवेंट की सैकड़ों समवर्ती प्रतियां भेजें और एक इनबॉक्स पंक्ति और एक व्यावसायिक म्यूटेशन साबित करें। इनबॉक्स कमिट के बाद लेकिन प्रतिक्रिया से पहले, कतार पब्लिश के बाद लेकिन आउटबॉक्स को चिह्नित करने से पहले, और व्यावसायिक कमिट के बाद लेकिन वर्कर एक्नॉलेजमेंट से पहले क्रैश करें। वर्ज़न 3, 1, और 2 डिलीवर करें; वर्कर्स को संतृप्त करें; उन्हें पुनर्स्थापित करें; और सीमित एक्नॉलेजमेंट लेटेंसी के साथ अंतिम कन्वर्जेंस साबित करें।

उच्च गुणवत्ता वाला नमूना उत्तर

"मैं 2xx को ड्यूरेबल स्वीकृति के रूप में परिभाषित करता हूँ। इनग्रेस स्टेटलेस है और केवल एडेप्टर सीमा पर प्रोवाइडर-विशिष्ट है। यह HTTPS POST को स्वीकार करता है, बॉडी को 1 MiB तक सीमित करता है, सटीक रॉ बाइट्स को सुरक्षित रखता है, और विश्वसनीय वर्तमान या पिछले सीक्रेट्स के खिलाफ प्रोवाइडर के कैनोनिकल हस्ताक्षरित ID, प्रयास टाइमस्टैम्प और पेलोड की पुष्टि करता है। HMAC तुलनाएं स्थिर समय की होती हैं। मैं फिर सत्यापित लिफाफे को पार्स करता हूँ और केवल समर्थित इवेंट प्रकारों की अनुमति देता हूँ।

एक डेटाबेस लेनदेन में मैं UNIQUE(provider, endpoint_id, provider_event_id) के तहत WebhookInbox सम्मिलित करता हूँ और एक आउटबॉक्स पंक्ति सम्मिलित करता हूँ। मैं कमिट के बाद ही स्वीकार करता हूँ। एक समवर्ती डुप्लिकेट उस की पर संघर्ष करता है और बिना किसी नए काम के 2xx भी प्राप्त करता है। 2,000 रिक्वेस्ट प्रति सेकंड और 10 KiB औसत पर, रॉ इनग्रेस लगभग 19.5 MiB/s है, इसलिए मैं इनग्रेस को क्षैतिज रूप से स्केल करता हूँ और केवल रिक्वेस्ट्स की गिनती करने के बजाय सिग्नेचर CPU, डेटाबेस कमिट्स, रेप्लिकेशन और बर्स्ट स्टोरेज का आकार तय करता हूँ।

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

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

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

सामान्य गलतियाँ

  • सत्यापन से पहले JSON को पार्स करना → पुन: सीरियलाइज़ेशन हस्ताक्षरित बाइट्स को बदल देता है → पहले सटीक रॉ बॉडी को कैप्चर और सत्यापित करें।
  • पर्सिस्टेंस से पहले 200 लौटाना → एक क्रैश चुपचाप एक स्वीकृत इवेंट को खो देता है → जवाब देने से पहले इनबॉक्स को कमिट करें।
  • डेटाबेस में सहेजना और फिर एक बार प्रकाशित करना → राइट्स के बीच एक क्रैश काम को फंसा देता है → इनबॉक्स के साथ एक आउटबॉक्स कमिट करें या इनबॉक्स पंक्तियों को सीधे लीज पर लें।
  • पहले रीड के साथ डुप्लिकेट्स की जांच करना → समवर्ती रिक्वेस्ट्स दोनों पास हो जाती हैं → परमाणु रूप से एक अद्वितीय प्रोवाइडर-इवेंट की लागू करें।
  • केवल टाइमस्टैम्प फ्रेशनेस का उपयोग करना → एक साथ डुप्लिकेट अभी भी दो बार लागू होते हैं → फ्रेशनेस को स्थिर-ID डिडुप्लिकेशन के साथ संयोजित करें।
  • केवल एक इवेंट ID का उपयोग करना → एक कैप्चर की गई वैध रिक्वेस्ट को रीप्ले किया जा सकता है जबकि उसका रिकॉर्ड अनुपस्थित या समाप्त हो गया है → प्रोवाइडर अनुबंध के अनुसार हस्ताक्षरित फ्रेशनेस को भी सत्यापित करें।
  • मान लेना कि आगमन क्रम इवेंट क्रम है → देर से आने वाले इवेंट्स स्थिति को पीछे ले जाते हैं → वर्ज़न, मोनोटोनिक ट्रांज़िशन, या प्रामाणिक-स्थिति समाधान का उपयोग करें।
  • HTTP हैंडलर में रिमोट साइड इफ़ेक्ट्स निष्पादित करना → लेटेंसी रीट्रीज़ और अज्ञात परिणामों का कारण बनती है → ड्यूरेबल रूप से स्वीकार करें, फिर एसिंक्रोनस आइडेम्पोटेंट काम का उपयोग करें।
  • पूर्ण पेलोड और सिग्नेचर लॉग करना → ऑब्ज़र्वेबिलिटी एक डेटा और सीक्रेट लीक बन जाती है → प्रतिबंधित पहुंच के साथ एन्क्रिप्टेड साक्ष्य संग्रहीत करें और रिडैक्ट किए गए पहचानकर्ताओं को लॉग करें।

अनुवर्ती प्रश्न और उत्तर

अनुवर्ती 1: ऐसे डुप्लिकेट के लिए 2xx क्यों लौटाएं जिसकी प्रोसेसिंग समाप्त नहीं हुई है?

मूल इवेंट पहले से ही ड्यूरेबल रूप से स्वीकृत है, इसलिए कोई अन्य प्रोवाइडर रीट्री रिकवरी वैल्यू नहीं जोड़ता है। विफलता लौटाने से अधिक डुप्लिकेट ट्रैफ़िक उत्पन्न होगा। मौजूदा इनबॉक्स पंक्ति वर्कर्स और समाधान के लिए योग्य बनी हुई है। यह केवल तभी सुरक्षित है जब पंक्ति ड्यूरेबल हो और ऐसी स्थिति में न हो जिसका अर्थ है कि स्वीकृति वापस ले ली गई थी (rolled back)।

अनुवर्ती 2: क्या होगा यदि इनबॉक्स को कमिट करने के बाद लेकिन 2xx भेजने से पहले प्रक्रिया क्रैश हो जाती है?

प्रोवाइडर पुन: प्रयास करता है। अद्वितीय की कमिट की गई पंक्ति को ढूंढती है, कोई दूसरा काम नहीं बनाया जाता है, और रिसीवर 2xx लौटाता है। यह अपेक्षित कम से कम एक बार (at-least-once) वाला पथ है। यदि क्लाइंट 2xx प्राप्त करता है लेकिन कनेक्शन परिणाम प्रोवाइडर के लिए अस्पष्ट है, तो वही कन्वर्जेंस लागू होता है।

अनुवर्ती 3: क्या Redis आइडेम्पोटेंसी कीज़ रख सकता है?

यह एक त्वरक (accelerator) हो सकता है, लेकिन केवल एक अल्पकालिक कैश स्वीकृति अनुबंध से कमजोर है। निष्कासन (eviction), फ़ेलओवर, या समाप्ति उसी भुगतान इवेंट को फिर से लागू करने की अनुमति दे सकती है। आवश्यक व्यवसाय और रीडिलीवरी विंडो के लिए ड्यूरेबल प्रोसेस्ड पहचान रखें; Redis का उपयोग केवल तभी करें जब की खोने से उस अनुबंध का उल्लंघन न हो सके।

अनुवर्ती 4: आप सीक्रेट-स्टोर डाउनटाइम को कैसे संभालते हैं?

स्पष्ट समाप्ति और मेट्रिक्स के साथ पहले से विश्वसनीय वर्ज़न के एक सीमित, एन्क्रिप्टेड इन-मेमोरी कैश का उपयोग करें। यदि कोई मान्य कैश्ड की मौजूद नहीं है, तो क्लोज़ फ़ेल (fail closed) करें और एक रीट्री-योग्य प्रतिक्रिया लौटाएं ताकि प्रोवाइडर फिर से डिलीवर कर सके। अहस्ताक्षरित काम को कभी भी स्वीकार न करें या किसी अविश्वसनीय रिक्वेस्ट से की पहचानकर्ता प्राप्त न करें और उस पर स्वचालित रूप से भरोसा न करें।

अनुवर्ती 5: आप आउट-ऑफ-ऑर्डर पेमेंट स्ट्रीम को कैसे पुनर्प्राप्त करते हैं?

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

अनुवर्ती 6: यह अभी भी बिल्कुल एक बार (exactly once) क्यों नहीं है?

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

सार्वजनिक स्रोत

संबंधित प्रश्न