Come usare le code del bus di servizio con PHP

Questa guida illustra come usare le code del bus di servizio. Gli esempi sono scritti in PHP e usano Azure SDK per PHP. Gli scenari presentati includono la creazione di code, l'invio e la ricezione di messaggi e l'eliminazione di code.

Informazioni sulle code del bus di servizio

Le code del bus di servizio supportano un modello di comunicazione con messaggistica negoziata . Quando si usano le code, i componenti di un'applicazione distribuita non comunicano direttamente l'uno con l'altro, ma scambiano messaggi tramite una coda, che agisce da intermediario (broker). Un producer di messaggi (mittente) invia un messaggio alla coda e quindi prosegue con la relativa elaborazione. In modo asincrono, il consumer di messaggi (ricevitore) recupera il messaggio dalla coda e lo elabora. Il producer non deve attendere la risposta del consumer per continuare a elaborare e inviare ulteriori messaggi. Le code consentono un recapito dei messaggi di tipo FIFO (First In, First Out) a uno o più consumer concorrenti. In base a questo metodo, in genere i messaggi vengono ricevuti ed elaborati nell'ordine temporale in cui sono stati aggiunti alla coda e ogni messaggio viene ricevuto ed elaborato da un solo consumer.

Concetti relativi alle code

Le code del bus di servizio sono una tecnologia di carattere generale che può essere usata in numerosi scenari:

  • Comunicazione tra ruoli Web e di lavoro in un'applicazione Azure multilivello.
  • Comunicazione tra app locali e app ospitate in Azure in una soluzione ibrida.
  • Comunicazione tra componenti di un'applicazione distribuita in esecuzione in locale in organizzazioni diverse o in reparti diversi della stessa organizzazione.

L'uso delle code consente la scalabilità delle applicazioni e garantisce maggiore resilienza all'architettura.

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.

In questa guida si useranno le funzionalità del servizio che possono essere chiamate da 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. Creare un file denominato composer.json nella radice del progetto, quindi aggiungere nel file il codice seguente:

    {
      "require": {
        "microsoft/azure-storage": "*"
      }
    }
    
  2. Scaricare composer.phar nella radice del progetto.
  3. Aprire un prompt dei comandi ed eseguire il comando seguente nella radice del progetto

    php composer.phar install
    

In alternativa andare alla libreria client PHP di Archiviazione di Microsoft Azure su GitHub per clonare il codice sorgente.

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

Per usare le API delle code del bus di servizio, procedere come segue:

  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 ServicesBuilder.

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];SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=[Primary Key]

Dove Endpoint è in genere nel formato [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];SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=[Primary Key]";

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

Creare una coda

È possibile eseguire operazioni di gestione per le code 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->createQueue per creare una coda denominata myqueue in uno spazio dei nomi del servizio MySBNamespace:

require_once 'vendor/autoload.php';

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

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

try    {
    $queueInfo = new QueueInfo("myqueue");

    // Create queue.
    $serviceBusRestProxy->createQueue($queueInfo);
}
catch(ServiceException $e){
    // Handle exception based on error codes and messages.
    // Error codes and messages are here: 
    // https://docs.microsoft.com/rest/api/storageservices/Common-REST-API-Error-Codes
    $code = $e->getCode();
    $error_message = $e->getMessage();
    echo $code.": ".$error_message."<br />";
}

Nota

È possibile usare il metodo listQueues negli oggetti ServiceBusRestProxy per verificare se in uno spazio dei nomi esiste già una coda con il nome specificato.

Inviare messaggi a una coda

Per inviare un messaggio a una coda del bus di servizio, l'applicazione chiama il metodo ServiceBusRestProxy->sendQueueMessage. Il seguente codice illustra come inviare un messaggio alla coda myqueue creata in precedenza all'interno dello 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->sendQueueMessage("myqueue", $message);
}
catch(ServiceException $e){
    // Handle exception based on error codes and messages.
    // Error codes and messages are here: 
    // https://docs.microsoft.com/rest/api/storageservices/Common-REST-API-Error-Codes
    $code = $e->getCode();
    $error_message = $e->getMessage();
    echo $code.": ".$error_message."<br />";
}

I messaggi inviati e ricevuti dalle code del bus di servizio sono istanze della classe BrokeredMessage. Gli oggetti BrokeredMessage includono un set di proprietà e metodi standard usati per contenere le proprietà personalizzate specifiche dell'applicazione e un corpo di dati arbitrari dell'applicazione.

Le code 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 una coda, mentre è prevista una limitazione alla dimensione totale dei messaggi di una coda. Il limite massimo della dimensione di una coda è di 5 GB.

Ricevere messaggi da una coda

Il modo ideale per ricevere i messaggi da una coda prevede l'uso di un metodo ServiceBusRestProxy->receiveQueueMessage. È possibile ricevere i messaggi in due modi diversi: 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 per un messaggio in una coda, lo contrassegna come utilizzato 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 utilizzare, 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 the receive mode to PeekLock (default is ReceiveAndDelete).
    $options = new ReceiveMessageOptions();
    $options->setPeekLock();

    // Receive message.
    $message = $serviceBusRestProxy->receiveQueueMessage("myqueue", $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 "Message deleted.<br />";
    $serviceBusRestProxy->deleteMessage($message);
}
catch(ServiceException $e){
    // Handle exception based on error codes and messages.
    // Error codes and messages are here:
    // https://docs.microsoft.com/rest/api/storageservices/Common-REST-API-Error-Codes
    $code = $e->getCode();
    $error_message = $e->getMessage();
    echo $code.": ".$error_message."<br />";
}

Come 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,è consigliabile 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.

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.

Per altre informazioni, vedere anche il Centro per sviluppatori PHP.