2015-06-09 36 views
16

Sto lavorando a un'applicazione di servizio di manutenzione di Azure qui dove ho determinati attori che devono ricevere ping/ganci da altri servizi su richiesta. L'applicazione è una sorta di motore di distribuzione evento che è destinato a lavorare qualcosa di simile:Motivo pubblicazione/sub in Fabric Service di Azure

  • Un router attore evento che può prendere un evento in e quindi si prenderà cura di distribuire tale evento a tutti gli abbonati di quel tipo di evento.
  • 0..N attori di sottoscrizione di eventi che in qualche modo devono informare il router sul tipo di eventi a cui desiderano iscriversi e su come desiderano che vengano recapitati (sincronizzazione o asincronia).
  • Quando l'attore del router degli eventi riceve un evento del tipo MyEvent, identifica ciò che gli utenti sono in ascolto e il modo in cui desiderano che l'evento venga recapitato. Per la consegna asincrona, verrà visualizzato un messaggio in un argomento del bus di servizio di Azure. Tuttavia, per la consegna sincrona, l'attore del router invocherà direttamente il metodo di iscrizione sugli attori sottoscrittori, in attesa della risposta.

La maggior parte di questo è abbastanza semplice, ma non sono del tutto sicuro di come riuscirò a eseguire la consegna sincrona di questi eventi. Non voglio che l'attore del router degli eventi sia in alcun modo a conoscenza degli interni degli attori che si iscrivono agli eventi, tuttavia con le attuali implementazioni ActorProxy e simili, è necessario avere accesso alle interfacce per invocare metodi su altri attori.

Dire che mi iscrivo a un tipo di evento, informando il router degli eventi che il mio indirizzo è fabric:/MyApp/MyEventSubscriberActor e che voglio iscrivermi allo MyEvent. Esiste un modo ragionevole all'interno delle API di Service Fabric Posso richiamare in modo programmatico un metodo su quell'attore senza (ad esempio OnEventAsync(MyEvent ev) utilizzando il metodo ActorProxy.Create<IMyEventSubscriberActor>()? Il codice sorgente di queste API non sembra essere pubblicamente disponibile, quindi non ho un modo diretto

+0

Sono po 'curioso sul perché si vuole fare sia sincrona e asincrona a meno alcuni eventi desideravano essere instradati a un'applicazione diversa che si desidera inviare all'argomento del bus di servizio di Azure. L'altra osservazione che ho è, rendendo un pub/sub non ti aiuterà con scalabilità perché l'attore router è bloccato fino a quando l'attore sottoscrittore completa l'attività.Hai pensato al "fuoco e dimentica" in cui gli attori dell'abbonato scelgono gli eventi da un ReliableQueue. –

+0

In realtà ho pensato un po 'a questo me stesso; Penso che starò bene solo facendo una consegna sincrona degli eventi a tutti gli effetti e poi far sì che il sottoscrittore determini se deve elaborare immediatamente l'evento o semplicemente eseguirlo su un ReliableQueue per l'elaborazione asincrona. Grazie per l'input. –

+0

Penso che con un fuoco e dimentichi il metodo asincrono, potresti essere in grado di elaborare più eventi rispetto all'elaborazione del modo sincrono. –

risposta

25

L'attore di sottoscrizione evento può implementare un'interfaccia di sottoscrizione evento che contiene un metodo "event-available". Può passare tale interfaccia a un metodo "subscribe-to-event" su l'interfaccia per l'interprete del router degli eventi

L'interfaccia per gli attori del router degli eventi può mantenere un riferimento all'interfaccia di sottoscrizione come parte del suo stato. Quando si verifica l'evento di interesse per l'utente, può chiamare il metho "evento disponibile" d sull'interfaccia che ha ricevuto e salvato in precedenza. Tutto questo può essere fatto senza creare esplicitamente un proxy attore per comunicare con l'attore dell'abbonamento all'evento (l'infrastruttura di serializzazione degli attori lo fa sotto il cofano).

Ecco un esempio molto semplice che omette il tipo di evento, presuppone solo un sottoscrittore, ecc., Ma dovrebbe darti un'idea della tecnica.

Interfacce:

interface IEventRouter : IActor 
{ 
    void Subscribe(IEventSubscriber subscriber); 
} 

interface IEventSubscriber : IActor 
{ 
    void EventAvailable(); 
} 

evento Codice abbonato:

class EventSubscriber : Actor, IEventSubscriber 
{ 
    void SubscribeToEvent() 
    { 
     IEventRouter router = ActorProxy.Create<IEventRouter>("fabric:/MyApp/MyEventRouterActor"); 
     router.Subscribe(this); 
    } 

    public void EventAvailable() 
    { 
     // Process the event 
    } 
} 

Evento Codice router:

// Define actor state 
[DataContract] 
class RouterState 
{ 
    [DataMember] 
    public IEventSubscriber Subscriber; 
} 

// Define actor 
class EventRouter : Actor<RouterState>, IEventRouter 
{ 
    public void Subscribe(IEventSubscriber subscriber) 
    { 
     this.State.Subscriber = subscriber; 
    } 

    void OnEventAvailable() 
    { 
     this.State.Subscriber.EventAvailable(); 
    } 
}  
+1

Oh, wow, questo in realtà era abbastanza elegante e qualcosa a cui non avevo pensato. La mia mente era molto bloccata nel pensare che un'interfaccia significasse un attore; il riutilizzo di interfacce su più tipi di attori per questo scopo non mi era nemmeno passato per la testa. Apprezzo l'input, questo probabilmente andrà bene. –

+6

È super utile sapere che l'infrastruttura di serializzazione gestisce la mappatura del proxy interfaccia-attore. Grazie! Ciò rende * questo * molto * più facile di quanto avessi temuto. –

+1

Per pub/sub engine/framework si utilizza questo pacchetto nuget ServiceFabric.PubSubActors. Il codice è disponibile in github: https://github.com/loekd/ServiceFabric.PubSubActors – alltej

Problemi correlati