हमें एक ऐसी स्थिति मिली है जहां मुझे अपने सर्वर पर आने वाली घटनाओं के एक बड़े प्रवाह से निपटना होगा, औसतन प्रति सेकंड लगभग 1000 घटनाएं (शिखर ~ 2000 हो सकती हैं)।
समस्या
हमारा सिस्टम हेरोकू पर होस्ट किया गया है और अपेक्षाकृत महंगे हरोकू पोस्टग्रब्स डीबी का उपयोग करता है , जो अधिकतम 500 डीबी कनेक्शन की अनुमति देता है। हम सर्वर से डीबी से कनेक्ट करने के लिए कनेक्शन पूलिंग का उपयोग करते हैं।
डीबी कनेक्शन पूल की तुलना में ईवेंट तेजी से आ सकते हैं
हमारे पास समस्या यह है कि कनेक्शन पूल को संभालने की तुलना में घटनाएं तेजी से आती हैं। जब तक एक कनेक्शन सर्वर से DB तक नेटवर्क राउंडट्रिप को पूरा कर लेता है, तब तक यह पूल में वापस आ सकता है, n
अतिरिक्त ईवेंट अधिक से अधिक आते हैं।
अंततः ईवेंट्स ढेर हो जाते हैं, सहेजने के लिए प्रतीक्षा करते हैं और क्योंकि पूल में कोई उपलब्ध कनेक्शन नहीं हैं, वे समय से बाहर हो जाते हैं और पूरी प्रणाली को गैर-परिचालन प्रदान किया जाता है।
हमने ग्राहकों से धीमी गति से आक्रामक उच्च आवृत्ति वाली घटनाओं का उत्सर्जन करके आपातकाल को हल कर दिया है, लेकिन हम अभी भी जानना चाहते हैं कि उस घटना को कैसे संभालना है जो हमें उस उच्च आवृत्ति घटनाओं को संभालने की आवश्यकता है।
प्रतिबन्ध
अन्य ग्राहक समवर्ती घटनाओं को पढ़ना चाहते हैं
अन्य ग्राहक किसी विशेष कुंजी के साथ सभी घटनाओं को पढ़ने के लिए लगातार अनुरोध करते हैं, भले ही वे अभी तक डीबी में सहेजे नहीं गए हों।
एक क्लाइंट GET api/v1/events?clientId=1
क्लाइंट 1 द्वारा भेजे गए सभी ईवेंट को क्वेरी और प्राप्त कर सकता है , भले ही उन घटनाओं को डीबी में अभी तक बचत नहीं की गई हो।
क्या इससे निपटने के लिए कोई "कक्षा" उदाहरण हैं?
संभव समाधान
हमारे सर्वर पर घटनाओं को दर्ज करें
हम सर्वर पर होने वाली घटनाओं को समझ सकते हैं (कतार में 400 की अधिकतम समवर्ती होने के कारण कनेक्शन पूल नहीं चलता है)।
यह बुरा विचार है क्योंकि:
- यह उपलब्ध सर्वर मेमोरी को खा जाएगा। स्टैक्ड-अप एन्केड की गई घटनाओं से भारी मात्रा में रैम की खपत होगी।
- हमारे सर्वर हर 24 घंटे में एक बार पुनः आरंभ करते हैं । यह हरोकू द्वारा लगाई गई एक कठिन सीमा है । सर्वर पुनः आरंभ कर सकता है जबकि घटनाओं की गणना की जा रही है, जिससे हमें संलग्न घटनाओं को खोना पड़ता है।
- यह सर्वर पर स्थिति का परिचय देता है, इस प्रकार स्केलेबिलिटी को नुकसान पहुंचाता है। यदि हमारे पास एक मल्टी-सर्वर सेटअप है और एक क्लाइंट सभी एन्केस्ड + सेव किए गए इवेंट्स को पढ़ना चाहता है, तो हमें यह पता नहीं चलेगा कि किस सर्वर पर एनक्वाइडेड इवेंट्स रहते हैं।
एक अलग संदेश कतार का उपयोग करें
मुझे लगता है कि हम एक संदेश कतार का उपयोग कर सकते हैं, (जैसे RabbitMQ ?), जहां हम इसमें संदेशों को पंप करते हैं और दूसरे छोर पर एक और सर्वर होता है जो केवल डीबी पर घटनाओं को सहेजने से संबंधित है।
मुझे यकीन नहीं है कि यदि संदेश कतारों की गणना की घटनाओं की अनुमति देता है (जो अभी तक सहेजे नहीं गए थे) तो यदि कोई अन्य ग्राहक किसी अन्य क्लाइंट के संदेशों को पढ़ना चाहता है, तो मैं केवल सहेजे गए संदेशों को डीबी और कतार से लंबित संदेशों को प्राप्त कर सकता हूं। और उन्हें एक साथ समेटना ताकि मैं उन्हें रीड-रिक्वेस्ट क्लाइंट को वापस भेज सकूं।
उन्हें प्रबंधित करने के लिए केंद्रीय डीबी-समन्वयक सर्वर के साथ संदेशों के एक हिस्से को सहेजने वाले कई डेटाबेस का उपयोग करें
एक और समाधान जो हमने हालांकि कई डेटाबेस का उपयोग करना है, एक केंद्रीय "डीबी समन्वयक / लोड बैलेंसर" के साथ है। एक ईवेंट प्राप्त करने पर यह समन्वयक संदेश को लिखने के लिए डेटाबेस में से एक का चयन करेगा। यह हमें कई हेरोकू डेटाबेस का उपयोग करने की अनुमति देनी चाहिए ताकि इस प्रकार से डेटाबेस की 500 x संख्या में कनेक्शन की सीमा समाप्त हो जाए।
एक पठन क्वेरी पर, यह समन्वयक SELECT
प्रत्येक डेटाबेस के लिए प्रश्न जारी कर सकता है, सभी परिणामों को मर्ज कर सकता है और उन्हें उस ग्राहक को वापस भेज सकता है जिसने पढ़ने का अनुरोध किया था।
यह बुरा विचार है क्योंकि:
- यह विचार ... ahem .. over-engineering की तरह लगता है? के रूप में अच्छी तरह से (बैकअप आदि ..) का प्रबंधन करने के लिए एक बुरा सपना होगा। यह निर्माण और रखरखाव और यह एक तरह लगता है, जब तक यह बिल्कुल जरूरी है करने के लिए जटिल है KISS उल्लंघन।
- यह संगति का त्याग करता है । यदि हम इस विचार के साथ चलते हैं, तो कई DB के लेन-देन करना एक नहीं है।
ANALYZE
स्वयं प्रश्नों पर चला हूं और वे कोई समस्या नहीं हैं। मैंने कनेक्शन पूल परिकल्पना का परीक्षण करने के लिए एक प्रोटोटाइप भी बनाया है और सत्यापित किया है कि यह वास्तव में समस्या है। डेटाबेस और सर्वर स्वयं विभिन्न मशीनों पर रहते हैं इसलिए विलंबता। इसके अलावा, हम हरोकू को छोड़ना नहीं चाहते हैं, जब तक कि पूरी तरह से आवश्यक नहीं है, तैनाती के बारे में चिंतित नहीं होना हमारे लिए बहुत बड़ा प्लस है।
select null
500 कनेक्शन जारी करने का प्रयास करें । मुझे यकीन है कि आप पाएंगे कि कनेक्शन पूल वहां की समस्या नहीं है।