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:
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.
- Selezionare File>Nuovo>progetto
- Selezionare Piattaforma>Windows
- Selezionare App console (.NET Framework)
- Selezionare Avanti
- Nel campo Nome progetto immettere un nome per l'applicazione
- 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:
- Libreria Azure.Core per .NET: questo pacchetto offre primitive, astrazioni e helper condivisi per le moderne librerie client di Azure SDK per .NET.
- Libreria client Azure.Storage.Common per .NET: questo pacchetto offre l'infrastruttura condivisa dalle altre librerie client di Archiviazione di Azure.
- Libreria client Azure.Storage.Queues per .NET: questo pacchetto consente di lavorare con Archiviazione code di Azure per archiviare i messaggi a cui un client può accedere.
- Libreria System.Configuration.ConfigurationManager per .NET: questo pacchetto consente di accedere ai file di configurazione per le applicazioni client.
È possibile usare NuGet per ottenere questi pacchetti. Seguire questa procedura:
- Fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni e scegliere Gestisci pacchetti NuGet.
- Selezionare Sfoglia
- Cercare online e
Azure.Storage.Queues
selezionare 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. - Cercare online e
System.Configuration.ConfigurationManager
selezionare 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:
Passare al portale di Azure.
Individuare l'account di archiviazione.
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.
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.
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 informazioni dettagliate sulle API disponibili, vedere la documentazione di riferimento sull'archiviazione code:
- Per ulteriori opzioni di archiviazione dei dati in Azure, consultare altre guide alle funzionalità.
- Introduzione ad Archiviazione tabelle di Azure con .NET per archiviare i dati strutturati.
- Iniziare a usare Archiviazione BLOB di Azure con .NET per archiviare dati non strutturati.
- Per archiviare i dati relazionali, vedere Connettersi al database SQL tramite .NET (C#).
- Per altre informazioni su come semplificare il codice scritto da usare con Archiviazione di Azure, vedere Informazioni su Azure WebJobs SDK.
Per esempi di codice correlati che usano sdk .NET versione 11.x deprecati, vedere Esempi di codice con .NET versione 11.x.