Condividi tramite


Introduzione all'archiviazione code di Azure con .NET

Panoramica

Archiviazione code di Azure fornisce la messaggistica cloud tra i componenti dell'applicazione. Nella progettazione di applicazioni per la scalabilità, i componenti dell'applicazione sono spesso disaccoppiati in modo che possano essere ridimensionati in modo indipendente. Archiviazione code fornisce la messaggistica asincrona tra i componenti dell'applicazione, indipendentemente dal fatto che siano in esecuzione nel cloud, sul desktop, in un server locale o in un dispositivo mobile. Archiviazione code supporta anche la gestione di attività asincrone e la creazione di flussi di lavoro dei processi.

Informazioni sull'esercitazione

Questa esercitazione illustra come scrivere codice .NET per alcuni scenari comuni con Archiviazione code di Azure. Gli scenari presentati includono creazione ed eliminazione di code, nonché aggiunta, lettura ed eliminazione di messaggi nella coda.

Tempo previsto per il completamento: 45 minuti

Prerequisiti

Che cos'è l'archiviazione code?

Il servizio di archiviazione di accodamento di Azure consente di archiviare grandi quantità di messaggi ai quali è possibile accedere da qualsiasi parte del mondo mediante chiamate autenticate tramite HTTP o HTTPS. La dimensione massima di un singolo messaggio della coda è di 64 KB e una coda può contenere milioni di messaggi, nei limiti della capacità complessiva di un account di archiviazione. L'archiviazione code viene spesso usata per creare un backlog di lavoro da elaborare in modo asincrono.

Concetti del servizio di accodamento

Il servizio di accodamento di Azure contiene i componenti seguenti:

Componenti del servizio code di Azure

  • Account di archiviazione: Tutti gli accessi ad Archiviazione di Azure vengono eseguiti tramite un account di archiviazione. Per altre informazioni sugli account di archiviazione, vedere Panoramica dell'account di archiviazione.

  • Coda: una coda contiene un set di messaggi. Tutti i messaggi devono essere inclusi in una coda. Si noti che il nome della coda deve essere in lettere minuscole. Per altre informazioni, vedere Denominazione di code e metadati.

  • Messaggio: un messaggio, in qualsiasi formato, con dimensioni massime di 64 KB. Il tempo massimo che un messaggio può rimanere nella coda è di 7 giorni. Per la versione 2017-07-29 o successive, la durata massima consentita può essere un numero positivo qualsiasi o -1, a indicare che il messaggio non scade. Se questo parametro viene omesso, la durata predefinita è di sette giorni.

  • Formato URL: Le code sono indirizzabili usando il formato URL seguente: http://<storage account>.queue.core.windows.net/<queue>

    L'URL seguente fa riferimento a una delle code nel diagramma:

    http://myaccount.queue.core.windows.net/incoming-orders

Creare un account di archiviazione di Azure

Il modo più semplice per creare il primo account di archiviazione di Azure consiste nell'usare il portale di Azure. Per altre informazioni, vedere Creare un account di archiviazione.

È anche possibile creare un account di archiviazione di Azure usando Azure PowerShell, l'interfaccia della riga di comando di Azure o il provider di risorse di archiviazione di Azure per .NET.

Se in questo momento non si preferisce creare un account di archiviazione in Azure, è anche possibile usare l'emulatore di archiviazione Azurite per eseguire e testare il codice in un ambiente locale. Per altre informazioni, vedere Usare l'emulatore Azurite per lo sviluppo locale di Archiviazione di Azure.

Configurazione dell'ambiente di sviluppo

Configurare quindi l'ambiente di sviluppo in Visual Studio per poter provare gli esempi di codice di questa guida.

Creare un progetto di applicazione console di Windows

In Visual Studio creare una nuova applicazione console di Windows. La procedura seguente illustra come creare un'applicazione console in Visual Studio 2019. La procedura è simile per le altre versioni di Visual Studio.

  1. Selezionare File>Nuovo>progetto
  2. Selezionare Piattaforma>Windows
  3. Selezionare App console (.NET Framework)
  4. Selezionare Avanti
  5. Nel campo Nome progetto immettere un nome per l'applicazione
  6. Selezionare Crea

Tutti gli esempi di codice in questa esercitazione possono essere aggiunti al metodo Main() del file Program.cs dell'applicazione console.

È possibile usare le librerie client di Archiviazione di Azure in qualsiasi tipo di applicazione .NET, tra cui un servizio cloud di Azure o un'app Web e applicazioni desktop e per dispositivi mobili. Per semplicità, in questa guida si usa un'applicazione console.

Usare NuGet per installare i pacchetti necessari

Per completare questa esercitazione, è necessario fare riferimento ai quattro pacchetti seguenti nel progetto:

È possibile usare NuGet per ottenere questi pacchetti. Seguire questa procedura:

  1. Fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni e scegliere Gestisci pacchetti NuGet.
  2. Selezionare Sfoglia
  3. Cercare online e Azure.Storage.Queuesselezionare Installa per installare la libreria client di Archiviazione di Azure e le relative dipendenze. Verranno inoltre installate le librerie Azure.Storage.Common e Azure.Core, che sono dipendenze della libreria code.
  4. Cercare online e System.Configuration.ConfigurationManagerselezionare Installa per installare il Configuration Manager.

Determinare l'ambiente di destinazione

Sono disponibili due opzioni relative all'ambiente per l'esecuzione degli esempi di questa guida:

  • È possibile eseguire il codice con un account di archiviazione di Azure nel cloud.
  • È possibile eseguire il codice nell'emulatore di archiviazione Di Azurite. Azurite è un ambiente locale che emula un account di archiviazione di Azure nel cloud. Azurite è un'opzione gratuita per il test e il debug del codice mentre l'applicazione è in fase di sviluppo. L'emulatore usa un account e una chiave noti. Per altre informazioni, vedere Usare l'emulatore Azurite per lo sviluppo e il test di Archiviazione di Azure locali.

Nota

È possibile impostare come destinazione l'emulatore di archiviazione per evitare di incorrere negli eventuali costi associati al servizio Archiviazione di Azure. Tuttavia, se si sceglie di specificare come destinazione un account di archiviazione di Azure nel cloud, i costi per l'esecuzione di questa esercitazione saranno trascurabili.

Ottenere la stringa di connessione di archiviazione

Le librerie client di Archiviazione di Azure per .NET supportano l'uso di una stringa di connessione di archiviazione per configurare endpoint e credenziali per l'accesso ai servizi di archiviazione. Per altre informazioni, vedere Gestire le chiavi di accesso dell'account di archiviazione.

Copiare le credenziali dal portale di Azure

Il codice di esempio deve autorizzare l'accesso all'account di archiviazione. Per eseguire l'autorizzazione, si passano all'applicazione le credenziali dell'account di archiviazione sotto forma di stringa di connessione. Per visualizzare le credenziali dell'account di archiviazione:

  1. Passare al portale di Azure.

  2. Individuare l'account di archiviazione.

  3. Nella sezione Impostazioni della panoramica dell'account di archiviazione selezionare Chiavi di accesso. Verranno visualizzate le chiavi di accesso dell'account, con la stringa di connessione completa per ogni chiave.

  4. Trovare il valore Stringa di connessione in key1 e fare clic sul pulsante Copia per copiare la stringa di connessione. Il valore della stringa di connessione verrà aggiunto a una variabile di ambiente nel passaggio successivo.

    Screenshot che mostra come copiare una stringa di connessione dal portale di Azure

Per altre informazioni sulle stringhe di connessione, vedere Configurare le stringhe di connessione di archiviazione di Azure.

Nota

La chiave dell’account di archiviazione è simile alla password radice per l'account di archiviazione. È consigliabile proteggere sempre la chiave dell'account di archiviazione. Evitare di distribuirla ad altri utenti, impostarla come hardcoded o salvarla in un file di testo normale accessibile ad altri. Rigenerare la chiave tramite il portale di Azure se si ritiene che possa essere stata compromessa.

Per gestire nel modo migliore la stringa di connessione di archiviazione, usare un file di configurazione. Per configurare la stringa di connessione, aprire il file app.config da Esplora soluzioni in Visual Studio. Aggiungere il contenuto dell'elemento <appSettings> illustrato qui. Sostituire connection-string con il valore copiato dall'account di archiviazione nel portale:

<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
    </startup>
    <appSettings>
        <add key="StorageConnectionString" value="connection-string" />
    </appSettings>
</configuration>

Ad esempio, l'impostazione di configurazione si presenta simile a:

<add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=storagesample;AccountKey=GMuzNHjlB3S9itqZJHHCnRkrokLkcSyW7yK9BRbGp0ENePunLPwBgpxV1Z/pVo9zpem/2xSHXkMqTHHLcx8XRA==EndpointSuffix=core.windows.net" />

Per indirizzare l'emulatore di archiviazione Azurite, è possibile usare un collegamento che esegue il mapping al nome e alla chiave dell'account noti. In questo caso, l'impostazione della stringa di connessione è:

<add key="StorageConnectionString" value="UseDevelopmentStorage=true" />

Aggiungere le direttive using

Aggiungere le direttive using seguenti all'inizio del file Program.cs:

using System; // Namespace for Console output
using System.Configuration; // Namespace for ConfigurationManager
using System.Threading.Tasks; // Namespace for Task
using Azure.Identity;
using Azure.Storage.Queues; // Namespace for Queue storage types
using Azure.Storage.Queues.Models; // Namespace for PeekedMessage

Creare il client di archiviazione code

La QueueClient classe consente di recuperare le code archiviate in Archiviazione code. Ecco come creare il client del servizio:

//-------------------------------------------------
// Create the queue service client
//-------------------------------------------------
public void CreateQueueClient(string queueName)
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instantiate a QueueClient which will be used to create and manipulate the queue
    QueueClient queueClient = new QueueClient(connectionString, queueName);
}

Suggerimento

I messaggi inviati tramite la QueueClient classe devono essere in un formato che può essere incluso in una richiesta XML con codifica UTF-8. Facoltativamente, è possibile impostare l'opzione MessageEncoding su Base64 per gestire messaggi non conformi.

È ora possibile scrivere codice che legge i dati da e scrive i dati in Archiviazione code.

Creare una coda

Questo esempio illustra come creare una coda:

//-------------------------------------------------
// Create a message queue
//-------------------------------------------------
public bool CreateQueue(string queueName)
{
    try
    {
        // Get the connection string from app settings
        string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

        // Instantiate a QueueClient which will be used to create and manipulate the queue
        QueueClient queueClient = new QueueClient(connectionString, queueName);

        // Create the queue
        queueClient.CreateIfNotExists();

        if (queueClient.Exists())
        {
            Console.WriteLine($"Queue created: '{queueClient.Name}'");
            return true;
        }
        else
        {
            Console.WriteLine($"Make sure the Azurite storage emulator running and try again.");
            return false;
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Exception: {ex.Message}\n\n");
        Console.WriteLine($"Make sure the Azurite storage emulator running and try again.");
        return false;
    }
}

Inserire un messaggio in una coda

Per inserire un messaggio in una coda esistente, chiamare il metodo SendMessage. Un messaggio può essere una stringa (in formato UTF-8) o una matrice di byte. Il codice seguente crea una coda (se non esiste) e inserisce un messaggio:

//-------------------------------------------------
// Insert a message into a queue
//-------------------------------------------------
public void InsertMessage(string queueName, string message)
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instantiate a QueueClient which will be used to create and manipulate the queue
    QueueClient queueClient = new QueueClient(connectionString, queueName);

    // Create the queue if it doesn't already exist
    queueClient.CreateIfNotExists();

    if (queueClient.Exists())
    {
        // Send a message to the queue
        queueClient.SendMessage(message);
    }

    Console.WriteLine($"Inserted: {message}");
}

Visualizzare il messaggio successivo

È possibile visualizzare un'anteprima del messaggio nella coda senza rimuoverlo chiamando il metodo PeekMessages. Se non si passa un valore per il parametro maxMessages, per impostazione predefinita viene visualizzata un'anteprima di un messaggio.

//-------------------------------------------------
// Peek at a message in the queue
//-------------------------------------------------
public void PeekMessage(string queueName)
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instantiate a QueueClient which will be used to manipulate the queue
    QueueClient queueClient = new QueueClient(connectionString, queueName);

    if (queueClient.Exists())
    { 
        // Peek at the next message
        PeekedMessage[] peekedMessage = queueClient.PeekMessages();

        // Display the message
        Console.WriteLine($"Peeked message: '{peekedMessage[0].Body}'");
    }
}

Cambiare il contenuto di un messaggio in coda

È possibile cambiare il contenuto di un messaggio inserito nella coda. Se il messaggio rappresenta un'attività di lavoro, è possibile utilizzare questa funzionalità per aggiornarne lo stato. Il codice seguente consente di aggiornare il messaggio in coda con nuovo contenuto e di impostarne il timeout di visibilità per prolungarlo di altri 60 secondi. In questo modo lo stato del lavoro associato al messaggio viene salvato e il client ha a disposizione un altro minuto per continuare l'elaborazione del messaggio. È possibile usare questa tecnica per tenere traccia dei flussi di lavoro multistep nei messaggi della coda, senza dover iniziare dall'inizio se un passaggio di elaborazione non riesce a causa di un errore hardware o software. In genere, è consigliabile mantenere anche un conteggio dei tentativi, in modo da eliminare i messaggi per cui vengono effettuati più di n tentativi. In questo modo è possibile evitare che un messaggio attivi un errore dell'applicazione ogni volta che viene elaborato.

//-------------------------------------------------
// Update an existing message in the queue
//-------------------------------------------------
public void UpdateMessage(string queueName)
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instantiate a QueueClient which will be used to manipulate the queue
    QueueClient queueClient = new QueueClient(connectionString, queueName);

    if (queueClient.Exists())
    {
        // Get the message from the queue
        QueueMessage[] message = queueClient.ReceiveMessages();

        // Update the message contents
        queueClient.UpdateMessage(message[0].MessageId, 
                message[0].PopReceipt, 
                "Updated contents",
                TimeSpan.FromSeconds(60.0)  // Make it invisible for another 60 seconds
            );
    }
}

Rimuovere il messaggio successivo dalla coda

Rimuovere un messaggio da una coda in due passaggi. Quando si chiama ReceiveMessages, viene visualizzato il messaggio successivo in una coda. Un messaggio restituito da ReceiveMessages diventa invisibile a qualsiasi altro elemento di codice che legge i messaggi di questa coda. Per impostazione predefinita, il messaggio rimane invisibile per 30 secondi. Per completare la rimozione del messaggio dalla coda, è necessario chiamare anche DeleteMessage. Questo processo in due passaggi di rimozione di un messaggio assicura che, qualora l'elaborazione di un messaggio non riesca a causa di errori hardware o software, un'altra istanza del codice sia in grado di ottenere lo stesso messaggio e di riprovare. Il codice chiama DeleteMessage subito dopo l'elaborazione del messaggio.

//-------------------------------------------------
// Process and remove a message from the queue
//-------------------------------------------------
public void DequeueMessage(string queueName)
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instantiate a QueueClient which will be used to manipulate the queue
    QueueClient queueClient = new QueueClient(connectionString, queueName);

    if (queueClient.Exists())
    {
        // Get the next message
        QueueMessage[] retrievedMessage = queueClient.ReceiveMessages();

        // Process (i.e. print) the message in less than 30 seconds
        Console.WriteLine($"Dequeued message: '{retrievedMessage[0].Body}'");

        // Delete the message
        queueClient.DeleteMessage(retrievedMessage[0].MessageId, retrievedMessage[0].PopReceipt);
    }
}

Usare il modello di Async-Await con le API di archiviazione code comuni

In questo esempio viene illustrato come usare il modello di Async-Await con le API di archiviazione code comuni. L'esempio chiama la versione asincrona di ognuno dei metodi specificati, come indicato dal Async suffisso di ogni metodo. Quando viene usato un metodo asincrono, il modello di Async-Await sospende l'esecuzione locale fino al completamento della chiamata. Questo comportamento consente al thread corrente di eseguire altre attività per evitare colli di bottiglia delle prestazioni e migliora la velocità di risposta complessiva dell'applicazione. Per ulteriori informazioni sull'utilizzo del modello Async-Await in .NET, vedere Async e Await (C# e Visual Basic)

//-------------------------------------------------
// Perform queue operations asynchronously
//-------------------------------------------------
public async Task QueueAsync(string queueName)
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instantiate a QueueClient which will be used to manipulate the queue
    QueueClient queueClient = new QueueClient(connectionString, queueName);

    // Create the queue if it doesn't already exist
    await queueClient.CreateIfNotExistsAsync();

    if (await queueClient.ExistsAsync())
    {
        Console.WriteLine($"Queue '{queueClient.Name}' created");
    }
    else
    {
        Console.WriteLine($"Queue '{queueClient.Name}' exists");
    }

    // Async enqueue the message
    await queueClient.SendMessageAsync("Hello, World");
    Console.WriteLine($"Message added");

    // Async receive the message
    QueueMessage[] retrievedMessage = await queueClient.ReceiveMessagesAsync();
    Console.WriteLine($"Retrieved message with content '{retrievedMessage[0].Body}'");

    // Async delete the message
    await queueClient.DeleteMessageAsync(retrievedMessage[0].MessageId, retrievedMessage[0].PopReceipt);
    Console.WriteLine($"Deleted message: '{retrievedMessage[0].Body}'");

    // Async delete the queue
    await queueClient.DeleteAsync();
    Console.WriteLine($"Deleted queue: '{queueClient.Name}'");
}

Usare opzioni aggiuntive per la dequeuing dei messaggi

È possibile personalizzare il recupero di messaggi da una coda in due modi. Innanzitutto, è possibile recuperare un batch di messaggi (massimo 32). In secondo luogo, è possibile impostare un timeout di invisibilità più lungo o più breve assegnando al codice più o meno tempo per l'elaborazione completa di ogni messaggio.

Nell'esempio di codice seguente viene usato il metodo ReceiveMessages per recuperare 20 messaggi con una sola chiamata. Ogni messaggio viene poi elaborato con un ciclo foreach. Per ogni messaggio, inoltre, il timeout di invisibilità viene impostato su cinque minuti. Si noti che i cinque minuti iniziano contemporaneamente per tutti i messaggi, quindi dopo cinque minuti dalla chiamata a ReceiveMessages, tutti i messaggi che non sono stati eliminati diventeranno nuovamente visibili.

//-----------------------------------------------------
// Process and remove multiple messages from the queue
//-----------------------------------------------------
public void DequeueMessages(string queueName)
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instantiate a QueueClient which will be used to manipulate the queue
    QueueClient queueClient = new QueueClient(connectionString, queueName);

    if (queueClient.Exists())
    {
        // Receive and process 20 messages
        QueueMessage[] receivedMessages = queueClient.ReceiveMessages(20, TimeSpan.FromMinutes(5));

        foreach (QueueMessage message in receivedMessages)
        {
            // Process (i.e. print) the messages in less than 5 minutes
            Console.WriteLine($"De-queued message: '{message.Body}'");

            // Delete the message
            queueClient.DeleteMessage(message.MessageId, message.PopReceipt);
        }
    }
}

Recuperare la lunghezza della coda

È possibile ottenere una stima sul numero di messaggi presenti in una coda. Il metodo GetProperties restituisce le proprietà della coda, incluso il numero dei messaggi. La proprietà ApproximateMessagesCount contiene il numero approssimativo di messaggi nella coda. Questo numero non è inferiore al numero effettivo di messaggi nella coda, ma potrebbe essere superiore.

//-----------------------------------------------------
// Get the approximate number of messages in the queue
//-----------------------------------------------------
public void GetQueueLength(string queueName)
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instantiate a QueueClient which will be used to manipulate the queue
    QueueClient queueClient = new QueueClient(connectionString, queueName);

    if (queueClient.Exists())
    {
        QueueProperties properties = queueClient.GetProperties();

        // Retrieve the cached approximate message count.
        int cachedMessagesCount = properties.ApproximateMessagesCount;

        // Display number of messages.
        Console.WriteLine($"Number of messages in queue: {cachedMessagesCount}");
    }
}

Eliminare una coda

Per eliminare una coda e tutti i messaggi che contiene, chiamare il metodo Delete sull'oggetto coda.

//-------------------------------------------------
// Delete the queue
//-------------------------------------------------
public void DeleteQueue(string queueName)
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instantiate a QueueClient which will be used to manipulate the queue
    QueueClient queueClient = new QueueClient(connectionString, queueName);

    if (queueClient.Exists())
    {
        // Delete the queue
        queueClient.Delete();
    }

    Console.WriteLine($"Queue deleted: '{queueClient.Name}'");
}

Passaggi successivi

Dopo aver appreso le nozioni di base dell'archiviazione code, seguire questi collegamenti per informazioni sulle attività di archiviazione più complesse.

Per esempi di codice correlati che usano sdk .NET versione 11.x deprecati, vedere Esempi di codice con .NET versione 11.x.