Condividi tramite


Il presente articolo è stato tradotto automaticamente.

Windows Azure Insider

Bus di servizio di Windows Azure: modelli di messaggistica mediante sessioni

Bruno Terkaly
Ricardo Villalobos

Scarica il codice di esempio

Bruno Terkaly Ricardo VillalobosIn uno dei nostri precedenti articoli, abbiamo discusso l'importanza di utilizzare modelli di messaggistica nel cloud per disaccoppiare soluzioni e promuovere architetture software facile in scala. (Vedere "Confronto Windows Azure code e servizio Bus code" a msdn.microsoft.com/magazine/jj159884.) Accodamento messaggi è uno di questi modelli di messaggistica, e la piattaforma Windows Azure offre due opzioni principali per implementare questo approccio: Servizi di archiviazione coda e servizio Bus code, entrambi i quali scenari dove i consumatori più competono per ricevere ed elaborare ciascuno dei messaggi in una coda. Questo è il modello canonico per sostenere i carichi di lavoro variabile nella nube, dove ricevitori possono essere dinamicamente aggiunti o rimossi basato sulla dimensione della coda, che offre un meccanismo di load balancing e failover per il back-end (vedi Figura 1).

Queuing Messaging Pattern: Each Message Is Consumed by a Single Receiver
Figura 1 modello Accodamento di messaggistica: Ogni messaggio è consumato da un unico ricevitore

Anche se il modello di messaggistica di accodamento è una grande soluzione per disaccoppiamento semplice, ci sono situazioni dove ogni ricevitore richiede la propria copia del messaggio, con l'opzione di scartarne alcuni messaggi basati su regole specifiche. Un buon esempio di questo tipo di scenario è mostrato Figura 2, che illustra una sfida comune che al dettaglio società faccia l'invio di informazioni a più rami, come l'ultimo catalogo prodotti o un listino prezzi aggiornato.

Publisher/Subscriber Messaging Pattern: Each Message Can Be Consumed More Than Once
Figura 2 Publisher/Subscriber Pattern di messaggistica: Ogni messaggio può essere consumato più di una volta

Per queste situazioni, il modello di pubblicazione/sottoscrizione è una migliore vestibilità, dove i ricevitori esprimono semplicemente un interesse in una o più categorie di messaggi, connessione a un abbonamento indipendente che contiene una copia del messaggio flusso. Il Bus di servizio Windows Azure implementa il pattern messaggistica editore/sottoscrizione attraverso argomenti e abbonamenti, che migliora notevolmente la capacità di controllare come vengono distribuiti i messaggi, sulla base di filtri e regole indipendenti. In questo articolo spiegheremo come applicare queste funzionalità di Windows Azure Service Bus utilizzando un semplice scenario di vita reale, assumendo i seguenti requisiti:

  1. Prodotti devono essere ricevuti nell'ordine, basato sulla pagina di catalogo.
  2. Alcuni dei negozi non portano le categorie specifiche di catalogo e prodotti in queste categorie devono essere filtrati per ogni negozio.
  3. Nuove informazioni sul catalogo non dovrebbe essere applicate al sistema negozio finché non sono arrivati tutti i messaggi.

Tutti gli esempi di codice per questo articolo sono stati creati con Visual Studio 2012, utilizzando c# come linguaggio di programmazione. Avrete anche bisogno Windows Azure SDK versione 1.8 per gli sviluppatori .NET e l'accesso a una sottoscrizione Windows Azure.

Impostazione il Blueprint di messaggistica per il progetto

Prima di scrivere alcun codice, è necessario definire l'entità diverse (argomenti e abbonamenti) che entreranno a far parte del workflow messaggistica. Questo può essere compiuto accedendo al portale di Windows Azure a manage.windowsazure.com. Effettuare il login con le credenziali e attenersi alla seguente procedura:

  1. Fare clic su Crea nuova icona in basso a sinistra del portale di gestione.
  2. Fare clic sull'icona servizi APP, quindi sul servizio BUS argomento e infine su creare CUSTOM (vedere Figura 3).
  3. Nella prima schermata di dialogo, immettere il nome del tema e selezionare l'appropriata regione e Windows Azure ID sottoscrizione. Se questo è il primo spazio dei nomi nella regione selezionata, la procedura guidata suggerirà una coda dello spazio dei nomi: [il tuo nome entità]-ns. È possibile modificare questo valore.
  4. Clicca sul marchio successivo (freccia verso destra) per inserire le restanti proprietà. È possibile mantenere i valori predefiniti. Fare clic sul segno di spunta per creare l'argomento.
  5. Fare clic sull'icona sulla barra di navigazione a sinistra per ottenere un elenco di spazi dei nomi del servizio Bus. Si noti che non si potrebbe vedere lo spazio dei nomi elencato immediatamente. Ci vogliono pochi secondi per creare lo spazio dei nomi e aggiornare l'interfaccia del portale.
  6. Selezionare l'argomento che avete appena creato dall'elenco e fare clic sulla chiave di accesso, che può essere trovato sul fondo dello schermo. Registrare la stringa di connessione completa per un uso successivo.
  7. Nella parte superiore dello schermo di Windows Azure portale, fare clic su sottoscrizioni e poi su Crea un nuovo abbonamento. Nella finestra di dialogo popup, immettere un nome (nel nostro esempio abbiamo usato "Store1Sub") e fare clic sulla freccia per continuare.
  8. Nella schermata successiva, mantenere i valori predefiniti, ma assicuratevi di selezionare l'opzione di abilitare sessioni. Fare clic sul segno di spunta per creare la sottoscrizione. Sessioni saranno utilizzate dai sottoscrittori per recuperare i messaggi in ordine sequenziale.
  9. Ripetere i passaggi 7 e 8 per ciascuno dei tre negozi.

Creating a New Service Bus Topic Using the Windows Azure Portal
Figura 3 creazione di un nuovo servizio Bus argomento utilizzando il Windows Azure Portal

Una volta che gli argomenti e gli abbonamenti sono stati creati, è possibile accedere anche loro direttamente in Visual Studio. Per farlo, aprire Esplora Server (vista | Esplora server) ed espandere il nodo Windows Azure Service Bus (vedi Figura 4). Tasto destro del mouse sul nodo Windows Azure Service Bus e selezionare Aggiungi nuova connessione. Immettere il nome del Namespace, il nome dell'emittente (di solito "proprietario") e chiave di accesso dell'emittente registrò quando lo spazio dei nomi di Windows Azure è stato creato nel portale.

Creating a Service Bus Topic and Subscriptions Using the Visual Studio Tools
Figura 4 creazione di un servizio Bus argomento e sottoscrizioni tramite Visual Studio Tools

Tieni presente che è possibile creare e gestire queste entità utilizzando le classi nello spazio dei nomi Microsoft.ServiceBus.Messaging, TopicClient e SubscriptionClient, che vengono utilizzati più avanti in questo articolo.

Una volta che è stata creata la struttura di base per il flusso di lavoro di messaggistica, noi ti simulare il traffico utilizzando due applicazioni console create in Visual Studio, come indicato nel Figura 5. La prima applicazione di console, MSDNSender, invierà il catalogo prodotti. Il secondo, MSDN­ricevitore, riceveranno le informazioni in ognuno dei negozi. Ti analizziamo il codice nelle sezioni seguenti. Nel modello di Pub/Sub, il MSDNSender è l'editore e il MSDNReceiver è l'abbonato.

Visual Studio Solution to Simulate the Products Catalog Scenario
Figura 5 soluzione di Visual Studio per simulare lo Scenario del catalogo prodotti

L'invio del catalogo prodotti dalla sede centrale

Come si può vedere Figura 2, quartier generale (l'editore) invia messaggi a un argomento. Questa logica è rappresentata dal codice nel file principale, Program. cs, una parte del progetto MSDNSender. Program incapsula la logica e il codice per inviare un elenco di prodotti come singoli messaggi all'argomento. Diamo un'occhiata alle diverse sezioni, a partire con il metodo Main. Notare che prima di tutto creiamo un client per l'argomento, come segue:

// Create a topicClient using the
// Service Bus credentials
TopicClient topicClient =
  TopicClient.CreateFromConnectionString(
  serviceBusConnectionString, topicName);

Una volta creato un topicClient, l'editore può inviare messaggi tramite esso. L'elenco dei prodotti da inviare è memorizzato in un file XML chiamato ProductsCatalog.xml, che contiene un elenco di 10 soggetti, prodotto che sarà trasformata in una matrice di oggetti. I prodotti verranno poi vengono mappati nelle classi, catalogo e prodotto memorizzate nel file CS:

// Deserialize XML file with Products, and store them in an object array
Catalog catalog = null;
string path = "ProductsCatalog.xml";
XmlSerializer serializer = new XmlSerializer(typeof(Catalog));
StreamReader reader = new StreamReader(path);
catalog = (Catalog) serializer.Deserialize(reader);
reader.Close();

Ogni prodotto nella matrice catalogo presenta la struttura indicata Figura 6.

Figura 6 classe rappresentazione per i prodotti nel catalogo

public class Product
  {
    [System.Xml.Serialization.XmlElement("ProductId")]
    public string ProductId { get; set; }
    [System.Xml.Serialization.XmlElement("ProductName")]
    public string ProductName { get; set; }
    [System.Xml.Serialization.XmlElement("Category")]
    public string Category { get; set; }
    [System.Xml.Serialization.XmlElement("CatalogPage")]
    public int CatalogPage { get; set; }
    [System.Xml.Serialization.XmlElement("MSRP")]
    public double MSRP { get; set; }
    [System.Xml.Serialization.XmlElement("Store")]
    public string Store { get; set; }
  }

All'interno del ciclo di matrice, una chiamata al metodo CreateMessage estrae diverse proprietà degli oggetti prodotti e li assegna al messaggio da inviare. Due proprietà richiedono attenzione supplementare:

if (isLastProductInArray)
  message.Properties.Add("IsLastMessageInSession", "true");
message.SessionId = catalogName;

Le sessioni sono estremamente importanti, perché permettono al ricevitore di determinare se sono arrivati tutti i messaggi che appartengono a un gruppo logico specifico. In questo caso, impostando la proprietà SessionId messaggio, noi stiamo specificando che il ricevitore non dovrebbe utilizzare le informazioni del catalogo fino a dopo che sono arrivati tutti i messaggi con lo stesso valore catalogName. Inoltre, per l'ultimo prodotto della matrice, stiamo aggiungendo una nuova proprietà: IsLastMessageInSession, che permetterà i ricevitori determinare se l'ultimo messaggio della sessione è arrivato, e il catalogo può essere completamente elaborati. Figura 7 MSDNSender in esecuzione viene illustrato.

Execution of the MSDNSender Project
Figura 7 esecuzione del progetto MSDNSender

Ricevere il catalogo dei prodotti tramite le sottoscrizioni presso i negozi

Ora che il catalogo e i prodotti sono stati inviati al soggetto e copiato i diversi abbonamenti, Let's rivolgere la nostra attenzione per il progetto MSDNReceiver, dove i messaggi vengono ricevuti ed elaborati. Si noti che nel metodo Main del file Program. cs, il codice crea un client per la sottoscrizione basata sulle informazioni fornite dall'utente tramite un Read­linea di comando. Gli utenti sono tenuti a inserire il loro numero di archivio, che riflette i messaggi che desiderano ricevere. In breve, ogni negozio ramo è interessato solo con i messaggi che si applicano a tale archivio:

Console.WriteLine("Enter Store Number");
  string storeNumber = Console.ReadLine();
  Console.WriteLine("Selecting Subscription for Store...");
  // Create a Subscription Client to the Topic
  SubscriptionClient subscriptionClient =
    SubscriptionClient.CreateFromConnectionString(
    serviceBusConnectionString, topicName,
    "Store" + storeNumber.Trim() + "Sub",
    ReceiveMode.PeekLock);

Perché noi stiamo ricevono messaggi da sottoscrizioni basate su sessioni (come spiegato nella sezione precedente), abbiamo bisogno di chiedere quella successiva utilizzando la seguente riga di codice:

MessageSession sessionReceiver =
  subscriptionClient.AcceptMessageSession(TimeSpan.FromSeconds(5));

Fondamentalmente, ciò significa che il client controllerà per eventuali messaggi di to-be-elaborati nella sottoscrizione — quelli cui proprietà SessionId non è null — e se tali messaggi non vengono rilevati entro un periodo di cinque secondi, la richiesta sarà tempo ­fuori, che chiude l'applicazione ricevente. D'altra parte, se una sessione viene trovata, verrà chiamato il metodo ReceivingSessionMessages. Prima di saltare in questo pezzo di codice, esaminiamo il concetto di stato della sessione, che consente allo sviluppatore di memorizzare informazioni che possono essere utilizzati mentre vengono ricevuti i messaggi che appartengono alla stessa transazione. In questo caso, stiamo usando lo stato della sessione di "ricordare" l'ultima pagina di catalogo che è stato ricevuto, come pure i messaggi — prodotti — che è arrivato fuori ordine.

Sulla base di questo, qui è il flusso di lavoro nel codice:

  1. Viene ricevuto il messaggio corrente nella ReceiveSession­i messaggi di metodo (vedere Figura 8), che si basa sul metodo ProcessMessage (Figura 9) per elaborarlo.
  2. All'interno del metodo ProcessMessage, se il messaggio è fuori sequenza, esso viene automaticamente posticipata e relativo ID archiviati nello stato sessione. In caso contrario, esso ha contrassegnato come "completo" e rimosso dalla sottoscrizione. Inoltre, il prossimo atteso sequenza — pagina catalogo — è memorizzato nella sessione.
  3. Dopo che è stato elaborato il messaggio ricevuto corrente, il codice successivo in ReceiveSessionMessages verifica differita messaggio ID della sessione e tenta di elaborare il loro nuovo basato sull'ultima pagina di catalogo.
  4. Una volta che tutti i messaggi sono stati ricevuti per la sessione, il ricevitore è chiuso.

Figura 8 il metodo ReceivedSessionMessages nel codice

static void ReceiveSessionMessages(MessageSession receiver)
  {
    // Read messages from subscription until subscription is empty
    Console.WriteLine("Reading messages from subscription {0}", 
      receiver.Path);
    Console.WriteLine("Receiver Type:" + receiver.GetType().Name);
    Console.WriteLine("Receiver.SessionId = " + receiver.SessionId);
    SequenceState sessionState = GetState(receiver);
    BrokeredMessage receivedMessage;
    while ((receivedMessage = receiver.Receive()) != null)
    {
      string sessionId = receiver.SessionId;
      ProcessMessage(receivedMessage, ref sessionState, receiver);
      while (sessionState.GetNextOutOfSequenceMessage() != -1)
      {
        // Call back deferred messages
        Console.WriteLine("Calling back for deferred message: Category {0},
          Message sequence {1}", receiver.SessionId,
            sessionState.GetNextSequenceId());
        receivedMessage = receiver.Receive(
          sessionState.GetNextOutOfSequenceMessage());
        ProcessMessage(receivedMessage, ref sessionState, receiver);
      }
      if (receivedMessage.Properties.ContainsKey(
        "IsLastMessageInSession"))
        break;
    }
    SetState(receiver, null);
    receiver.Close();
  }

Figura 9 il metodo ProcessMessage nel codice

static void ProcessMessage(BrokeredMessage message, ref SequenceState sessionState,
  MessageSession session = null)
  {
    if (session != null)
    {
      int messageId = Convert.ToInt32(message.Properties["CatalogPage"]);
      if (sessionState.GetNextSequenceId() == messageId)
      {
        OutputMessageInfo("RECV: ", message, "State: " + "RECEIVED");
        sessionState.SetNextSequenceId(messageId + 1);
        message.Complete();
        SetState(session, sessionState);
      }
      else
      {
        Console.WriteLine("Deferring message: Category {0}, Catalog Page {1}",
          session.SessionId, messageId);
        sessionState.AddOutOfSequenceMessage(messageId, 
          message.SequenceNumber);
        message.Defer();
        SetState(session, sessionState);
      }
    }
    Thread.Sleep(receiverDelay);
  }

Tieni presente che per questo progetto, ID messaggio differite vengono archiviati nello stato sessione e potrebbe essere potenzialmente perduto. In un ambiente di produzione, si consiglia di utilizzare un certo tipo di archiviazione persistente (tabelle di Windows Azure è una opzione) per questo scopo. Si noti che se il messaggio contiene la proprietà IsLastMessage­SessionInSession (impostare durante il processo di invio), il ciclo di sessione è terminato. La console di output per il progetto MSDNReceiver può essere visto Figura 10.

Execution of the MSDNReceiver project
Figura 10 esecuzione del progetto MSDNReceiver

Abbonamenti Bus Servizio Windows Azure darvi la possibilità di creare regole specifiche che filtrano i messaggi prima che essi sono consumati. In questo caso, sarebbe relativamente facile creare una regola che separa prodotti per categoria o dal numero di negozio (che abbiamo ignorati in questo progetto). Le regole possono essere create a livello di codice direttamente nel portale di Windows Azure o attraverso strumenti di Visual Studio.

Conclusioni

Il Bus di servizio Windows Azure offre un'implementazione incredibilmente robusta e flessibile del modello di pubblicazione/sottoscrizione. Diverse situazioni possono essere affrontate attraverso l'utilizzo di argomenti e sottoscrizioni. La capacità di supportare più mittenti trasmettere messaggi a più ricevitori, combinate con la capacità di logicamente gruppo e ordina messaggi, si apre un mondo di possibilità per gli sviluppatori moderni. Inoltre, essendo in grado di sfruttare una sessione permanente per tenere traccia dello stato rende semplice per raggruppare i messaggi in modo logico e controllare la loro sequenza. In un mondo dove ambienti distribuiti sono la norma, capire come utilizzare modelli di messaggistica e gli strumenti che li circonda è cruciale per gli architetti di software di oggi lavorano nel cloud.

Bruno Terkaly è un developer evangelist per Microsoft. La sua profonda competenza deriva da anni di esperienza nel campo, scrivendo codice utilizzando una moltitudine di piattaforme, linguaggi, framework, SDK, librerie e API. Dedica il suo tempo a scrivere codice, a pubblicare post su blog e a tenere presentazioni sulla creazione di applicazioni basate su cloud, nello specifico utilizzando la piattaforma Windows Azure.

Ricardo Villalobos è un architetto software con oltre 15 anni di esperienza nella progettazione e nella creazione di applicazioni per aziende nel settore SCM (Supply Chain Management). Possesso di certificazioni tecniche diverse, come pure un Master in business administration presso l'Università di Dallas, lavora come un architetto cloud nel gruppo di incubazione CSV di Windows Azure per Microsoft.

Grazie all'esperto tecnica seguente per la revisione di questo articolo: Abhishek Lal