मेरे पास एक वेब ऐप है जो Azure सर्विस बस पर संदेश भेजता है और उत्तर की प्रतीक्षा करता है:

var response = await this.createClient.GetResponse<Models.Response<CommandResponse>>(message, cancellationToken);

मेरे पास एक सेवा बस ट्रिगर के साथ एक Azure फ़ंक्शन है जो संदेशों का उपभोग करता है:

        [FunctionName("CommandHandler")]
        public Task HandleCommandAsync(
            [ServiceBusTrigger("input-queue", Connection = "AzureWebJobsServiceBus"), ServiceBusAccount("ServiceBus")]
            Message message,
            IBinder binder,
            ILogger logger,
            CancellationToken cancellationToken)
        {
            logger.LogInformation("Command Handler Function Invoked.");

            var result = System.Text.Encoding.UTF8.GetString(message.Body);
            var d = JsonConvert.DeserializeObject<dynamic>(result);
            string messageType = d.message.messageType.Value;

            var handler = Bus.Factory.CreateBrokeredMessageReceiver(
                binder,
                cfg =>
                    {
                        cfg.CancellationToken = cancellationToken;
                        cfg.SetLog(logger);
                        cfg.InputAddress = new Uri($"{this.secrets.Value.ServiceBusUri}/input-queue");
                        cfg.UseRetry(x => x.Intervals(10, 100, 500, 1000));

                            cfg.Consumer(() => this.customerConsumer);
                    });

            var handlerResult = handler.Handle(message);
            logger.LogInformation("Command Handler Function Completed.");
            return handlerResult;
        }

वेब ऐप से संदेश भेजने के लिए मुझे उपभोक्ताओं को कॉन्फ़िगर करना होगा। मुझे यकीन नहीं है कि यह क्यों आवश्यक है, क्योंकि वेब ऐप को उपभोक्ताओं को सीधे संदर्भित करने की आवश्यकता नहीं होनी चाहिए, लेकिन निम्नलिखित कोड के बिना, कोई संदेश नहीं भेजा जाता है।

            services.AddMassTransit(
                x =>
                {
                    x.AddConsumer<CustomerConsumer>();

                    x.AddBus(
                            provider => Bus.Factory.CreateUsingAzureServiceBus(
                                cfg =>
                                    {
                                        var host = cfg.Host(secrets.AzureWebJobsServiceBus, h => { });

                                        cfg.ReceiveEndpoint(
                                            host,
                                            "input-queue",
                                            ep =>
                                                {
                                                    ep.ConfigureConsumer<CustomerConsumer>(provider);

                                                    ep.PrefetchCount = 16;
                                                    ep.UseMessageRetry(r => r.Interval(2, 100));
                                                });
                                    }));

                    x.AddRequestClient<RegisterNewCustomerCommand>();
                });

संदेश भेजे जाने के बाद समस्या है, कभी-कभी CommandHandler फ़ंक्शन ऐप ट्रिगर करता है और उपभोक्ता के Handle संदेश को आमंत्रित करता है।

लेकिन कभी-कभी वेब ऐप अनजाने में सीधे उपभोक्ता को आमंत्रित करता है (क्योंकि उपभोक्ता स्टार्टअप में पंजीकृत है और कतार में संदेशों को सुन रहा है)।

यह मेरे लिए अवांछित है। मापनीयता के लिए केवल Azure फ़ंक्शन को उपभोक्ताओं को आमंत्रित करना चाहिए। इसके अलावा, उपभोक्ताओं के पास निर्भरता इंजेक्शन है जो केवल फ़ंक्शन ऐप के WebHostStartUp में पंजीकृत हैं, इसलिए उपभोक्ताओं को सीधे वेब ऐप से लागू होने पर त्रुटि मिलती है।

प्रश्न: मैं वेब ऐप और उपभोक्ताओं के बीच निर्भरता को कैसे तोड़ सकता हूं ताकि वे कभी भी सीधे वेब ऐप द्वारा नहीं बल्कि हमेशा फंक्शन ऐप ट्रिगर द्वारा बुलाए जाएं? क्या कोई तरीका है जिससे मैं वेब ऐप की स्टार्टअप विधि में उपभोक्ताओं को जोड़ने/कॉन्फ़िगर करने से बच सकता हूं, जबकि अभी भी वेब ऐप को GetResponse के माध्यम से संदेश भेजने में सक्षम बनाता हूं?

अद्यतन - समाधान

ASP.NET Core 2.2 स्टार्टअप को उपभोक्ताओं के लिए किसी संदर्भ की आवश्यकता नहीं है (जब तक कि मेरे विपरीत आप नहीं चाहते कि आपका वेब ऐप भी संदेशों का उपभोग करे)।

आपको अपने AddRequestClient में कतार के पथ सहित सेवा बस URL जोड़ने की आवश्यकता है। स्वीकृत उत्तर देखें।

यह मेरे लिए काम किया।


            services.AddMassTransit(
                x =>
                    {
                        x.AddBus(
                            provider => Bus.Factory.CreateUsingAzureServiceBus(
                                cfg =>
                                    {
                                        cfg.Host(
                                            secrets.AzureWebJobsServiceBus,
                                            h => { h.TransportType = TransportType.Amqp; });
                                    }));

                        var serviceBusUri = new Uri($"{settings.ServiceBusUri}/input-queue");
                        x.AddRequestClient<RegisterNewCustomerCommand>
                    });
        }

0
Dan Cook 14 अगस्त 2019, 17:54

1 उत्तर

सबसे बढ़िया उत्तर

आपको उपभोक्ता को अपने क्लाइंट-साइड एपीआई पर रखने की आवश्यकता नहीं है। केवल एक चीज जो मैं सोच सकता हूं वह यह है कि आपके पास टोपोलॉजी सेटअप सही नहीं था।

  1. सुनिश्चित करें कि कतार पहले से मौजूद है, क्योंकि फ़ंक्शन कतार नहीं बनाते हैं।
  2. क्यू के लिए यूआरआई पता कॉन्फ़िगर करें, ताकि आपका वेब एपीआई इसे AddRequestClient कॉल पर एक तर्क (_sb://host.../input-queue) के रूप में निर्दिष्ट कर सके।
  3. फायदा!

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

अनुरोध क्लाइंट के लिए क्लाइंट ऐप में यूआरआई जोड़ने से समस्या का समाधान होना चाहिए, और सीधे कतार में कमांड भेजना चाहिए।

1
Chris Patterson 14 अगस्त 2019, 19:18