Come usare gli argomenti e le sottoscrizioni del bus di servizio

In questo articolo verrà descritto come usare gli argomenti e le sottoscrizioni del bus di servizio. Gli esempi sono scritti in PHP e usano Azure SDK per PHP. Gli scenari presentati includono la creazione di argomenti e sottoscrizioni, la creazione di filtri per le sottoscrizioni, l’invio di messaggi a un argomento, la ricezione di messaggi da una sottoscrizione e l’eliminazione di argomenti e sottoscrizioni.

Cosa sono gli argomenti e le sottoscrizioni del bus di servizio?

Gli argomenti e le sottoscrizioni del bus di servizio supportano un modello di comunicazione con messaggistica di pubblicazione-sottoscrizione . Quando si usano gli argomenti e le sottoscrizioni, i componenti di un'applicazione distribuita non comunicano direttamente l'uno con l'altro, ma scambiano messaggi tramite un argomento, che agisce da intermediario.

Concetti relativi agli argomenti

Diversamente dalle code del bus di servizio, in cui ogni messaggio viene elaborato da un unico consumer, gli argomenti e le sottoscrizioni offrono una forma di comunicazione "uno a molti" tramite un modello di pubblicazione-sottoscrizione. È possibile registrare più sottoscrizioni a un argomento. Quando un messaggio viene inviato a un argomento, viene reso disponibile affinché ogni sottoscrizione possa gestirlo o elaborarlo in modo indipendente.

La sottoscrizione a un argomento è simile a una coda virtuale che riceve copie dei messaggi che sono stati inviati all'argomento. È possibile registrare regole di filtro per un argomento in base alla sottoscrizione, per poter filtrare o limitare quali messaggi relativi a un argomento vengono ricevuti dalle diverse sottoscrizioni dell'argomento.

Gli argomenti e le sottoscrizioni del bus di servizio consentono la scalabilità e l'elaborazione di grandi quantità di messaggi tra un numero elevato di utenti e applicazioni.

Creare uno spazio dei nomi

Per iniziare a usare gli argomenti e le sottoscrizioni del bus di servizio in Azure, è necessario creare prima di tutto uno spazio dei nomi del servizio. Uno spazio dei nomi fornisce un contenitore di ambito per fare riferimento alle risorse del bus di servizio all'interno dell'applicazione.

Per creare uno spazio dei nomi:

  1. Accedere al portale di Azure.
  2. Nel riquadro di spostamento sinistro del portale fare clic su Nuovo, quindi su Enterprise Integration e infine su Bus di servizio.
  3. Nella finestra di dialogo Crea spazio dei nomi immettere un nome per lo spazio dei nomi. Verrà effettuato immediatamente un controllo sulla disponibilità del nome.
  4. Dopo aver verificato che il nome dello spazio dei nomi sia disponibile, scegliere il piano tariffario, ovvero Basic, Standard o Premium.
  5. Nel campo Sottoscrizione scegliere una sottoscrizione di Azure in cui creare lo spazio dei nomi.
  6. Nel campo Gruppo di risorse scegliere un gruppo di risorse esistente nel quale risiederà lo spazio dei nomi oppure crearne uno nuovo.
  7. In Localitàscegliere il paese o l'area in cui deve essere ospitato lo spazio dei nomi.

    Crea spazio dei nomi

  8. Selezionare il pulsante Create . A questo punto, lo spazio dei nomi verrà creato e abilitato nel sistema. Potrebbero essere necessari alcuni minuti per consentire al sistema di effettuare il provisioning delle risorse per lo spazio dei nomi creato.

Ottenere le credenziali

  1. Nell'elenco degli spazi dei nomi fare clic sul nome dello spazio dei nomi appena creato.
  2. Nel pannello Spazio dei nomi del bus di servizio fare clic su Criteri di accesso condiviso.
  3. Nel pannello Criteri di accesso condivisi fare clic su RootManageSharedAccessKey.

    connection-info

  4. Nel pannello Criteri: RootManageSharedAccessKey fare clic sul pulsante Copia accanto a Stringa di connessione - chiave primaria per copiare la stringa di connessione negli Appunti e usarla in un secondo momento.

    connection-string

Creare un'applicazione PHP

Per creare un'applicazione PHP che acceda al servizio BLOB di Azure, è sufficiente fare riferimento alle classi in Azure SDK per PHP dall'interno del codice. Per creare l'applicazione, è possibile usare qualsiasi strumento di sviluppo o il Blocco note.

Nota

L'installazione di PHP deve avere anche l'estensione OpenSSL installata e abilitata.

Questo articolo illustra come usare le funzionalità del servizio che possono essere chiamate in un'applicazione PHP in locale o nel codice in esecuzione in un ruolo Web, in un ruolo di lavoro o in un sito Web di Azure.

Acquisire le librerie client di Azure

Installazione tramite Composer

  1. Installare GIT. Si noti che in Windows, è anche necessario aggiungere l'eseguibile Git alla variabile di ambiente PATH.
  2. Creare un file denominato composer.json nella radice del progetto, quindi aggiungere nel file il codice seguente:

    {
      "require": {
        "microsoft/windowsazure": "^0.4"
      }
    }
    
  3. Scaricare composer.phar nella radice del progetto.
  4. Aprire un prompt dei comandi ed eseguire il comando seguente nella radice del progetto

    php composer.phar install
    

Configurare l'applicazione per l'uso del bus di servizio

Per usare le API del bus di servizio:

  1. Fare riferimento al file autoloader mediante l'istruzione require_once.
  2. Fare riferimento a tutte le eventuali classi utilizzabili.

Nell'esempio seguente viene indicato come includere il file autoloader e fare riferimento alla classe ServiceBusService.

Nota

Questo esempio (e in altri esempi in questo articolo) presuppone che siano state installate le librerie client PHP per Azure tramite Composer. Se le librerie sono state installate manualmente o come pacchetto PEAR, è necessario fare riferimento al file autoloader WindowsAzure.php.

require_once 'vendor\autoload.php';
use WindowsAzure\Common\ServicesBuilder;

Nei seguenti esempi l'istruzione require_once verrà sempre visualizzata, ma si fa riferimento solo alle classi necessarie per eseguire l'esempio.

Configurare una stringa di connessione per il bus di servizio

Per creare un'istanza di un client del bus di servizio, è necessario innanzitutto disporre di una stringa di connessione valida nel seguente formato:

Endpoint=[yourEndpoint];SharedSecretIssuer=[Default Issuer];SharedSecretValue=[Default Key]

Dove Endpoint è in genere nel formato https://[yourNamespace].servicebus.windows.net.

Per creare un client del servizio Azure, è necessario usare la classe ServicesBuilder. È possibile:

  • Passare la stringa di connessione direttamente.
  • utilizzare CloudConfigurationManager (CCM) per cercare la stringa di connessione in più origini esterne:
    • Per impostazione predefinita viene fornito con il supporto per un'origine esterna, ovvero le variabili ambientali.
    • È possibile aggiungere nuove origini estendendo la classe ConnectionStringSource.

Per gli esempi illustrati in questo articolo, la stringa di connessione viene passata direttamente.

require_once 'vendor/autoload.php';

use WindowsAzure\Common\ServicesBuilder;

$connectionString = "Endpoint=[yourEndpoint];SharedSecretIssuer=[Default Issuer];SharedSecretValue=[Default Key]";

$serviceBusRestProxy = ServicesBuilder::getInstance()->createServiceBusService($connectionString);

Creare un argomento

È possibile eseguire operazioni di gestione per gli argomenti del bus di servizio usando la classe ServiceBusRestProxy. Un oggetto ServiceBusRestProxy è costruito tramite il metodo factory ServicesBuilder::createServiceBusService con una stringa di connessione appropriata che incapsula le autorizzazioni di token per gestirlo.

L'esempio seguente mostra come creare un'istanza di ServiceBusRestProxy e chiamare il metodo ServiceBusRestProxy->createTopic per creare un argomento denominato mytopic in uno spazio dei nomi MySBNamespace:

require_once 'vendor/autoload.php';

use WindowsAzure\Common\ServicesBuilder;
use WindowsAzure\Common\ServiceException;
use WindowsAzure\ServiceBus\Models\TopicInfo;

// Create Service Bus REST proxy.
$serviceBusRestProxy = ServicesBuilder::getInstance()->createServiceBusService($connectionString);

try    {        
    // Create topic.
    $topicInfo = new TopicInfo("mytopic");
    $serviceBusRestProxy->createTopic($topicInfo);
}
catch(ServiceException $e){
    // Handle exception based on error codes and messages.
    // Error codes and messages are here: 
    // http://msdn.microsoft.com/library/windowsazure/dd179357
    $code = $e->getCode();
    $error_message = $e->getMessage();
    echo $code.": ".$error_message."<br />";
}
Nota

È possibile usare il metodo listTopics negli oggetti ServiceBusRestProxy per verificare se in uno spazio dei nomi del servizio esiste già un argomento con il nome specificato.

Creare una sottoscrizione

È possibile creare le sottoscrizioni di un argomento con il metodo ServiceBusRestProxy->createSubscription. Le sottoscrizioni sono denominate e possono includere un filtro facoltativo che limita l'insieme dei messaggi passati alla coda virtuale della sottoscrizione.

Creare una sottoscrizione con il filtro (MatchAll) predefinito

Il filtro MatchAll è il filtro predefinito e viene usato se non vengono specificati altri filtri durante la creazione di una nuova sottoscrizione. Quando si usa il filtro MatchAll, tutti i messaggi pubblicati nell'argomento vengono inseriti nella coda virtuale della sottoscrizione. Nell'esempio seguente viene creata una sottoscrizione denominata 'mysubscription' e viene usato il filtro predefinito MatchAll.

require_once 'vendor/autoload.php';

use WindowsAzure\Common\ServicesBuilder;
use WindowsAzure\Common\ServiceException;
use WindowsAzure\ServiceBus\Models\SubscriptionInfo;

// Create Service Bus REST proxy.
$serviceBusRestProxy = ServicesBuilder::getInstance()->createServiceBusService($connectionString);

try    {
    // Create subscription.
    $subscriptionInfo = new SubscriptionInfo("mysubscription");
    $serviceBusRestProxy->createSubscription("mytopic", $subscriptionInfo);
}
catch(ServiceException $e){
    // Handle exception based on error codes and messages.
    // Error codes and messages are here: 
    // http://msdn.microsoft.com/library/azure/dd179357
    $code = $e->getCode();
    $error_message = $e->getMessage();
    echo $code.": ".$error_message."<br />";
}

Creare sottoscrizioni con i filtri

È anche possibile configurare filtri che consentono di specificare quali messaggi inviati a un argomento devono essere presenti in una specifica sottoscrizione dell'argomento. Il tipo di filtro più flessibile tra quelli supportati dalle sottoscrizioni è SqlFilter, che implementa un subset di SQL92. I filtri SQL agiscono sulle proprietà dei messaggi pubblicati nell'argomento. Per altre informazioni su SqlFilters, vedere la sezione relativa alla proprietà SqlFilter.SqlExpression.

Nota

Ogni regola in una sottoscrizione elabora i messaggi in arrivo indipendentemente, aggiungendo i messaggi risultanti alla sottoscrizione stessa. Ogni nuova sottoscrizione presenta anche un oggetto Rule predefinito con un filtro che aggiunge tutti i messaggi dall'argomento alla sottoscrizione. Per ricevere solo messaggi corrispondenti al filtro in uso, è necessario rimuovere la regola predefinita. È possibile rimuovere la regola predefinita usando il metodo ServiceBusRestProxy->deleteRule.

L'esempio seguente crea una sottoscrizione denominata HighMessages con un filtro SqlFilter che seleziona solo i messaggi in cui il valore della proprietà MessageNumber personalizzata è maggiore di 3. Per informazioni su come aggiungere proprietà personalizzate ai messaggi, vedere Inviare messaggi a un argomento.

$subscriptionInfo = new SubscriptionInfo("HighMessages");
$serviceBusRestProxy->createSubscription("mytopic", $subscriptionInfo);

$serviceBusRestProxy->deleteRule("mytopic", "HighMessages", '$Default');

$ruleInfo = new RuleInfo("HighMessagesRule");
$ruleInfo->withSqlFilter("MessageNumber > 3");
$ruleResult = $serviceBusRestProxy->createRule("mytopic", "HighMessages", $ruleInfo);

Si noti che questo codice richiede l'uso di uno spazio dei nomi aggiuntivo: WindowsAzure\ServiceBus\Models\SubscriptionInfo.

Analogamente, l'esempio seguente crea una sottoscrizione denominata LowMessages con un filtro SqlFilter che seleziona solo i messaggi in cui il valore della proprietà MessageNumber è minore o uguale a 3.

$subscriptionInfo = new SubscriptionInfo("LowMessages");
$serviceBusRestProxy->createSubscription("mytopic", $subscriptionInfo);

$serviceBusRestProxy->deleteRule("mytopic", "LowMessages", '$Default');

$ruleInfo = new RuleInfo("LowMessagesRule");
$ruleInfo->withSqlFilter("MessageNumber <= 3");
$ruleResult = $serviceBusRestProxy->createRule("mytopic", "LowMessages", $ruleInfo);

A questo punto, quando viene inviato un messaggio all'argomento mytopic, viene sempre recapitato ai ricevitori con sottoscrizione mysubscription e recapitato selettivamente ai ricevitori con sottoscrizioni HighMessages e LowMessages, a seconda del contenuto del messaggio.

Inviare messaggi a un argomento

Per inviare un messaggio a un argomento del bus di servizio, l'applicazione chiama il metodo ServiceBusRestProxy->sendTopicMessage. Il codice seguente illustra come inviare un messaggio all'argomento mytopic creato prima nello spazio dei nomi del servizio MySBNamespace.

require_once 'vendor/autoload.php';

use WindowsAzure\Common\ServicesBuilder;
use WindowsAzure\Common\ServiceException;
use WindowsAzure\ServiceBus\Models\BrokeredMessage;

// Create Service Bus REST proxy.
$serviceBusRestProxy = ServicesBuilder::getInstance()->createServiceBusService($connectionString);

try    {
    // Create message.
    $message = new BrokeredMessage();
    $message->setBody("my message");

    // Send message.
    $serviceBusRestProxy->sendTopicMessage("mytopic", $message);
}
catch(ServiceException $e){
    // Handle exception based on error codes and messages.
    // Error codes and messages are here: 
    // http://msdn.microsoft.com/library/azure/hh780775
    $code = $e->getCode();
    $error_message = $e->getMessage();
    echo $code.": ".$error_message."<br />";
}

I messaggi inviati ad argomenti del bus di servizio sono istanze della classe BrokeredMessage. Gli oggetti BrokeredMessage includono un set di proprietà e metodi standard, nonché proprietà usate per contenere proprietà personalizzate specifiche dell'applicazione. L'esempio seguente illustra come inviare 5 messaggi di prova all'argomento mytopic creato in precedenza. Il metodo setProperty viene usato per aggiungere una proprietà personalizzata (MessageNumber) a ogni messaggio. Si noti che il valore della proprietà MessageNumber varia per ogni messaggio, consentendo di determinare quali sottoscrizioni lo riceveranno, come descritto nella sezione Creare una sottoscrizione:

for($i = 0; $i < 5; $i++){
    // Create message.
    $message = new BrokeredMessage();
    $message->setBody("my message ".$i);

    // Set custom property.
    $message->setProperty("MessageNumber", $i);

    // Send message.
    $serviceBusRestProxy->sendTopicMessage("mytopic", $message);
}

Gli argomenti del bus di servizio supportano messaggi di dimensioni massime pari a 256 KB nel livello Standard e pari a 1 MB nel livello Premium. Le dimensioni massime dell'intestazione, che include le proprietà standard e personalizzate dell'applicazione, non possono superare 64 KB. Non esiste alcun limite al numero di messaggi mantenuti in un argomento, mentre è prevista una limitazione alla dimensione totale dei messaggi di un argomento. Il limite massimo delle dimensioni di un argomento è 5 GB. Per altre informazioni sulle quote, vedere Quote del bus di servizio.

Ricevere messaggi da una sottoscrizione

Il modo ideale per ricevere i messaggi da una sottoscrizione prevede l'uso di un metodo ServiceBusRestProxy->receiveSubscriptionMessage. Le modalità di ricezione dei messaggi sono due: ReceiveAndDelete e PeekLock. PeekLock è la modalità predefinita.

Quando si usa la modalità ReceiveAndDelete, l'operazione di ricezione viene eseguita in un'unica fase. Quando infatti il bus di servizio riceve una richiesta di lettura relativa a un messaggio in una sottoscrizione, lo contrassegna come usato e lo restituisce all'applicazione. La modalità ReceiveAndDelete * costituisce il modello più semplice ed è adatta per scenari in cui un'applicazione può tollerare la mancata elaborazione di un messaggio in caso di errore. 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. Poiché il bus di servizio contrassegna il messaggio come utilizzato, quando l'applicazione viene riavviata e inizia a utilizzare nuovamente i messaggi, il messaggio utilizzato prima dell'arresto anomalo risulterà perso.

Nella modalità PeekLock predefinita l'operazione di ricezione viene suddivisa in due fasi, in modo da consentire il supporto di applicazioni che non possono tollerare messaggi mancanti. Quando il bus di servizio riceve una richiesta, individua il messaggio successivo da usare, lo blocca per impedirne la ricezione da parte di altri consumer e quindi lo restituisce all'applicazione. Dopo aver elaborato il messaggio, o averlo archiviato in modo affidabile per una successiva elaborazione, l'applicazione completa la seconda fase del processo di ricezione passando il messaggio ricevuto a ServiceBusRestProxy->deleteMessage. Quando il bus di servizio vede la chiamata deleteMessage, contrassegna il messaggio come utilizzato e lo rimuove dalla coda.

L'esempio seguente illustra come ricevere ed elaborare un messaggio usando la modalità PeekLock (predefinita).

require_once 'vendor/autoload.php';

use WindowsAzure\Common\ServicesBuilder;
use WindowsAzure\Common\ServiceException;
use WindowsAzure\ServiceBus\Models\ReceiveMessageOptions;

// Create Service Bus REST proxy.
$serviceBusRestProxy = ServicesBuilder::getInstance()->createServiceBusService($connectionString);

try    {
    // Set receive mode to PeekLock (default is ReceiveAndDelete)
    $options = new ReceiveMessageOptions();
    $options->setPeekLock();

    // Get message.
    $message = $serviceBusRestProxy->receiveSubscriptionMessage("mytopic", "mysubscription", $options);

    echo "Body: ".$message->getBody()."<br />";
    echo "MessageID: ".$message->getMessageId()."<br />";

    /*---------------------------
        Process message here.
    ----------------------------*/

    // Delete message. Not necessary if peek lock is not set.
    echo "Deleting message...<br />";
    $serviceBusRestProxy->deleteMessage($message);
}
catch(ServiceException $e){
    // Handle exception based on error codes and messages.
    // Error codes and messages are here:
    // http://msdn.microsoft.com/library/azure/hh780735
    $code = $e->getCode();
    $error_message = $e->getMessage();
    echo $code.": ".$error_message."<br />";
}

Procedura: Gestire arresti anomali e messaggi illeggibili dell'applicazione

Il bus di servizio fornisce funzionalità per il ripristino gestito automaticamente in caso di errori nell'applicazione o di problemi di elaborazione di un messaggio. Se un'applicazione ricevente non è in grado di elaborare il messaggio per un qualsiasi motivo, può chiamare il metodo unlockMessage anziché deleteMessage sul messaggio ricevuto. In questo modo, il bus di servizio sbloccherà il messaggio nella coda rendendolo nuovamente disponibile per la ricezione da parte della stessa o da un'altra applicazione consumer.

Al messaggio bloccato nella coda è inoltre associato 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 sbloccherà automaticamente il messaggio rendendolo nuovamente disponibile per la ricezione.

In caso di arresto anomalo dell'applicazione dopo l'elaborazione del messaggio, ma prima dell'invio della richiesta deleteMessage, il messaggio verrà nuovamente recapitato all'applicazione al riavvio del sistema. Questo processo di elaborazione viene spesso definito di tipo At-Least-Once, per indicare che ogni messaggio verrà elaborato almeno una volta, ma che in determinate situazioni potrà essere recapitato una seconda volta. Se lo scenario non tollera la doppia elaborazione, gli sviluppatori dovranno aggiungere logica aggiuntiva alle applicazioni per gestire il secondo recapito del messaggio. A tale scopo viene spesso usato il metodo getMessageId del messaggio, che rimane costante in tutti i tentativi di recapito.

Eliminare argomenti e sottoscrizioni

Per eliminare un argomento o una sottoscrizione, usare rispettivamente il metodo ServiceBusRestProxy->deleteTopic o ServiceBusRestProxy->deleteSubscripton. Si noti che, se si elimina un argomento, vengono eliminate anche tutte le sottoscrizioni registrate con l'argomento.

L'esempio seguente illustra come eliminare un argomento denominato mytopic e le relative sottoscrizioni registrate.

require_once 'vendor/autoload.php';

use WindowsAzure\ServiceBus\ServiceBusService;
use WindowsAzure\ServiceBus\ServiceBusSettings;
use WindowsAzure\Common\ServiceException;

// Create Service Bus REST proxy.
$serviceBusRestProxy = ServicesBuilder::getInstance()->createServiceBusService($connectionString);

try    {        
    // Delete topic.
    $serviceBusRestProxy->deleteTopic("mytopic");
}
catch(ServiceException $e){
    // Handle exception based on error codes and messages.
    // Error codes and messages are here: 
    // http://msdn.microsoft.com/library/azure/dd179357
    $code = $e->getCode();
    $error_message = $e->getMessage();
    echo $code.": ".$error_message."<br />";
}

È possibile eliminare una sottoscrizione in modo indipendente usando il metodo deleteSubscription:

$serviceBusRestProxy->deleteSubscription("mytopic", "mysubscription");

Passaggi successivi

A questo punto, dopo aver appreso le nozioni di base delle code del bus di servizio, vedere Code, argomenti e sottoscrizioni per altre informazioni.