2015-04-28 23 views
9

Merhaba Bir web hizmeti ve bir çalışan rolü (şu anda) olan bir Bulut Hizmeti oluşturuyorum. İstenilen iş akışım şöyle olurdu: tarayıcı, web rolünde bir webApi denetleyicisini çağırır; bu, daha sonra iş rolü tarafından işlenen bir sıraya (veya hizmet veri yoluna) ileti gönderir. Çok uzak çok iyi. İşçi rolü mesajın işlenmesini tamamladığında, web rolünde bir yöntem aramak istiyorum, bu işlem tarayıcıyı tamamladığını (daha sonra SignalR ile) bildirecektir. Soruyu sormak için doğru yer değilse lütfen bana izin verin, çünkü bu daha çok “en iyi uygulama” sorusu gibi, gerçek bir sorun gibi.İşçi Rolü ve Web Rolü arasındaki Azure iletişimi

  1. işçi rolü (tablo depolama) bir tablo satırını günceller ilerleme ve görevin tamamlanması ile: Şimdiye kadar 2 yaklaşımları kabul var. Web rolüne işaret yok. Tarayıcı, tablo depolarını doğrudan (REST api üzerinden) okur ve bu nedenle görevin ne zaman tamamlandığını bilir. Bu, sürekli oylama yaklaşımını beğenmemek ve “olay-temelli” bir çözüme sahip olmak isterim. Ayrıca, müşteri işlemin bittiği bilgisini aldıktan sonra, işlemin tamamlandığını diğer istemcilere (SignalR üzerinden) yayınlamak için bir web api yöntemine ek bir çağrı yapmalıdır.

  2. (aşağıdaki kod örneğini bakınız) da çalışır (zaten de test) SignalR ile birlikte Interrole communication kullanma

kod örneği:

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); 

Sorum şu: (orada daha iyi diğer vardır) Yönlendirme yolları nasıl Çalışıyor? -> Web rolü? Yani, bir işçi rolünün işlenmesini tamamladığında web rolünde bir yöntem tetiklenir mi? Web rolündeki yöntem daha sonra güncellemeyi tüm istemcilere SignalR üzerinden yayınlayacaktır. Aynı zamanda Event Hubs'a da baktım ama benim için, Tüketici Tüketici rolünü üstlenmeye devam edecek.

cevap

2

Tamam ben olası bir çözüm ile geldi bazı ekstra girişimleri ve biraz araştırma sonrasında ... Ben Web Rolünün OnStart yöntemi (DEĞİL İşçi rolü içine bu kodu

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(); 
       } 
      }); 

kullanıyordum) Böylece, web rolümdeki yöntemimi (bu durumda TestSignal()) referans alabilmem için farklı bir UygulamaAlanı'na (büyük olasılıkla) ait olduğu için, bu OnMessage olay işleyicisinden çağrıldığında IHubContext öğesinin her zaman boş olduğu ortaya çıktı. bu nedenle, sinyal Hub'ın statik Hub'ı bile paylaşılmadı. Bu yüzden aynı kodun tamamını Global.asax.cs içine taşıdım, böylece aynı AppDomain'i paylaşacak ve şimdi çalışıyor. Bu yaklaşımda kalacağım çünkü sürekli oylamadan çok daha fazlasını seviyorum.

+0

Bu uygulamayı seviyorum! Bu deseni daha önce hiç düşünmemiştim ve oldukça kaygan. İyi iş! – Rogala

0

Ben zaten bunu başarmak için yeterli bilgi ve uygulama deneyimine sahip düşünüyorum. SignalR kullanarak parlak bir yaklaşım, sizden öğrendim.

Başka bir biraz farklı bir yaklaşım, Azure Scheduler kullanarak WebRole'a göndermek için sabit sorgulama kullanıyorum.

IMO, WebAPI sunucusunun bir doğası olarak, yoklama tasarlanmış hangi web sunucusu takip etmek en uygun ve güvenilir bir yaklaşımdır.

+0

Geri bildirim için teşekkürler, uzman değilim, ancak Zamanlayıcı'nın farklı bir amaç için olduğunu düşünüyorum ve genel olarak bu yaklaşımı sevmiyorum. Evet, oy verme işleri ve web rolünü daha az içerir, ancak hala gitmek için en iyi yol olduğunu düşünmüyorum ... –

0

geç soruya Biraz :) ama ne biz hayata geçirdik bir yanıt kuyruğu ve oturum kimlikleri belirtmektir web rol işçisi rolüne mesaj gönderdikten sonra bekliyor hangi.Sen web rolü (bizim senaryoda biz özellikle beklemek istedim)

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 

İşçi Rolü Ayrıca

// 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

işçi rolü cevap beklerken cevabı engelleme önlemek için ince ayar yapabilirsiniz HttpClient aracılığıyla doğrudan uygulamaya geri iletişim kurmak için Jessie's approach kontrol edin.

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); 
    } 
} 
İlgili konular