Rozpoczynanie pracy z usługą Azure Queue Storage przy użyciu platformy .NET

Omówienie

Usługa Azure Queue Storage udostępnia komunikaty w chmurze między składnikami aplikacji. Podczas projektowania aplikacji na potrzeby skalowania składniki aplikacji są często oddzielone, dzięki czemu można je skalować niezależnie. Usługa Queue Storage dostarcza asynchroniczne komunikaty między składnikami aplikacji, niezależnie od tego, czy działają w chmurze, na pulpicie, na serwerze lokalnym, czy na urządzeniu przenośnym. Usługa Queue Storage obsługuje również zarządzanie zadaniami asynchronicznymi i tworzeniem przepływów pracy procesu.

Informacje o tym samouczku

W tym samouczku pokazano, jak napisać kod platformy .NET w niektórych typowych scenariuszach przy użyciu usługi Azure Queue Storage. Omówione scenariusze obejmują tworzenie i usuwanie kolejek oraz dodawanie, odczytywanie i usuwanie komunikatów kolejek.

Szacowany czas trwania: 45 minut

Wymagania wstępne

Co to jest usługa Queue Storage?

Azure Queue Storage to usługa do przechowywania dużej liczby komunikatów, do której można uzyskać dostęp z dowolnego miejsca na świecie za pośrednictwem uwierzytelnionego połączenia za pomocą protokołu HTTP lub HTTPS. Pojedynczy komunikat z kolejki nie może przekraczać 64 KB, a kolejka może zawierać miliony komunikatów — maksymalnie liczbę nieprzekraczającą całkowitego limitu pojemności konta magazynu. Usługa Queue Storage jest często używana do tworzenia listy prac w celu przetwarzania asynchronicznego.

Pojęcia dotyczące usługi kolejki

Usługa Azure Queue service zawiera następujące składniki:

Składniki usługi Azure Queue Service

  • Konto magazynu: cały dostęp do usługi Azure Storage odbywa się przez konto magazynu. Aby uzyskać więcej informacji na temat kont magazynu, zobacz Omówienie konta magazynu.

  • Kolejka: kolejka zawiera zestaw komunikatów. Wszystkie komunikaty muszą być w kolejce. Pamiętaj, że nazwa kolejki może zawierać tylko małe litery. Informacje dotyczące nazewnictwa kolejek można znaleźć w temacie Naming Queues and Metadata (Nazewnictwo kolejek i metadanych).

  • Komunikat: komunikat w dowolnym formacie, o maksymalnym rozmiarze 64 KB. Maksymalny czas pozostawania komunikatu w kolejce wynosi 7 dni. W przypadku wersji 2017-07-29 lub nowszej maksymalny czas wygaśnięcia może być dowolną liczbą dodatnią lub -1 wskazującą, że komunikat nie wygaśnie. Jeśli ten parametr zostanie pominięty, domyślny czas wygaśnięcia wynosi siedem dni.

  • Format adresu URL: Kolejki są adresowalne przy użyciu następującego formatu adresu URL: http://<storage account>.queue.core.windows.net/<queue>

    Następujący adres URL dotyczy kolejki w schemacie:

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

Tworzenie konta usługi Azure Storage

Najprościej jest utworzyć pierwsze konto usługi Azure Storage przy użyciu witryny Azure Portal. Więcej informacji można znaleźć w temacie Tworzenie konta magazynu.

Można również utworzyć konto usługi Azure Storage przy użyciu programu Azure PowerShell, interfejsu wiersza polecenia Azure lub dostawcy zasobów usługi Azure Storage dla platformy .NET.

Jeśli w tej chwili nie chcesz tworzyć konta magazynu na platformie Azure, możesz również użyć emulatora magazynu Azurite, aby uruchomić i przetestować kod w środowisku lokalnym. Aby uzyskać więcej informacji, zobacz Use the Azurite emulator for local Azure Storage development (Używanie emulatora Azurite do lokalnego programowania w usłudze Azure Storage).

Konfigurowanie środowiska projektowego

Następnie skonfiguruj środowisko projektowe w programie Visual Studio, aby przygotować się do wypróbowania przykładów kodu zawartych w tym przewodniku.

Utwórz projekt aplikacji konsolowej dla systemu Windows

W programie Visual Studio utwórz nową aplikację konsoli dla systemu Windows. W poniższych krokach pokazano, jak utworzyć aplikację konsolową w programie Visual Studio 2019. Procedura jest podobna w innych wersjach programu Visual Studio.

  1. Wybierz pozycję Plik>nowy>projekt
  2. Wybierz pozycję Platforma>Windows
  3. Wybierz pozycję Aplikacja konsolowa (.NET Framework)
  4. Wybierz pozycję Dalej
  5. W polu Nazwa projektu wprowadź nazwę aplikacji
  6. Wybierz pozycję Utwórz

Wszystkie przykłady kodu w tym samouczku można dodać do metody Main() w pliku Program.cs aplikacji konsolowej.

Biblioteki klienta usługi Azure Storage można używać w dowolnym typie aplikacji .NET, w tym usługi w chmurze platformy Azure lub aplikacji internetowej oraz aplikacji klasycznych i mobilnych. W tym przewodniku dla uproszczenia przedstawiono aplikację konsolową.

Użycie pakietu NuGet w celu zainstalowania wymaganych pakietów

Aby ukończyć ten samouczek, należy odwołać się do następujących czterech pakietów w projekcie:

Do uzyskania tych pakietów można użyć narzędzia NuGet. Wykonaj następujące kroki:

  1. Kliknij prawym przyciskiem myszy projekt w Eksplorator rozwiązań i wybierz polecenie Zarządzaj pakietami NuGet.
  2. Wybierz pozycję Przeglądaj
  3. Wyszukaj w trybie online Azure.Storage.Queues, a następnie wybierz pozycję Zainstaluj , aby zainstalować bibliotekę klienta usługi Azure Storage i jej zależności. Spowoduje to również zainstalowanie bibliotek Azure.Storage.Common i Azure.Core, które są zależnościami biblioteki kolejek.
  4. Wyszukaj w trybie online ciąg System.Configuration.ConfigurationManager, a następnie wybierz pozycję Zainstaluj, aby zainstalować Configuration Manager.

Określanie środowiska docelowego

W przypadku uruchamiania przykładów w tym przewodniku istnieją dwie opcje środowiska:

Uwaga

Na obiekt docelowy można wybrać emulator magazynu, aby uniknąć ponoszenia kosztów związanych z usługą Azure Storage. Jeśli jednak zdecydujesz się na docelowe konto usługi Azure Storage w chmurze, koszty wykonania tego samouczka będą niewielkie.

Pobieranie parametrów połączenia magazynu

Biblioteki klienta usługi Azure Storage dla platformy .NET obsługują parametry połączenia magazynu w celu skonfigurowania punktów końcowych i poświadczeń na potrzeby uzyskiwania dostępu do usług magazynu. Aby uzyskać więcej informacji, zobacz Zarządzanie kluczami dostępu do konta magazynu.

Kopiowanie poświadczeń z witryny Azure Portal

Przykładowy kod musi autoryzować dostęp do konta magazynu. Na potrzeby autoryzacji podajesz aplikacji swoje poświadczenia konta magazynu w postaci parametrów połączenia. Aby wyświetlić swoje poświadczenia konta magazynu:

  1. Przejdź do witryny Azure Portal.

  2. Odszukaj konto magazynu.

  3. W sekcji Ustawienia omówienia kont magazynu wybierz pozycję Klucze dostępu. Zostaną wyświetlone klucze dostępu do Twojego konta, a także pełne parametry połączenia dla każdego klucza.

  4. Znajdź wartość Parametry połączenia w obszarze key1i kliknij przycisk Kopiuj, aby skopiować parametry połączenia. W następnym kroku dodasz wartość parametrów połączenia do zmiennej środowiskowej.

    Zrzut ekranu pokazujący sposób kopiowania parametrów połączenia z witryny Azure Portal

Aby uzyskać więcej informacji dotyczących parametrów połączenia, zobacz Konfigurowanie parametrów połączenia z usługą Azure Storage.

Uwaga

Klucz konta magazynu jest podobny do hasła głównego konta magazynu. Zawsze chroń klucz konta magazynu. Nie udostępniaj go innym użytkownikom, nie koduj go trwale ani nie zapisuj w zwykłym pliku tekstowym, do którego mają dostęp inne osoby. Wygeneruj ponownie klucz za pośrednictwem witryny Azure Portal, jeśli uważasz, że jego zabezpieczenia mogły zostać naruszone.

Najlepiej przechowywać parametry połączenia magazynu w pliku konfiguracji. Aby skonfigurować parametry połączenia, otwórz plik app.config z Eksploratora rozwiązań w programie Visual Studio. Dodaj zawartość elementu pokazanego <appSettings> tutaj. Zastąp connection-string wartość skopiowaną z konta magazynu w portalu:

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

Na przykład ustawienie konfiguracji może wyglądać mniej więcej tak:

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

Aby kierować się do emulatora magazynu Azurite, możesz użyć skrótu mapowania na dobrze znaną nazwę konta i klucz. W takim przypadku ustawienie parametrów połączenia wygląda następująco:

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

Dodawanie dyrektyw using

Dodaj następujące dyrektywy using na początku pliku 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

Tworzenie klienta usługi Queue Storage

Klasa QueueClient umożliwia pobieranie kolejek przechowywanych w usłudze Queue Storage. Oto jeden ze sposobów tworzenia klienta usługi:

//-------------------------------------------------
// 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);
}

Porada

Komunikaty wysyłane przy użyciu QueueClient klasy muszą być w formacie, który można uwzględnić w żądaniu XML z kodowaniem UTF-8. Opcjonalnie możesz ustawić opcję MessageEncoding na Base64 , aby obsłużyć komunikaty niezgodne.

Teraz możesz napisać kod, który odczytuje dane z usługi Queue Storage i zapisuje je w usłudze Queue Storage.

Tworzenie kolejki

W tym przykładzie pokazano, jak utworzyć kolejkę:

//-------------------------------------------------
// 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;
    }
}

Wstawianie komunikatu do kolejki

Aby wstawić komunikat do istniejącej kolejki, wywołaj metodę SendMessage . Komunikat może być ciągiem (w formacie UTF-8) lub tablicą bajtów. Poniższy kod tworzy kolejkę (jeśli nie istnieje) i wstawia komunikat:

//-------------------------------------------------
// 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}");
}

Podgląd kolejnego komunikatu

Komunikaty w kolejce można wyświetlać bez usuwania ich z kolejki przez wywołanie PeekMessages metody . Jeśli nie przekażesz wartości parametru, wartością domyślną jest zajrzeć do jednego komunikatu maxMessages .

//-------------------------------------------------
// 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}'");
    }
}

Zmiana zawartości komunikatu w kolejce

Możesz zmienić zawartość komunikatu w kolejce. Jeśli komunikat reprezentuje zadanie robocze, możesz użyć tej funkcji, aby zaktualizować stan zadania. Poniższy kod aktualizuje komunikat kolejki o nową zawartość i ustawia rozszerzenie limitu czasu widoczności o kolejne 60 sekund. Operacja ta zapisuje stan pracy powiązanej z komunikatem i daje klientowi kolejną minutę na kontynuowanie pracy nad komunikatem. Można użyć tej techniki do śledzenia wieloetapowych przepływów pracy w komunikatach kolejki bez konieczności rozpoczynania się od początku, jeśli krok przetwarzania zakończy się niepowodzeniem z powodu awarii sprzętu lub oprogramowania. Zazwyczaj stosuje się również liczbę ponownych prób. Jeśli komunikat zostanie ponowiony więcej niż n razy, zostanie usunięty. Jest to zabezpieczenie przed komunikatami, które wyzwalają błąd aplikacji zawsze, gdy są przetwarzane.

//-------------------------------------------------
// 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
            );
    }
}

Dequeue następnej wiadomości

Dequeue komunikat z kolejki w dwóch krokach. Po wywołaniu metody ReceiveMessageszostanie wyświetlony następny komunikat w kolejce. Komunikat zwrócony z ReceiveMessages staje się niewidoczny dla każdego innego kodu odczytujących komunikaty z tej kolejki. Domyślnie komunikat pozostanie niewidoczny przez 30 sekund. Aby zakończyć usuwanie komunikatu z kolejki, należy również wywołać metodę DeleteMessage. Ten dwuetapowy proces usuwania komunikatów gwarantuje, że jeśli kod nie będzie w stanie przetworzyć komunikatu z powodu awarii sprzętu lub oprogramowania, inne wystąpienie kodu będzie w stanie uzyskać ten sam komunikat i ponowić próbę. Kod wywołuje się DeleteMessage bezpośrednio po przetworzeniu komunikatu.

//-------------------------------------------------
// 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);
    }
}

Używanie wzorca Async-Await z typowymi interfejsami API usługi Queue Storage

W tym przykładzie pokazano, jak używać wzorca Async-Await z typowymi interfejsami API usługi Queue Storage. Przykład wywołuje asynchroniczną wersję każdej z podanych metod, wskazaną Async przez sufiks każdej metody. W przypadku użycia metody asynchronicznej wzorzec Async-Await zawiesza wykonywanie lokalne do momentu zakończenia wywołania. Takie zachowanie umożliwia wykonywanie innych zadań przez bieżący wątek, co pomaga unikać wąskich gardeł zmniejszających wydajność i poprawia ogólną szybkość reakcji aplikacji. Aby uzyskać więcej informacji na temat używania wzorca Async-Await na platformie .NET, zobacz Async and Await (C# i 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}'");
}

Użyj dodatkowych opcji usuwania komunikatów w kolejce

Istnieją dwa sposoby dostosowania pobierania komunikatów z kolejki. Po pierwsze można uzyskać komunikaty zbiorczo (do 32). Po drugie można ustawić dłuższy lub krótszy limit czasu niewidoczności, dzięki czemu kod będzie mieć więcej lub mniej czasu na pełne przetworzenie każdego komunikatu.

Poniższy przykład kodu używa ReceiveMessages metody , aby uzyskać 20 komunikatów w jednym wywołaniu. Następnie przetwarza każdy komunikat przy użyciu foreach pętli. Ustawia również limitu czasu niewidoczności na pięć minut dla każdego komunikatu. Należy pamiętać, że pięć minut rozpoczyna się dla wszystkich komunikatów w tym samym czasie, więc po upływie pięciu minut od wywołania metody ReceiveMessages, wszystkie komunikaty, które nie zostały usunięte, staną się ponownie widoczne.

//-----------------------------------------------------
// 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);
        }
    }
}

Pobieranie długości kolejki

Możesz uzyskać szacunkową liczbę komunikatów w kolejce. Metoda GetProperties zwraca właściwości kolejki, w tym liczbę komunikatów. Właściwość ApproximateMessagesCount zawiera przybliżoną liczbę komunikatów w kolejce. Ta liczba nie jest mniejsza niż rzeczywista liczba komunikatów w kolejce, ale może być wyższa.

//-----------------------------------------------------
// 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}");
    }
}

Usuwanie kolejki

Aby usunąć kolejkę i wszystkie zawarte w nim komunikaty, wywołaj Delete metodę w obiekcie kolejki.

//-------------------------------------------------
// 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}'");
}

Następne kroki

Teraz, gdy znasz już podstawy usługi Queue Storage, skorzystaj z tych linków, aby dowiedzieć się więcej o bardziej złożonych zadaniach magazynu.

Aby uzyskać powiązane przykłady kodu korzystające z przestarzałych zestawów SDK platformy .NET w wersji 11.x, zobacz Przykłady kodu korzystające z platformy .NET w wersji 11.x.