2015-04-28 13 views
9

के बीच Azure संचार हाय मैं क्लाउड सेवा का निर्माण कर रहा हूं जिसमें (इस पल के लिए) एक वेब और एक कार्यकर्ता भूमिका है। मेरा वांछित वर्कफ़्लो होगा: ब्राउज़र वेब भूमिका पर एक वेबएपी नियंत्रक को कॉल करता है, जो कतार (या सेवा बस) को संदेश भेजता है जिसे उसके बाद कार्यकर्ता की भूमिका द्वारा संसाधित किया जाता है। अब तक सब ठीक है। अब जब कार्यकर्ता भूमिका संदेश को संसाधित करती है तो मैं वेब भूमिका पर एक विधि को कॉल करना चाहता हूं, जो तब ब्राउज़र को संकेत देगा कि प्रसंस्करण पूरा हो गया है (सिग्नल के माध्यम से)। कृपया मुझे क्षमा करें अगर यह पूछने का सही स्थान नहीं है क्योंकि यह एक वास्तविक समस्या के बजाय "सर्वोत्तम अभ्यास" प्रश्न की तरह है।श्रमिक भूमिका और वेब भूमिका

  1. कार्यकर्ता भूमिका अद्यतन करता है एक तालिका पंक्ति (तालिका भंडारण में) प्रगति और कार्य के पूरा होने के साथ: मैं अब तक 2 दृष्टिकोण पर विचार किया है। वेब भूमिका के लिए कोई संकेत नहीं है। ब्राउजर सीधे तालिका भंडारण (आरईएसटी एपीआई के माध्यम से) को पढ़ता है और इसलिए जानता है कि कार्य पूरा हो गया है। यह अच्छी तरह से काम करता है (मैंने पहले ही इसका परीक्षण किया है), भले ही मुझे निरंतर मतदान के दृष्टिकोण पसंद न हों और मैं "घटना-आधारित" समाधान चाहता हूं। इसके अलावा, जब ग्राहक को यह जानकारी मिल जाती है कि प्रक्रिया समाप्त हो गई है, तो उसे ऑपरेशन पूरा होने के बाद अन्य ग्राहकों (सिग्नल के माध्यम से) प्रसारित करने के लिए एक वेब एपीआई विधि को अतिरिक्त कॉल करना होगा।

  2. (नीचे दिए गए कोड नमूना देखें) भी काम करता है (पहले से ही के रूप में अच्छी तरह से परीक्षण किया) एक साथ Interrole communication का उपयोग SignalR साथ

कोड का नमूना:

var protocol = "http";  
var ipAddress = RoleEnvironment.Roles["XXX.YYY.Web"] 
     .Instances[0] 
     .InstanceEndpoints.ToArray() 
     .Where(ep => ep.Value.Protocol == protocol) 
     .First() 
     .Value.IPEndpoint.ToString(); 

var stringEndpoint = string.Format("{0}://{1}", protocol, ipAddress.ToString());     
Trace.WriteLine("Retrieved endpoint address: " + stringEndpoint, "Information");    
HubConnection connection = new HubConnection(stringEndpoint); 
IHubProxy proxy = connection.CreateHubProxy("MyWebHub"); 
connection.Start().Wait(); 

//later... 

proxy.Invoke("ProgressUpdated", clientId, progress); 

मेरे सवाल यह है: वहाँ अन्य रहे हैं (बेहतर) दिशा में संवाद करने के तरीके श्रमिक भूमिका -> वेब भूमिका? यही है, जब एक कार्यकर्ता की भूमिका ने अपनी प्रसंस्करण समाप्त कर दी है तो वेब भूमिका पर एक विधि को ट्रिगर करें? वेब भूमिका पर विधि सिग्नलआर के माध्यम से सभी ग्राहकों को अपडेट प्रसारित करेगी। मैंने Event Hubs पर भी एक नज़र डाली है, लेकिन मेरी समझ के लिए इवेंट उपभोक्ता अभी भी कार्यकर्ता की भूमिका पर चलेंगे।

उत्तर

2

ठीक है कुछ अतिरिक्त प्रयास और अनुसंधान का एक सा मैं एक संभव समाधान के साथ आए हैं के बाद ... मैं वेब भूमिका की onStart विधि (नहीं कार्यकर्ता भूमिका के अंदर इस कोड

AzureServiceBus.QueueClient.OnMessage((message) => 
      { 
       try 
       { 
        // Process message from queue 
        Trace.WriteLine("Message received: " + ((BrokeredMessage)message).Label); 

        var breezeController = new BreezeController(); 
        breezeController.TestSignal(); 

        // Remove message from queue 
        message.Complete(); 
       } 
       catch (Exception) 
       { 
        // Indicates a problem, unlock message in queue 
        message.Abandon(); 
       } 
      }); 

उपयोग कर रहा था) ताकि मैं इस मामले में वेब रोल (टेस्टसिग्नल() के अंदर अपनी विधि का संदर्भ दे सकूं) लेकिन यह पता चला कि IHubContext हमेशा इस ऑनमेज़ेज इवेंट हैंडलर के भीतर से बुलाया गया था, क्योंकि यह एक अलग ऐपडोमेन से संबंधित है (बहुत संभावना है) इस प्रकार सिग्नलआर का स्थिर हब भी साझा नहीं किया गया था। इसलिए मैंने ग्लोबल.एएसएक्स सीएस के अंदर यह वही संपूर्ण कोड ले जाया है ताकि वह वही ऐपडोमेन साझा कर सके और अब यह काम करता है। मुझे लगता है कि मैं इस दृष्टिकोण के साथ रहूंगा क्योंकि मुझे लगातार मतदान से ज्यादा पसंद है।

+0

मुझे यह कार्यान्वयन पसंद है! पहले कभी इस पैटर्न के बारे में सोचा नहीं, और यह बहुत चिकना है। अच्छी नौकरी! – Rogala

0

मुझे लगता है कि आपके पास इसे प्राप्त करने के लिए पहले से ही पर्याप्त ज्ञान और कार्यान्वयन अनुभव है। सिग्नल का उपयोग करना शानदार दृष्टिकोण है, मैंने आपसे सीखा।

एक और छोटा-अलग-अलग दृष्टिकोण, मैं Azure Scheduler का उपयोग कर GET संदेश को वेबरोल भेजने के लिए लगातार मतदान का उपयोग करता हूं।

आईएमओ, वेबपी सर्वर की प्रकृति के रूप में, मतदान वेब सर्वर को डिज़ाइन करने के लिए सबसे उपयुक्त और विश्वसनीय दृष्टिकोण है।

+0

प्रतिक्रिया के लिए थैंक्स, मैं एक विशेषज्ञ नहीं हूं लेकिन मुझे लगता है कि शेड्यूलर कुछ अलग और सामान्य रूप से मुझे इस दृष्टिकोण को पसंद नहीं है। हां, मतदान कार्य करता है और इसमें वेब भूमिका कम होती है, लेकिन फिर भी मुझे नहीं लगता कि यह जाने का सबसे अच्छा तरीका है ... –

0

प्रश्न के लिए थोड़ा देर हो चुकी है :) लेकिन हमने जो कार्यान्वित किया है वह प्रतिक्रिया कतार और सत्र आईडी निर्दिष्ट करना है जिस पर कार्य भूमिका में संदेश भेजने के बाद वेब भूमिका का इंतजार है।आप इसे tweak प्रतिक्रिया अवरुद्ध जबकि वेब भूमिका (हमारे परिदृश्य में हम विशेष रूप से प्रतीक्षा करने के लिए करना चाहता था)

WebRole

string sessionId = Guid.NewGuid().ToString(); 
[...] 
// put message in sync queue 
var message = new BrokeredMessage(request) 
{ 
    ReplyToSessionId = sessionId 
}; 
await ServiceBusConnector.Instance.SyncClient.SendAsync(message); 

// now listen to reply on session response queue (only accepts message on same session id) 
MessageSession session = await ServiceBusConnector.Instance.SyncResponseClient.AcceptMessageSessionAsync(sessionId); 

BrokeredMessage responseMessage = await session.ReceiveAsync(TimeSpan.FromMinutes(5)); 
await responseMessage.CompleteAsync(); 
await session.CloseAsync(); 

Response response = responseMessage.GetBody<Response>(); 
// process Worker Role's response 

कार्यकर्ता भूमिका

// if a ReplyToSessionId has been specified, it means that the sender is 
    // actively waiting for a response 
    if (!String.IsNullOrEmpty(receivedMessage.ReplyToSessionId)) 
    { 
     // now respond on sync response queue 
     var responseMessage = new BrokeredMessage(response) 
     { 
      SessionId = receivedMessage.ReplyToSessionId 
     }; 

     // consider allowing client to specify a ReplyTo response queue (not needed for now) 
     await ServiceBusConnector.Instance.SyncResponseClient.SendAsync(responseMessage); 
    } 
0

इसके अलावा कार्यकर्ता भूमिका जबाब इंतजार कर रहा है से बचने के लिए कर सकते हैं HttpClient के माध्यम से सीधे ऐप पर सीधे संवाद करने के लिए Jessie's approach देखें।

public class Functions 
{ 
    public static async Task ProcessQueueMessage([QueueTrigger("jobqueue")] Guid jobId, TextWriter log) 
    { 
     for (int i = 10; i <= 100; i+=10) 
     { 
      Thread.Sleep(400); 

      await CommunicateProgress(jobId, i); 
     } 
    } 

    private static async Task CommunicateProgress(Guid jobId, int percentage) 
    { 
     var httpClient = new HttpClient(); 

     var queryString = String.Format("?jobId={0}&progress={1}", jobId, percentage); 
     var request = ConfigurationManager.AppSettings["ProgressNotificationEndpoint"] + queryString; 

     await httpClient.GetAsync(request); 
    } 
} 
संबंधित मुद्दे