Code, argomenti e sottoscrizioni del bus di servizioService Bus queues, topics, and subscriptions

Il bus di servizio di Microsoft Azure supporta un set di tecnologie middleware orientate ai messaggi e basate sul cloud, incluso l'accodamento dei messaggi affidabile e la messaggistica di pubblicazione e sottoscrizione permanente.Microsoft Azure Service Bus supports a set of cloud-based, message-oriented middleware technologies including reliable message queuing and durable publish/subscribe messaging. Queste funzionalità di messaggistica "negoziata" possono essere considerate come funzionalità di messaggistica asincrone o disaccoppiate che supportano scenari di pubblicazione e sottoscrizione, disaccoppiamento temporale e bilanciamento del carico tramite il carico di lavoro di messaggistica del bus di servizio.These "brokered" messaging capabilities can be thought of as decoupled messaging features that support publish-subscribe, temporal decoupling, and load balancing scenarios using the Service Bus messaging workload. La comunicazione disaccoppiata presenta molti vantaggi, ad esempio client e server possono connettersi quando necessario ed eseguire le relative operazioni in modo asincrono.Decoupled communication has many advantages; for example, clients and servers can connect as needed and perform their operations in an asynchronous fashion.

Le entità di messaggistica che costituiscono le funzionalità di messaggistica di base nel bus di servizio sono code, argomenti e sottoscrizioni e regole/azioni.The messaging entities that form the core of the messaging capabilities in Service Bus are queues, topics and subscriptions, and rules/actions.

CodeQueues

Le code consentono un recapito dei messaggi di tipo FIFO (First In, First Out) a uno o più consumer concorrenti.Queues offer First In, First Out (FIFO) message delivery to one or more competing consumers. In altri termini, i messaggi in genere vengono ricevuti ed elaborati dai ricevitori secondo l'ordine temporale in cui sono stati aggiunti alla coda e ogni messaggio viene ricevuto ed elaborato da un solo consumer.That is, messages are typically expected to be received and processed by the receivers in the order in which they were added to the queue, and each message is received and processed by only one message consumer. Il vantaggio principale derivante dall'uso delle code è quello di ottenere un "disaccoppiamento temporale" dei componenti applicativi,A key benefit of using queues is to achieve "temporal decoupling" of application components. ovvero non è necessario che i producer e i consumer inviino e ricevano i messaggi contemporaneamente perché i messaggi restano archiviati nella coda.In other words, the producers (senders) and consumers (receivers) do not have to be sending and receiving messages at the same time, because messages are stored durably in the queue. Il producer inoltre non deve attendere la risposta del consumer per continuare a elaborare e inviare messaggi.Furthermore, the producer does not have to wait for a reply from the consumer in order to continue to process and send messages.

Un vantaggio correlato è quello del "livellamento del carico", che permette ai producer e ai consumer di inviare e ricevere i messaggi con frequenze diverse.A related benefit is "load leveling," which enables producers and consumers to send and receive messages at different rates. In molte applicazioni, il carico del sistema varia nel tempo, tuttavia, il tempo di elaborazione necessario per ogni unità è in genere costante.In many applications, the system load varies over time; however, the processing time required for each unit of work is typically constant. L'interposizione di una coda tra producer e consumer di messaggi implica che è necessario solo eseguire il provisioning dell'applicazione consumer per gestire un carico medio invece di un carico massimo.Intermediating message producers and consumers with a queue means that the consuming application only has to be provisioned to be able to handle average load instead of peak load. In base alla variazione del carico in ingresso, si verificherà un incremento o una riduzione della profondità della coda,The depth of the queue grows and contracts as the incoming load varies. con un risparmio diretto in termini economici rispetto alle risorse infrastrutturali richieste per gestire il carico dell'applicazione.This directly saves money with regard to the amount of infrastructure required to service the application load. Con l'aumento del carico, è possibile aggiungere altri processi di lavoro per la lettura della coda.As the load increases, more worker processes can be added to read from the queue. Ciascun messaggio viene elaborato da un solo processo di lavoro.Each message is processed by only one of the worker processes. Inoltre, il bilanciamento del carico di tipo pull permette un uso ottimale dei computer di lavoro anche quando questi presentano una potenza di elaborazione diversa. Ogni computer effettuerà infatti il pull dei messaggi in base alla propria velocità massima.Furthermore, this pull-based load balancing allows for optimum use of the worker computers even if the worker computers differ with regard to processing power, as they pull messages at their own maximum rate. Questo modello viene spesso definito modello del "consumer concorrente".This pattern is often termed the "competing consumer" pattern.

L'uso di code da interporre tra producer e consumer di messaggi fornisce un accoppiamento intrinseco di tipo regime di controllo libero tra i componenti.Using queues to intermediate between message producers and consumers provides an inherent loose coupling between the components. Poiché producer e consumer sono indipendenti gli uni dagli altri, è possibile aggiornare un consumer senza causare alcun effetto sul producer.Because producers and consumers are not aware of each other, a consumer can be upgraded without having any effect on the producer.

La creazione di una coda è un processo che prevede più passaggi. Creating a queue is a multi-step process. Le operazioni di gestione per le entità di messaggistica del bus di servizio (code e argomenti) vengono eseguite tramite la classe Microsoft.ServiceBus.NamespaceManager che viene costruita specificando l'indirizzo di base dello spazio dei nomi e le credenziali utente del bus di servizio.You perform management operations for Service Bus messaging entities (both queues and topics) via the Microsoft.ServiceBus.NamespaceManager class, which is constructed by supplying the base address of the Service Bus namespace and the user credentials. NamespaceManager fornisce i metodi per creare, enumerare ed eliminare le entità di messaggistica.NamespaceManager provides methods to create, enumerate, and delete messaging entities. Dopo aver creato un oggetto Microsoft.ServiceBus.TokenProvider da un nome e una chiave di firma di accesso condiviso e un oggetto di gestione dello spazio dei nomi servizio, è possibile usare il metodo Microsoft.ServiceBus.NamespaceManager.CreateQueue per creare la coda.After creating a Microsoft.ServiceBus.TokenProvider object from the SAS name and key, and a service namespace management object, you can use the Microsoft.ServiceBus.NamespaceManager.CreateQueue method to create the queue. Ad esempio:For example:

// Create management credentials
TokenProvider credentials = TokenProvider.CreateSharedAccessSignatureTokenProvider(sasKeyName,sasKeyValue);
// Create namespace client
NamespaceManager namespaceClient = new NamespaceManager(ServiceBusEnvironment.CreateServiceUri("sb", ServiceNamespace, string.Empty), credentials);

È quindi possibile creare un oggetto coda e una factory di messaggistica usando l'URI del bus di servizio come argomento.You can then create a queue object and a messaging factory with the Service Bus URI as an argument. Ad esempio:For example:

QueueDescription myQueue;
myQueue = namespaceClient.CreateQueue("TestQueue");
MessagingFactory factory = MessagingFactory.Create(ServiceBusEnvironment.CreateServiceUri("sb", ServiceNamespace, string.Empty), credentials); 
QueueClient myQueueClient = factory.CreateQueueClient("TestQueue");

È quindi possibile inviare messaggi alla coda.You can then send messages to the queue. Se ad esempio si ha un elenco di messaggi negoziati denominato MessageList, sarà possibile usare un codice simile all'esempio seguente:For example, if you have a list of brokered messages called MessageList, the code appears similar to the following example:

for (int count = 0; count < 6; count++)
{
    var issue = MessageList[count];
    issue.Label = issue.Properties["IssueTitle"].ToString();
    myQueueClient.Send(issue);
}

È possibile quindi ricevere messaggi dalla coda, come indicato nell'esempio seguente:You then receive messages from the queue as follows:

while ((message = myQueueClient.Receive(new TimeSpan(hours: 0, minutes: 0, seconds: 5))) != null)
    {
        Console.WriteLine(string.Format("Message received: {0}, {1}, {2}", message.SequenceNumber, message.Label, message.MessageId));
        message.Complete();

        Console.WriteLine("Processing message (sleeping...)");
        Thread.Sleep(1000);
    }

Quando si usa la modalità ReceiveAndDelete, la ricezione è un'operazione a un'unica fase. Quando il bus di servizio riceve la richiesta, contrassegna il messaggio come usato e lo restituisce all'applicazione.In the ReceiveAndDelete mode, the receive operation is single-shot; that is, when Service Bus receives the request, it marks the message as being consumed and returns it to the application. La modalità ReceiveAndDelete rappresenta il modello più semplice ed è adatta per scenari in cui un'applicazione può tollerare la mancata elaborazione di un messaggio in caso di errore.ReceiveAndDelete mode is the simplest model and works best for scenarios in which the application can tolerate not processing a message in the event of a failure. Per comprendere meglio questo meccanismo, si consideri uno scenario in cui il consumer invia la richiesta di ricezione e viene arrestato in modo anomalo prima dell'elaborazione.To understand this, consider a scenario in which the consumer issues the receive request and then crashes before processing it. Poiché il bus di servizio contrassegna il messaggio come consumato, quando l'applicazione viene riavviata e inizia a consumare nuovamente i messaggi, il messaggio consumato prima dell'arresto anomalo risulterà perso.Because Service Bus marks the message as being consumed, when the application restarts and begins consuming messages again, it will have missed the message that was consumed prior to the crash.

Con la modalità PeekLock il processo di ricezione diventa un'operazione in due fasi, che rende possibile il supporto di applicazioni che non riescono a tollerare messaggi mancanti.In PeekLock mode, the receive operation becomes two-stage, which makes it possible to support applications that cannot tolerate missing messages. Quando il bus di servizio riceve la richiesta, individua il messaggio successivo da consumare, lo blocca per impedirne la ricezione da parte di altri consumer e lo restituisce quindi all'applicazione.When Service Bus receives the request, it finds the next message to be consumed, locks it to prevent other consumers from receiving it, and then returns it to the application. Dopo aver elaborato il messaggio o averlo archiviato in modo affidabile per una successiva elaborazione, l'applicazione esegue la seconda fase del processo di ricezione chiamando Complete sul messaggio ricevuto.After the application finishes processing the message (or stores it reliably for future processing), it completes the second stage of the receive process by calling Complete on the received message. Quando il bus di servizio vede la chiamata Complete, contrassegna il messaggio come usato.When Service Bus sees the Complete call, it marks the message as being consumed.

Se per qualche motivo l’applicazione non è in grado di elaborare il messaggio, può chiamare il metodo Abandon, invece di Complete, per il messaggio ricevuto.If the application is unable to process the message for some reason, it can call the Abandon method on the received message (instead of Complete). In questo modo, il bus di servizio sbloccherà il messaggio che sarà disponibile per essere nuovamente ricevuto dallo stesso consumer o da un altro consumer concorrente.This enables Service Bus to unlock the message and make it available to be received again, either by the same consumer or by another competing consumer. Al blocco è associato anche un timeout. Se l'applicazione non riesce a elaborare il messaggio prima della scadenza del timeout, ad esempio a causa di un arresto anomalo, il bus di servizio sblocca il messaggio rendendolo nuovamente disponibile per la ricezione (eseguendo essenzialmente un'operazione Abandon per impostazione predefinita).Secondly, there is a timeout associated with the lock and if the application fails to process the message before the lock timeout expires (for example, if the application crashes), then Service Bus unlocks the message and makes it available to be received again (essentially performing an Abandon operation by default).

Si noti che in caso di arresto anomalo dell'applicazione dopo l'elaborazione del messaggio ma prima dell'emissione della richiesta Complete, il messaggio verrà nuovamente recapitato all'applicazione al riavvio.Note that in the event that the application crashes after processing the message, but before the Complete request is issued, the message is redelivered to the application when it restarts. Questo processo di elaborazione viene spesso definito di tipo At-Least-Once, per indicare che ogni messaggio viene elaborato almeno una volta.This is often called At Least Once processing; that is, each message is processed at least once. ma che in determinate situazioni potrà essere recapitato una seconda volta.However, in certain situations the same message may be redelivered. Se lo scenario non tollera la doppia elaborazione, sarà necessaria una logica aggiuntiva nell'applicazione per il rilevamento dei duplicati in base alla proprietà MessageId del messaggio, che rimane costante per tutti i tentativi di recapito.If the scenario cannot tolerate duplicate processing, then additional logic is required in the application to detect duplicates, which can be achieved based upon the MessageId property of the message, which remains constant across delivery attempts. Questo tipo di elaborazione viene definito di tipo Exactly Once.This is known as Exactly Once processing.

Argomenti e sottoscrizioniTopics and subscriptions

Diversamente dalle code, in cui ogni messaggio viene elaborato da un unico consumer, gli argomenti e le sottoscrizioni offrono una forma di comunicazione di tipo uno-a-molti, in un modello di pubblicazione/sottoscrizione.In contrast to queues, in which each message is processed by a single consumer, topics and subscriptions provide a one-to-many form of communication, in a publish/subscribe pattern. Particolarmente utile per la comunicazione con un numero molto elevato di destinatari, ogni messaggio pubblicato è reso disponibile per ogni sottoscrizione registrata con l'argomento.Useful for scaling to very large numbers of recipients, each published message is made available to each subscription registered with the topic. I messaggi vengono inviati a un argomento e recapitati a una o più sottoscrizioni associate, a seconda delle regole di filtro che possono essere impostate per ogni sottoscrizione.Messages are sent to a topic and delivered to one or more associated subscriptions, depending on filter rules that can be set on a per-subscription basis. Per limitare i messaggi da ricevere, le sottoscrizioni possono usare filtri aggiuntivi.The subscriptions can use additional filters to restrict the messages that they want to receive. I messaggi vengono inviati a un argomento nello stesso modo in cui vengono inviati a una coda, con la differenza che i messaggi non vengono ricevuti direttamente dall'argomento.Messages are sent to a topic in the same way they are sent to a queue, but messages are not received from the topic directly. Vengono ricevuti dalle sottoscrizioni.Instead, they are received from subscriptions. La sottoscrizione di un argomento è simile a una coda virtuale che riceve copie dei messaggi inviati all'argomento.A topic subscription resembles a virtual queue that receives copies of the messages that are sent to the topic. La procedura di ricezione dei messaggi da parte di una sottoscrizione è identica a quella usata per la ricezione da parte di una coda.Messages are received from a subscription identically to the way they are received from a queue.

Ai fini di un confronto, la funzionalità di invio dei messaggi di una coda esegue il mapping direttamente a un argomento e la funzionalità di ricezione dei messaggi esegue il mapping a una sottoscrizione.By way of comparison, the message-sending functionality of a queue maps directly to a topic and its message-receiving functionality maps to a subscription. Questo significa anche che le sottoscrizioni supportano gli stessi modelli descritti prima in questa sezione in merito alle code: consumer concorrente, disaccoppiamento temporale, livellamento del carico e bilanciamento del carico.Among other things, this means that subscriptions support the same patterns described earlier in this section with regard to queues: competing consumer, temporal decoupling, load leveling, and load balancing.

La procedura per la creazione di un argomento è simile a quella per la creazione di una coda, come illustrato nell'esempio della sezione precedente.Creating a topic is similar to creating a queue, as shown in the example in the previous section. Creare l'URI del servizio e usare la classe NamespaceManager per creare il client dello spazio dei nomi.Create the service URI, and then use the NamespaceManager class to create the namespace client. È quindi possibile creare un argomento usando il metodo CreateTopic.You can then create a topic using the CreateTopic method. Ad esempio:For example:

TopicDescription dataCollectionTopic = namespaceClient.CreateTopic("DataCollectionTopic");

Aggiungere quindi le sottoscrizioni desiderate:Next, add subscriptions as desired:

SubscriptionDescription myAgentSubscription = namespaceClient.CreateSubscription(myTopic.Path, "Inventory");
SubscriptionDescription myAuditSubscription = namespaceClient.CreateSubscription(myTopic.Path, "Dashboard");

Sarà quindi possibile creare un client dell'argomento.You can then create a topic client. Ad esempio:For example:

MessagingFactory factory = MessagingFactory.Create(serviceUri, tokenProvider);
TopicClient myTopicClient = factory.CreateTopicClient(myTopic.Path)

Usando il mittente del messaggio, è possibile inviare messaggi all'argomento e riceverli, come illustrato nella sezione precedente.Using the message sender, you can send and receive messages to and from the topic, as shown in the previous section. Ad esempio:For example:

foreach (BrokeredMessage message in messageList)
{
    myTopicClient.Send(message);
    Console.WriteLine(
    string.Format("Message sent: Id = {0}, Body = {1}", message.MessageId, message.GetBody<string>()));
}

Come accade per le code, i messaggi vengono ricevuti da una sottoscrizione usando un oggetto SubscriptionClient invece di un oggetto QueueClient.Similar to queues, messages are received from a subscription using a SubscriptionClient object instead of a QueueClient object. Creare il client della sottoscrizione, passando il nome dell'argomento, il nome della sottoscrizione e (facoltativamente) la modalità di ricezione come parametri.Create the subscription client, passing the name of the topic, the name of the subscription, and (optionally) the receive mode as parameters. Ad esempio, con la sottoscrizione Inventory:For example, with the Inventory subscription:

// Create the subscription client
MessagingFactory factory = MessagingFactory.Create(serviceUri, tokenProvider); 

SubscriptionClient agentSubscriptionClient = factory.CreateSubscriptionClient("IssueTrackingTopic", "Inventory", ReceiveMode.PeekLock);
SubscriptionClient auditSubscriptionClient = factory.CreateSubscriptionClient("IssueTrackingTopic", "Dashboard", ReceiveMode.ReceiveAndDelete); 

while ((message = agentSubscriptionClient.Receive(TimeSpan.FromSeconds(5))) != null)
{
    Console.WriteLine("\nReceiving message from Inventory...");
    Console.WriteLine(string.Format("Message received: Id = {0}, Body = {1}", message.MessageId, message.GetBody<string>()));
    message.Complete();
}          

// Create a receiver using ReceiveAndDelete mode
while ((message = auditSubscriptionClient.Receive(TimeSpan.FromSeconds(5))) != null)
{
    Console.WriteLine("\nReceiving message from Dashboard...");
    Console.WriteLine(string.Format("Message received: Id = {0}, Body = {1}", message.MessageId, message.GetBody<string>()));
}

Regole e azioniRules and actions

In molti scenari, i messaggi con caratteristiche specifiche devono essere elaborati in modi specifici.In many scenarios, messages that have specific characteristics must be processed in different ways. A questo scopo, è possibile configurare le sottoscrizioni in modo che trovino i messaggi che presentano le proprietà desiderate e apportare quindi alcune modifiche a tali proprietà.To enable this, you can configure subscriptions to find messages that have desired properties and then perform certain modifications to those properties. Mentre nelle sottoscrizioni del bus di servizio tutti i messaggi vengono inviati all'argomento, l'utente può copiare solo un subset di tali messaggi nella coda virtuale delle sottoscrizioni.While Service Bus subscriptions see all messages sent to the topic, you can only copy a subset of those messages to the virtual subscription queue. Questa operazione viene eseguita usando i filtri della sottoscrizione.This is accomplished using subscription filters. Queste modifiche sono chiamate azioni di filtro.Such modifications are called filter actions. Quando viene creata una sottoscrizione, è possibile specificare un'espressione di filtro che agisce sulle proprietà del messaggio, sulle proprietà del sistema, ad esempio Label, e sulle proprietà dell'applicazione personalizzata, ad esempio StoreName. In questo caso l'espressione di filtro SQL è facoltativa. Senza un'espressione di filtro SQL, qualsiasi azione di filtro definita in una sottoscrizione verrà eseguita in tutti i messaggi di tale sottoscrizione.When a subscription is created, you can supply a filter expression that operates on the properties of the message, both the system properties (for example, Label) and custom application properties (for example, StoreName.) The SQL filter expression is optional in this case; without a SQL filter expression, any filter action defined on a subscription will be performed on all the messages for that subscription.

Facendo riferimento all'esempio precedente, per filtrare solo i messaggi provenienti da Store1, è necessario creare la sottoscrizione Dashboard come indicato nella procedura seguente:Using the previous example, to filter messages coming only from Store1, you would create the Dashboard subscription as follows:

namespaceManager.CreateSubscription("IssueTrackingTopic", "Dashboard", new SqlFilter("StoreName = 'Store1'"));

Dopo aver creato questo filtro della sottoscrizione, solo i messaggi con la proprietà StoreName impostata su Store1 vengono copiati nella coda virtuale per la sottoscrizione Dashboard.With this subscription filter in place, only messages that have the StoreName property set to Store1 are copied to the virtual queue for the Dashboard subscription.

Per altre informazioni sui valori di filtro possibili, vedere la documentazione relativa alle classi SqlFilter e SqlRuleAction.For more information about possible filter values, see the documentation for the SqlFilter and SqlRuleAction classes. Vedere anche gli esempi Brokered Messaging: Advanced Filters (Messaggistica negoziata: filtri avanzati) e Topic Filters (Filtri di argomento).Also, see the Brokered Messaging: Advanced Filters and Topic Filters samples.

Passaggi successiviNext steps

Per altri esempi e informazioni sull'uso della messaggistica del bus di servizio, vedere gli argomenti avanzati seguenti.See the following advanced topics for more information and examples of using Service Bus messaging.