मुख्य सामग्री पर जाएँ

CooLWJ पर खोजें

选择搜索范围,输入关键词后按回车。

भाषा

rabbitmq कंज़्यूमर का “बिना वजह गायब हो जाना”

समस्या की पृष्ठभूमि:

9वें महीने की 1 तारीख को लगभग 17:12 बजे, परिनियोजन कर्मियों से शिकायत मिली कि कुछ उपकरण ठीक से अपग्रेड नहीं हो पा रहे थे और कंसोल से भेजे गए निर्देश प्राप्त नहीं कर रहे थे। सहकर्मियों ने control प्रोजेक्ट(आगे संक्षेप में control)के लॉग देखे और पाया कि control को उपकरणों द्वारा भेजी गई शैडो जानकारी मिली ही नहीं थी, इसलिए उसने निर्देश नहीं भेजे। control प्रोजेक्ट सीधे उपकरणों से जुड़ता है और उनसे प्राप्त जानकारी के आधार पर अपग्रेड तथा लॉग भेजने जैसे निर्देश और कॉन्फ़िगरेशन जानकारी उपकरणों को भेजता है। IoT शुरू होने से पहले control उपकरणों की वर्तमान जानकारी पाने के लिए हार्टबीट रिपोर्ट पर निर्भर था, और IoT शुरू होने के बाद उपकरण शैडो जानकारी पर निर्भर है

से डिवाइस की वर्तमान जानकारी प्राप्त की जाती है। control डिवाइस की शैडो जानकारी की सदस्यता लेता है, लेकिन शैडो जानकारी शैडो सेवा(संक्षेप में IoT)द्वारा आगे भेजी जाती है; वह डिवाइस द्वारा भेजी गई शैडो रिपोर्ट से सीधे नहीं जुड़ता। प्रवाह के विशिष्ट विवरण के लिए नीचे दिए गए दो चित्र देखें:

एप्लिकेशन(control)डिवाइस की स्थिति प्राप्त करता है

एप्लिकेशन(control)डिवाइस को निर्देश भेजता है

 

यह पता चलते ही कि control को शैडो संदेश नहीं मिल रहे थे, मैं तुरंत rabbitmq के कंसोल पर गया और संदेशों की मौजूदगी जाँची, ताकि दो बातें पक्की कर सकूँ:1.क्या डिवाइस ने संदेश भेजे थे 2.क्या rabbitmq सामान्य रूप से काम कर रहा था, नीचे चित्र1、चित्र2 उस समय लिए गए rabbitmq कंसोल के दो स्क्रीनशॉट हैं, जिनसेचित्र1 यह स्पष्ट रूप से निर्धारित किया जा सकता है कि उपकरण संदेश भेज रहा है, लेकिन बहुत सारे संदेश unacked(जिनकी प्राप्ति की पुष्टि नहीं हुई है)(इसका अर्थ है कि संदेश उपभोक्ता तक पहुँच चुका है, बस उपभोक्ता ने ack नहीं भेजा है, सैद्धांतिक रूप से कुछ समय प्रतीक्षा करने पर स्थिति सामान्य हो जानी चाहिए)का है, किस कतार में unacked संदेश जमा हैं, यह जानने के लिए देखेंचित्र2,“spacebridgeiot-shadow” ठीक वही है जिसका उपयोग हम उपकरणों द्वारा भेजी गई शैडो जानकारी प्राप्त करने के लिए करते हैं, संदेश कतार में जमा हो गए थे इसलिए उनका control को न भेजा जाना भी समझ में आता था, कुछ समय देखने पर पता चला कि unacked की संख्या 0 हो गई, लेकिन total की कुल संख्या में खास बदलाव नहीं हुआ, ऐसा लगा जैसे unacked संदेश फिर से संदेश कतार में लौटकर डिलीवरी की प्रतीक्षा कर रहे हों, और सचमुच कुछ मिनट बाद फिर बड़ी संख्या में unacked संदेश दिखाई दिए, कुछ मिनट बाद ये unacked संदेश वापस कतार में लौट गए, control को तब भी कोई संदेश नहीं मिला, इस समय IoT के लॉग देखने पर पता चला कि शैडो संदेश आए ही नहीं थे, rabbitmq के कंसोल में देखा “spacebridgeiot-shadow” इस कतार में तो कोई उपभोक्ता ही नहीं बचा था, जैसेचित्र3 में दिखाया गया है। इस समय rabbitmq के लॉग देखने पर वास्तव में त्रुटि संदेश मिले, जैसेचित्र 4 में दिखाए अनुसार, rabbitmq ने स्वयं कनेक्शन बंद कर दिया।

चित्र1:rabbitmq का अवलोकन चित्र

 

 

चित्र2:rabbitmq कतार के आँकड़ों का आलेख

 

 

चित्र3:spacebridgeiot-shadow का अवलोकन

 

 

 चित्र4:rabbitmq का त्रुटि संदेश

 

अस्थायी समाधान:

चूँकि तब तक बहुत सारी शिकायतें आ चुकी थीं, इसलिए कुछ कठोर उपाय अपनाया गया—“जमा हुए संदेशों को मिटा देना”, और मिटाने के बाद सचमुच सब सामान्य हो गया(टिप्पणी:प्रोडक्शन की समस्याएँ जल्द से जल्द हल करनी होती हैं। हमारे पास लॉग का विश्लेषण करके व्यवस्थित ढंग से समाधान करने का समय नहीं होता, तेज़ी ज़रूरी है)。

 

RabbitMQ का तकनीकी चिह्न

स्थानीय परीक्षण परिवेश में समस्या दोहराना:

1.परिवेश 10.200.41.166 के rabbitmq की कतार “mirrorTestQueue” में बड़ी संख्या में संदेश जमा करें(कम से कम दस हज़ार के स्तर पर)

2.mirrorTestQueue के उपभोक्ता को रोकें, संदेश जमा हो जाने के बाद उसे फिर शुरू करें

3.संदेश जमा हो जाने के बाद,उपभोक्ता को फिर से शुरू करें

 

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

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

हमें संदेह हुआ कि शायद TCP स्तर पर कुछ गड़बड़ है, इसलिए पैकेट कैप्चर करके कोई सुराग खोजने का निर्णय लिया। सचमुच, किस्मत ने साथ दिया। अधिक बात किए बिना सीधे चित्र देखते हैं।

 

 

 13:06:25.643428 से पहले तक rabbitmq उपभोक्ता को लगातार संदेश भेज रहा था,13:06:25.643428 के समय से उपभोक्ता की tcp विंडो पूरी भरने लगी,यह स्थिति लगभग 30 सेकंड रही,फिर rabbitmq ने स्वयं कनेक्शन काट दिया(एक rst पैकेट भेजा),इसके बाद उपभोक्ता फिर जुड़ा,फिर विंडो दोबारा पूरी भरती रही,और लगभग 30 सेकंड बाद कनेक्शन फिर काट दिया गया।

 

काफ़ी नियमित लग रहा है,हर बार 30 सेकंड तक चलता है,लगता है यह कोई कॉन्फ़िगर करने योग्य पैरामीटर है,मोटे तौर पर इसे यूँ समेट सकते हैं “tcp विंडो भरने के कारण सर्वर ने स्वयं rst भेजकर कनेक्शन रीसेट किया,और यह नियमित ढंग से होता है”

इस बार खोज के शब्द बदलने पर मिलाउत्तर,rabbitmq में एक पैरामीटर है जिसका नाम है tcp_listen_options.send_timeout लेखन समय सीमा को नियंत्रित करने वाला एक पैरामीटर है, और लेखन की समय सीमा समाप्त होने पर tcp का RST ट्रिगर होता है(https://github.com/rabbitmq/rabbitmq-java-client/issues/341),कुछ बदलाव करके देखें कि परिणाम कैसा है:

1. लेखन टाइमआउट को 10s करें

tcp_listen_options.send_timeout = 10000

 2.पैकेट कैप्चर करके देखें कि यह असर कर रहा है या नहीं

 

 विंडो भरने से कनेक्शन बंद होने तक लगभग 10 सेकंड लगे।

 

घटनाक्रम की समीक्षा:

rabbitmq के उपभोक्ता पक्ष पर prefetch सेट नहीं होने के कारण rabbitmq ने एक ही बार में उपभोक्ता को बहुत अधिक संदेश भेज दिए। इससे उपभोक्ता की tcp विंडो पूरी भर गई, जिसके बाद rabbitmq का tcp_listen_options.send_timeout सक्रिय हुआ। यह लेखन टाइमआउट एक सीमा तक पहुँचने पर rabbitmq उपभोक्ता का tcp कनेक्शन तोड़ देता है।

 

अंतिम समाधान:

        पहले संदेशों को हटाना केवल मजबूरी में अपनाया गया उपाय था। इससे समस्या तो हल हो गई, लेकिन यह बहुत कठोर तरीका था। हमें इससे निपटने का एक सुगठित समाधान ढूँढ़ना होगा। चूँकि उपभोक्ता को बहुत अधिक संदेश भेजे जाने से tcp विंडो भर गई थी, इसलिए हमें प्राप्ति की दर पर काम करना चाहिए। rabbitmq से कनेक्ट होते समय उसे बस यह बता देना है कि मुझे बहुत अधिक संदेश मत भेजो。(आगे दिया गया अंश यहाँ से उद्धृत हैhttps://blog.csdn.net/james_searcher/article/details/70308565)rabbitmq में prefetch नाम का एक गुण होता है, जो बताता है कि एक उपभोक्ता अधिकतम कितने अपुष्ट संदेश ले सकता है। इसे कैसे समझें?mq हर consumer के लिए एक बफ़र तय करता है, जिसका आकार prefetch होता है। हर संदेश मिलने पर MQ उसे बफ़र में भेजता है, फिर क्लाइंट को भेजता है। जब ack संदेश मिलता है(consumer baseack निर्देश भेजता है), तो mq बफ़र में एक स्थान खाली करता है और उसमें नया संदेश जोड़ता है। लेकिन यदि उस समय बफ़र भरा हो, तो MQ अवरुद्ध अवस्था में चला जाता है। अधिक स्पष्ट रूप से, मान लें कि prefetch का मान 10 है और कुल दो consumer हैं। यानी हर consumer हर बार queue से 10 संदेश पहले से लेकर अपने स्थानीय बफ़र में प्रसंस्करण के इंतज़ार में रखता है। साथ ही उस channel के अपुष्ट संदेशों की संख्या 20 हो जाती है। Rabbit पहले consumer1 को पूरे 10 संदेश भेजता है, फिर consumer2 को 10 संदेश भेजता है। यदि इस समय कोई नया संदेश भेजना हो, तो पहले जाँचा जाता है कि channel के अपुष्ट संदेशों की संख्या 20 के बराबर है या नहीं;यदि है, तो संदेश consumer को नहीं भेजा जाता और वह queue में ही रहता है। इसके बाद जब कोई consumer एक संदेश का ack देता है, तो अपुष्ट संदेशों की संख्या 19 हो जाती है। तब Rabbit देखता है कि किस consumer के अपुष्ट संदेश 10 से कम हैं और उसी को संदेश भेजता है।

 

कोड में विशेष रूप से यह है

 

 

इस मान का आकलन कैसे करें? rabbitmq के आधिकारिक लेख में इसे बहुत अच्छी तरह समझाया गया है, इसलिए यहाँ विस्तार नहीं करेंगे। हमारे सिस्टम में फिलहाल यह 20 रखा गया है।

https://www.rabbitmq.com/blog/2012/05/11/some-queuing-theory-throughput-latency-and-bandwidth/

 

 

समापन:

rabbitmq के इस्तेमाल में हम अभी शुरुआती स्तर पर हैं। इसका उपयोग करने से पहले rabbitmq के API को खूब पढ़ना, आम API के इस्तेमाल से परिचित होना और स्थानीय परिवेश में अधिक प्रयोग करना ज़रूरी है।


टिप्पणियाँ

भेजा जा रहा है

लोकप्रिय पोस्ट

अपनी थीम चुनें

आपकी थीम पूरी साइट पर लागू होगी।