RabbitMQ / AMQP: एकल कतार, एक ही संदेश के लिए कई उपभोक्ता?


146

मैं अभी सामान्य रूप से RabbitMQ और AMQP का उपयोग करना शुरू कर रहा हूं।

  • मेरे पास संदेशों की कतार है
  • मेरे पास कई उपभोक्ता हैं, जो एक ही संदेश के साथ अलग-अलग चीजें करना चाहते हैं ।

अधिकांश RabbitMQ दस्तावेज़ीकरण राउंड-रॉबिन पर ध्यान केंद्रित करने के लिए लगता है, अर्थात जहां एक एकल संदेश का उपभोग एकल उपभोक्ता द्वारा किया जाता है, जिसमें लोड प्रत्येक उपभोक्ता के बीच फैलता है। यह वास्तव में मेरे द्वारा देखा गया व्यवहार है।

एक उदाहरण: निर्माता के पास एक ही कतार है, और हर 2 सेकंड में संदेश भेजें:

var amqp = require('amqp');
var connection = amqp.createConnection({ host: "localhost", port: 5672 });
var count = 1;

connection.on('ready', function () {
  var sendMessage = function(connection, queue_name, payload) {
    var encoded_payload = JSON.stringify(payload);  
    connection.publish(queue_name, encoded_payload);
  }

  setInterval( function() {    
    var test_message = 'TEST '+count
    sendMessage(connection, "my_queue_name", test_message)  
    count += 1;
  }, 2000) 


})

और यहाँ एक उपभोक्ता है:

var amqp = require('amqp');
var connection = amqp.createConnection({ host: "localhost", port: 5672 });
connection.on('ready', function () {
  connection.queue("my_queue_name", function(queue){
    queue.bind('#'); 
    queue.subscribe(function (message) {
      var encoded_payload = unescape(message.data)
      var payload = JSON.parse(encoded_payload)
      console.log('Recieved a message:')
      console.log(payload)
    })
  })
})

यदि मैं उपभोक्ता को दो बार शुरू करता हूं , तो मैं देख सकता हूं कि प्रत्येक उपभोक्ता राउंड-रॉबिन व्यवहार में वैकल्पिक संदेशों का उपभोग कर रहा है। जैसे, मैं एक टर्मिनल में 1, 3, 5 के संदेश देखूंगा, दूसरे में 2, 4, 6

मेरा सवाल यह है कि:

  • क्या मेरे पास प्रत्येक उपभोक्ता समान संदेश प्राप्त कर सकता है? यानी, दोनों उपभोक्ताओं को 1, 2, 3, 4, 5, 6 संदेश मिलेंगे? इसे AMQP / RabbitMQ में क्या कहा जाता है? यह सामान्य रूप से कैसे कॉन्फ़िगर किया गया है?

  • क्या यह आमतौर पर किया जाता है? क्या मुझे बदले में एक ही उपभोक्ता के साथ, संदेश को दो अलग-अलग कतारों में बदलना चाहिए?


5
मैं कोई RabbitMQ विशेषज्ञ नहीं हूं। हालाँकि, अब आपके पास जो कतार है उसे कतार कहा जाता है, लेकिन आप चाहते हैं कि विषय क्या हों, इस ट्यूटोरियल देखें: rabbitmq.com/tutorials/tutorial-five-python.html , कतार बनाम विषयों पर अधिक: msdn.microsoft.com/en-us /library/windowsazure/hh367516.aspx
UrbanEsc

1
मेरा मानना ​​है कि वह वास्तव में प्रशंसक चाहते हैं, हालांकि विषय भी काम करेंगे और बाद में अधिक नियंत्रण देंगे।
रॉबथफॉल्फ

धन्यवाद @UrbanEsc विषयों को लगता है कि समस्या को हल करने के लिए एक संदेश कई कतारों को मारा, और इसलिए प्रत्येक कतार उपभोक्ताओं द्वारा उपभोग किया जाना चाहिए। जो मुझे मेरे विशेष मामले के लिए कई कतार / एकल उपभोक्ता परिदृश्य की ओर ले जाता है।
मिकमेकाना

1
2018 के लिए (और 2016 और उससे पहले के लिए भी) उत्तर काफका, आईएमओ जैसी किसी चीज का उपयोग करना है।
वाट्स इनबॉक्‍स

जवाबों:


115

क्या मेरे पास प्रत्येक उपभोक्ता समान संदेश प्राप्त कर सकता है? यानी, दोनों उपभोक्ताओं को 1, 2, 3, 4, 5, 6 संदेश मिलेंगे? इसे AMQP / RabbitMQ में क्या कहा जाता है? यह सामान्य रूप से कैसे कॉन्फ़िगर किया गया है?

नहीं, नहीं तो उपभोक्ता एक ही कतार में हैं। RabbitMQ की AMQP अवधारणाओं से गाइड:

यह समझना महत्वपूर्ण है कि, AMQP 0-9-1 में, संदेश उपभोक्ताओं के बीच संतुलित हैं।

ऐसा लगता है कि एक कतार के भीतर गोल-रॉबिन व्यवहार एक दिया गया है , और विन्यास योग्य नहीं है। यानी, एक ही संदेश आईडी को कई उपभोक्ताओं द्वारा नियंत्रित करने के लिए अलग-अलग कतार की आवश्यकता होती है।

क्या यह आमतौर पर किया जाता है? क्या मुझे बदले में एक ही उपभोक्ता के साथ, संदेश को दो अलग-अलग कतारों में बदलना चाहिए?

यह नहीं है, एक ही संदेश आईडी को संभालने वाले प्रत्येक उपभोक्ता के साथ एकल कतार / एकाधिक उपभोक्ता संभव नहीं है। विनिमय मार्ग पर संदेश को दो अलग-अलग कतारों में रखने से वास्तव में बेहतर होता है।

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

यहाँ मेरा कट्टर विनिमय है, भेजने और प्राप्त करने दोनों:

var amqp = require('amqp');
var connection = amqp.createConnection({ host: "localhost", port: 5672 });
var count = 1;

connection.on('ready', function () {
  connection.exchange("my_exchange", options={type:'fanout'}, function(exchange) {   

    var sendMessage = function(exchange, payload) {
      console.log('about to publish')
      var encoded_payload = JSON.stringify(payload);
      exchange.publish('', encoded_payload, {})
    }

    // Recieve messages
    connection.queue("my_queue_name", function(queue){
      console.log('Created queue')
      queue.bind(exchange, ''); 
      queue.subscribe(function (message) {
        console.log('subscribed to queue')
        var encoded_payload = unescape(message.data)
        var payload = JSON.parse(encoded_payload)
        console.log('Recieved a message:')
        console.log(payload)
      })
    })

    setInterval( function() {    
      var test_message = 'TEST '+count
      sendMessage(exchange, test_message)  
      count += 1;
    }, 2000) 
 })
})

1
प्रशंसक बाहर स्पष्ट रूप से आप क्या चाहते थे। यह यहां आपकी मदद नहीं करेगा, लेकिन मुझे लगा कि मैं एक कतार के भीतर राउंड-रॉबिन व्यवहार का उल्लेख करूंगा। int prefetchCount = 1; channel.basicQos(prefetchCount); यह प्रत्येक उपभोक्ता को पिछले एक के साथ समाप्त होते ही एक संदेश प्राप्त करने की अनुमति देगा। इसके बजाय बारी-बारी से संदेश प्राप्त करना। फिर से आपकी समस्या का समाधान नहीं है, लेकिन लोगों को जानना उपयोगी हो सकता है। यहां उदाहरण http://www.rabbitmq.com/tutorials/tutorial-two-java.html फेयर डिस्पैच के तहत
ओमित

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

2
क्या खरगोश के विषय में अपाचे सक्रिय एमएमएस विषयों का कोई विकल्प है जहां कोई कतार शामिल नहीं है, बल्कि मल्टीकास्टिंग है?
पैन्टोनिस

यदि एक ही उपयोगकर्ता कई उपकरणों से लॉगिन करता है तो संदेश केवल एक ही उपकरण को प्राप्त करता है। इसे कैसे हल किया जा सकता है या कोई विचार कृपया?
रफीक

@ रफीक आपको इसके लिए एक प्रश्न पूछना चाहिए।
मिकमेकाना 14

28

बस खरगोश खरगोश ट्यूटोरियल पढ़ें । आप संदेश को विनिमय करने के लिए प्रकाशित करते हैं, कतार में नहीं; फिर इसे उपयुक्त कतारों में लगाया जाता है। आपके मामले में, आपको प्रत्येक उपभोक्ता के लिए अलग कतार बाँधनी चाहिए। इस तरह, वे संदेशों का पूरी तरह से स्वतंत्र रूप से उपभोग कर सकते हैं।


27

उत्तर के अंतिम दो अक्षर लगभग सही हैं - मेरे पास कई ऐसे एप्लिकेशन हैं जो ऐसे संदेश उत्पन्न करते हैं जो विभिन्न उपभोक्ताओं के साथ समाप्त होने की आवश्यकता होती है इसलिए प्रक्रिया बहुत सरल है।

यदि आप एक ही संदेश के लिए कई उपभोक्ताओं को चाहते हैं, तो निम्न प्रक्रिया करें।

कई कतारें बनाएं, प्रत्येक ऐप के लिए एक जो संदेश प्राप्त करना है, प्रत्येक कतार गुणों में, amq.direct एक्सचेंज के साथ एक रूटिंग टैग "बाइंड" करें। आपको amq.direct को भेजने के लिए प्रकाशन एप्लिकेशन बदलें और रूटिंग-टैग (एक कतार नहीं) का उपयोग करें। इसके बाद AMQP एक ही बंधन के साथ संदेश को प्रत्येक कतार में कॉपी करेगा। एक जादू की तरह काम करता है :)

उदाहरण: मुझे लगता है कि मेरे पास एक JSON स्ट्रिंग है जिसे मैं उत्पन्न करता हूं, मैं इसे "amq.direct" एक्सचेंज को राउटिंग टैग "न्यू-सेल्स-ऑर्डर" का उपयोग करके प्रकाशित करता हूं, मेरे पास मेरे ऑर्डर_प्रिंटर ऐप के लिए एक कतार है जो ऑर्डर प्रिंट करता है, मेरे पास है मेरे बिलिंग सिस्टम के लिए कतार जो ऑर्डर की एक प्रति भेजेगा और ग्राहक को चालान देगा और मेरे पास एक वेब संग्रह प्रणाली है जहां मैं ऐतिहासिक / अनुपालन कारणों के लिए आदेशों का संग्रह करता हूं और मेरे पास एक ग्राहक वेब इंटरफ़ेस है जहां आदेशों को ट्रैक किया जाता है क्योंकि अन्य जानकारी के बारे में आता है एक आदेश।

इसलिए मेरी कतारें हैं: order_printer, order_billing, order_archive और order_tracking सभी के पास बाध्यकारी टैग "नया-बिक्री-ऑर्डर" है जो उन्हें बाध्य करता है, सभी 4 को JSON डेटा मिलेगा।

यह प्रकाशन एप्लिकेशन के बिना डेटा भेजने या प्राप्त करने वाले ऐप्स के बारे में देखभाल करने का एक आदर्श तरीका है।


8

हां प्रत्येक उपभोक्ता एक ही संदेश प्राप्त कर सकता है। अच्छी तरह से देखिए http://www.rabbitmq.com/tutorials/tutorial-three-python.html http://www.rabbitmq.com/tutorials/tutorial-four-python.html http: //www.rabbitmq । com / ट्यूटोरियल / ट्यूटोरियल-पांच python.html

संदेशों को रूट करने के विभिन्न तरीकों के लिए। मुझे पता है कि वे अजगर और जावा के लिए हैं, लेकिन सिद्धांतों को समझने के लिए अच्छा है, तय करें कि आप क्या कर रहे हैं और फिर जेएस में इसे कैसे करें। इसकी तरह लगता है कि आप एक साधारण प्रशंसक ( ट्यूटोरियल 3) करना चाहते हैं ) , जो एक्सचेंज से जुड़ी सभी कतारों को संदेश भेजता है।

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

हाँ, यह आमतौर पर किया जाता है, यह AMPQ की विशेषताओं में से एक है।


महान जवाब, सिवाय 'यह आमतौर पर किया जाता है?' मैं 'प्रत्येक उपभोक्ता को एक ही संदेश प्राप्त होने' का उल्लेख कर रहा था - जो आमतौर पर नहीं किया जाता है (एक ही कतार में उपभोक्ता हमेशा राउंड रॉबिन)। संभवत: पर्याप्त नहीं होने के लिए मेरी गलती है।
मिकमेकाना

वास्तव में मैं यह कहने के लिए उद्यम करूंगा कि यह निर्भर करता है कि आप इसके लिए क्या उपयोग करना चाहते हैं। आपके पास दो मूल विकल्प हैं पब / उप या कार्य कतार। आपका मूल सेट एक काम कतार था लेकिन आप जो चाहते थे वह एक प्रशंसक पब / उप था। वे बताते हैं कि यहां आम उपयोग पूरी तरह से इस बात पर निर्भर है कि आप क्या करना चाहते हैं।
रॉबथफॉल्फ

निश्चित रूप से लेकिन एक कार्य कतार में, एक ही संदेश (उदाहरण के लिए, एक ही संदेश आईडी) विभिन्न उपभोक्ताओं द्वारा नियंत्रित नहीं किया जाता है - यह अंतर्निहित राउंड रॉबिन है। फिर यह स्पष्ट रूप से पर्याप्त नहीं होने के लिए मेरी गलती है।
मिकमेकाना

हम यहाँ क्रॉस के उद्देश्यों पर बात करते दिखाई देते हैं।
रॉबथॉल्फ

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


3

RabbitMQ / AMQP: एकल कतार, एक ही संदेश और पेज रिफ्रेश के लिए कई उपभोक्ता।

rabbit.on('ready', function () {    });
    sockjs_chat.on('connection', function (conn) {

        conn.on('data', function (message) {
            try {
                var obj = JSON.parse(message.replace(/\r/g, '').replace(/\n/g, ''));

                if (obj.header == "register") {

                    // Connect to RabbitMQ
                    try {
                        conn.exchange = rabbit.exchange(exchange, { type: 'topic',
                            autoDelete: false,
                            durable: false,
                            exclusive: false,
                            confirm: true
                        });

                        conn.q = rabbit.queue('my-queue-'+obj.agentID, {
                            durable: false,
                            autoDelete: false,
                            exclusive: false
                        }, function () {
                            conn.channel = 'my-queue-'+obj.agentID;
                            conn.q.bind(conn.exchange, conn.channel);

                            conn.q.subscribe(function (message) {
                                console.log("[MSG] ---> " + JSON.stringify(message));
                                conn.write(JSON.stringify(message) + "\n");
                            }).addCallback(function(ok) {
                                ctag[conn.channel] = ok.consumerTag; });
                        });
                    } catch (err) {
                        console.log("Could not create connection to RabbitMQ. \nStack trace -->" + err.stack);
                    }

                } else if (obj.header == "typing") {

                    var reply = {
                        type: 'chatMsg',
                        msg: utils.escp(obj.msga),
                        visitorNick: obj.channel,
                        customField1: '',
                        time: utils.getDateTime(),
                        channel: obj.channel
                    };

                    conn.exchange.publish('my-queue-'+obj.agentID, reply);
                }

            } catch (err) {
                console.log("ERROR ----> " + err.stack);
            }
        });

        // When the visitor closes or reloads a page we need to unbind from RabbitMQ?
        conn.on('close', function () {
            try {

                // Close the socket
                conn.close();

                // Close RabbitMQ           
               conn.q.unsubscribe(ctag[conn.channel]);

            } catch (er) {
                console.log(":::::::: EXCEPTION SOCKJS (ON-CLOSE) ::::::::>>>>>>> " + er.stack);
            }
        });
    });

1

अपने इच्छित व्यवहार को प्राप्त करने के लिए, प्रत्येक उपभोक्ता को अपनी कतार से उपभोग करना चाहिए। एक बार में सभी कतारों को संदेश प्राप्त करने के लिए आपको एक गैर-प्रत्यक्ष विनिमय प्रकार (विषय, शीर्ष लेख, प्रशंसक) का उपयोग करना होगा।


1

जैसा कि मैंने आपके मामले का आकलन किया है:

  • मेरे पास संदेशों की एक कतार है (संदेश प्राप्त करने के लिए आपका स्रोत, इसका नाम q111 है)

  • मेरे पास कई उपभोक्ता हैं, जो एक ही संदेश के साथ अलग-अलग चीजें करना चाहते हैं।

आपकी समस्या यहाँ है जबकि 3 संदेश इस कतार द्वारा प्राप्त किए गए हैं, संदेश 1 का उपभोग उपभोक्ता A, अन्य उपभोक्ता B और C संदेश 2 और 3 का उपभोग करते हैं। जहाँ आपको सेटअप की आवश्यकता होती है, जहाँ rabbitmq संदेश की समान प्रतियों से गुजरता है ये तीनों संदेश (1,2,3) तीनों जुड़े उपभोक्ताओं (ए, बी, सी) को एक साथ मिलते हैं।

हालांकि इसे प्राप्त करने के लिए कई कॉन्फ़िगरेशन किए जा सकते हैं, एक सरल तरीका निम्नलिखित दो चरण अवधारणा का उपयोग करना है:

  • वांछित कतार (q111) से संदेशों को पिकअप करने के लिए एक गतिशील खरगोश-फावड़ा का उपयोग करें और एक कट्टर विनिमय (इस उद्देश्य के लिए विशेष रूप से बनाया और समर्पित) के लिए प्रकाशित करें।
  • अब अपने उपभोक्ताओं A, B & C (जो कतार से (q111) सुन रहे थे) को फिर से कॉन्फ़िगर करें ताकि प्रत्येक उपभोक्ता के लिए अनन्य और अनाम कतार का उपयोग करके सीधे इस फैनआउट एक्सचेंज से सुन सकें।

नोट: इस अवधारणा का उपयोग करते हुए सीधे स्रोत कतार (q111) से उपभोग न करें, क्योंकि पहले से ही उपभोग किए गए संदेशों को आपके फैनआउट एक्सचेंज को फावड़ा नहीं दिया जाएगा।

यदि आपको लगता है कि यह आपकी सटीक आवश्यकता को पूरा नहीं करता है ... तो अपने सुझाव पोस्ट करने के लिए स्वतंत्र महसूस करें :-)


0

यदि आप एमक्लिब लाइब्रेरी का उपयोग कर रहे हैं जैसा कि मैं कर रहा हूं, तो उनके पास पब्लिश / सब्सक्राइब रबबिटम्यूक ट्यूटोरियल के कार्यान्वयन का एक आसान उदाहरण है जो आपको मिल सकता है।


0

मुझे लगता है कि आपको फैन-आउट का उपयोग करके अपने संदेश भेजने की जांच करनी चाहिए एक्सचेंजर । इस तरह से आप विभिन्न उपभोक्ताओं के लिए एक ही संदेश प्राप्त करेंगे, तालिका के तहत RabbitMQ इस नए उपभोक्ताओं / ग्राहकों में से प्रत्येक के लिए अंतर कतार बना रहा है।

यह जावास्क्रिप्ट में ट्यूटोरियल उदाहरण देखने के लिए लिंक है https://www.rabbitmq.com/tutorials/tutorial-one-javascript.html


-1

इस परिदृश्य में एक दिलचस्प विकल्प है जिसका जवाब मुझे यहाँ नहीं मिला।

आप एक उपभोक्ता में "अपेक्षित" सुविधा वाले संदेशों को दूसरे में संसाधित करने के लिए उन्हें रद्द कर सकते हैं। आम तौर पर यह एक सही तरीका नहीं है, लेकिन शायद यह किसी के लिए काफी अच्छा होगा।

https://www.rabbitmq.com/nack.html

और लूप्स से सावधान रहें (जब सभी कंस्यूमर्स nack + requeue संदेश)!


1
मैं इसके खिलाफ अत्यधिक सलाह दूंगा, क्योंकि यह किसी भी तरह से पैमाने पर नहीं है। उपभोक्ताओं के लिए कोई आदेश नहीं है, आप उपभोक्ता बी की गारंटी नहीं दे सकते हैं जो इसकी आवश्यकता नहीं होगी, उपभोक्ता ए से पहले संदेश प्राप्त करता है जो इसे संसाधित करेगा और इसकी आवश्यकता होगी, उल्लिखित लूप एक समस्या है। जैसा कि आप कहते हैं "यह आम तौर पर सही तरीके से नहीं बोल रहा है", और मैं ऐसे परिदृश्य के बारे में नहीं सोच सकता जहां यह अन्य उत्तरों से बेहतर होगा।
केविन स्ट्रेचर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.