Приступая к работе с хранилищем очередей Azure с помощью .NET
Обзор
Хранилище очередей Azure — это служба, обеспечивающая обмен сообщениями в облаке между компонентами приложения. При разработке приложений для масштабирования компоненты приложения часто не связаны между собой, так что они могут масштабироваться независимо друг от друга. Хранилище очередей обеспечивает асинхронный обмен сообщениями между компонентами приложения независимо от того, где они выполняются: в облаке, на рабочем столе, локальном сервере или мобильном устройстве. Хранилище очередей также поддерживает управление асинхронными задачами и создание рабочих процессов.
О данном учебнике
В этом руководстве показано, как написать код .NET для некоторых распространенных сценариев использования хранилища очередей Azure. Эти сценарии включают создание и удаление очередей, а также добавление, чтение и удаление сообщений.
Предполагаемое время выполнения: 45 минут.
Предварительные условия
Что такое хранилище очередей?
Хранилище очередей Azure — это служба для хранения большого количества сообщений, к которым можно получить доступ практически из любой точки мира с помощью вызовов с проверкой подлинности по протоколам HTTP или HTTPS. Одно сообщение очереди может быть размером до 64 КБ, а очередь может содержать миллионы сообщений до общего ограничения емкости учетной записи хранения. Хранилище очередей часто используется для создания списка невыполненных заданий для асинхронной обработки.
Основные понятия службы очередей
Служба очередей Azure содержит следующие компоненты:
Учетная запись хранения. Весь доступ к хранилищу Azure осуществляется с помощью учетной записи хранения. См. сведения об учетных записях хранения.
Очередь. Очередь содержит набор сообщений. Все сообщения должны находиться в очереди. Обратите внимание: имя очереди должно содержать только строчные символы. Дополнительные сведения см. в статье о присвоении имен очередям и метаданным.
Сообщение. Сообщение в любом формате размером до 64 КБ. Сообщение может оставаться в очереди не более 7 дней. Начиная с версии 2017-07-29, максимальный срок жизни может быть задан любым положительным числом или значением -1, свидетельствующим о том, что срок жизни сообщения неограничен. Если этот параметр не указан, срок жизни по умолчанию составляет семь дней.
Формат URL-адреса: обращаться к очередям можно с помощью URL-адреса следующего вида: http://
<storage account>
.queue.core.windows.net/<queue>
Следующий URL-адрес позволяет обратиться к очереди на схеме:
http://myaccount.queue.core.windows.net/incoming-orders
Создание учетной записи хранения Azure
Самый простой способ создать первую учетную запись хранения Azure — воспользоваться порталом Azure. Дополнительную информацию см. в статье Об учетных записях хранения Azure.
Кроме того, создать учетную запись хранения Azure можно с помощью Azure PowerShell, Azure CLI или поставщика ресурсов службы хранилища Azure для .NET.
Если вы не хотите сейчас создавать учетную запись хранения в Azure, код можно запустить и протестировать в локальной среде с помощью эмулятора хранилища Azurite. Дополнительные сведения см. в статье Использование эмулятора Azurite для разработки и тестирования службы хранилища Azure.
Настройка среды разработки
Теперь настройте среду разработки в Visual Studio для работы с примерами кода из этого руководства.
Создание нового проекта консольного приложения Windows
В Visual Studio создайте новое консольное приложение Windows. Ниже показано, как создать консольное приложение в Visual Studio 2019. Эти же действия можно выполнить и в других версиях Visual Studio.
- Выберите Файл>Создать>Проект.
- Выберите Платформу>Windows
- Выберите Консольное приложение (.NET Framework) .
- Щелкните Далее.
- В поле Имя проекта введите имя приложения.
- Нажмите кнопку Создать
Все примеры кода из этого руководства можно добавить в метод Main()
в файле Program.cs
консольного приложения.
Вы можете использовать клиентскую библиотеку службы хранилища Azure в любом приложении .NET, в том числе в облачной службе Azure, веб-приложении Azure, классическом или мобильном приложении. Для упрощения в этом руководстве мы будем использовать консольное приложение.
Установка необходимых пакетов с помощью NuGet
Чтобы завершить работу с этим руководством, необходимо сослаться на следующие четыре пакета в проекте.
- Библиотека Azure.Core для .NET — этот пакет содержит общие примитивы, абстракции и вспомогательные методы для современных клиентских библиотек пакета SDK для .NET.
- Клиентская библиотека Azure.Storage.Common для .NET — этот пакет содержит инфраструктуру, совместно используемую другими клиентскими библиотеками службы хранилища Azure.
- Клиентская библиотека Azure.Storage.Queues для .NET — этот пакет позволяет использовать хранилище очередей Azure для хранения сообщений, доступ к которым может получить клиент.
- Библиотека System.Configuration.ConfigurationManager для .NET — этот пакет предоставляет доступ к файлам конфигурации для клиентских приложений.
Вы можете использовать NuGet для получения обоих пакетов. Выполните указанные ниже действия.
- Щелкните правой кнопкой мыши проект в обозревателе решений и выберите Управление пакетами NuGet.
- Щелкните Обзор.
- Выполните в Интернете поиск по запросу
Azure.Storage.Queues
и нажмите кнопку Установить, чтобы установить клиентскую библиотеку службы хранилища и зависимые компоненты. Кроме того, будут установлены библиотеки Azure.Storage.Common и Azure.Core, которые являются зависимостями библиотеки очередей. - Выполните в Интернете поиск по запросу
System.Configuration.ConfigurationManager
и выберите Установить, чтобы установить Configuration Manager.
Определение целевой среды
Примеры из этого руководства можно выполнять в двух средах.
- Вы можете выполнить код в учетной записи хранения Azure в облаке.
- Вы можете выполнить код в эмуляторе хранения Azure. Azurite — это локальная среда, эмулирующая учетную запись хранения Azure в облаке. Azurite можно использовать как бесплатный вариант для тестирования и отладки кода, пока приложение находится на стадии разработки. Эмулятор использует известную учетную запись и ключ. Дополнительные сведения см. в статье Использование эмулятора Azurite для разработки и тестирования службы хранилища Azure.
Примечание
Вы можете указать эмулятор хранения, чтобы избежать затрат, связанных с хранилищем Azure. Однако если вы выберете учетную запись хранения Azure в облаке, затраты на выполнение заданий в учебнике будут незначительны.
Получение параметров строк подключения службы хранилища
Библиотека клиента хранилища Azure для .NET поддерживает использование строки подключения для настройки конечных точек и учетных данных для доступа к службам хранилища. См. сведения о том, как управлять ключами доступа к учетной записи хранения.
Копирование учетных данных с портала Azure
Чтобы использовать пример кода, вам нужно авторизоваться для получения доступа к своей учетной записи хранения. Для этого предоставьте приложению учетные данные учетной записи хранения в виде строки подключения. Просмотр учетных данных учетной записи хранения:
Перейдите на портал Azure.
Перейдите к учетной записи хранения.
В разделе Параметры учетной записи хранения выберите параметр Ключи доступа. Появятся ключи доступа к учетной записи и полная строка подключения для каждого ключа.
Найдите значение Строка подключения в разделе key1 и нажмите кнопку Скопировать, чтобы скопировать строку подключения. На следующем этапе вы добавите значение строки подключения в переменную среды.
Дополнительные сведения о строках подключения см. в руководстве по настройке строк подключения службы хранилища Azure.
Примечание
Ключ учетной записи хранения похож на корневой пароль для вашей учетной записи хранения. Не забудьте защитить ключ учетной записи хранения. Не сообщайте его другим пользователям, не определяйте его в коде и не храните его в текстовом файле, доступном другим пользователям. Повторно создайте ключ с помощью портала Azure, если вы считаете, что он мог быть скомпрометирован.
Строку подключения хранилища рекомендуется хранить в файле конфигурации. Чтобы настроить строку подключения, откройте файл app.config
в обозревателе решений Visual Studio. Добавьте содержимое элемента <appSettings>
, показанное в данном примере. Замените connection-string
значением, скопированным из учетной записи хранения на портале:
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<appSettings>
<add key="StorageConnectionString" value="connection-string" />
</appSettings>
</configuration>
Например, параметр конфигурации может быть приблизительно таким:
<add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=storagesample;AccountKey=GMuzNHjlB3S9itqZJHHCnRkrokLkcSyW7yK9BRbGp0ENePunLPwBgpxV1Z/pVo9zpem/2xSHXkMqTHHLcx8XRA==EndpointSuffix=core.windows.net" />
Чтобы указать эмулятор хранения Azurite, можно использовать ярлык, который сопоставляется с хорошо известным именем и ключом. В этом случае параметр строки подключения будет таким:
<add key="StorageConnectionString" value="UseDevelopmentStorage=true" />
Добавление директив using
Добавьте в верхнюю часть файла Program.cs
следующие директивы using
:
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
Создание клиента хранилища очередей
Класс QueueClient
позволяет получать очереди, находящиеся в Хранилище очередей. Вот один из способов создать клиента службы.
//-------------------------------------------------
// 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);
}
Совет
Сообщения, отправляемые с помощью класса QueueClient
, должны быть такого формата, который можно включить в XML-запрос с кодированием UTF-8. При необходимости можно задать параметру MessageEncoding значение Base64, чтобы обрабатывать сообщения, не соответствующие этому критерию.
Теперь вы можете написать код, который считывает и записывает данные в хранилище очередей.
Создание очереди
В этом примере показано, как создать очередь:
//-------------------------------------------------
// 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;
}
}
Вставка сообщения в очередь
Чтобы вставить сообщение в существующую очередь, вызовите метод SendMessage
. Для создания объекта можно использовать либо строку (в формате UTF-8), либо массив байтов. Ниже приведен код, который создает очередь (если она не существует) и вставляет сообщение:
//-------------------------------------------------
// 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}");
}
Просмотр следующего сообщения
Вы можете просмотреть сообщение в очереди, не удаляя его из очереди, вызвав метод PeekMessages
. Если значение для параметра 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}'");
}
}
Изменение содержимого сообщения в очереди
Вы можете изменить содержимое сообщения непосредственно в очереди. Если сообщение представляет собой рабочую задачу, можно использовать эту функцию для обновления состояния рабочей задачи. Следующий код добавляет новое содержимое в очередь сообщений и продлевает время ожидания видимости еще на 60 секунд. Это сохраняет состояние работы, связанной с данным сообщением, и позволяет клиенту продолжить работу с сообщением на протяжении еще одной минуты. Этот метод можно использовать для отслеживания многошаговых рабочих процессов по сообщениям в очереди без необходимости начинать с самого начала в случае сбоя шага обработки в связи с ошибкой аппаратного или программного обеспечения. Обычно также сохраняется счетчик повторов. Если количество повторов сообщения превысит n раз, его нужно удалить. Это обеспечивает защиту от сообщений, которые инициируют ошибку приложения при каждой попытке обработки.
//-------------------------------------------------
// 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
);
}
}
Удаление следующего сообщения из очереди
Удалить сообщение из очереди можно в два этапа. При вызове метода ReceiveMessages
вы получаете следующее сообщение в очереди. Сообщение, возвращаемое методом ReceiveMessages
, становится невидимым для другого кода, считывающего сообщения из этой очереди. По умолчанию это сообщение остается невидимым в течение 30 секунд. Чтобы завершить удаление сообщения из очереди, необходимо также вызвать метод DeleteMessage
. Этот двухэтапный процесс удаления сообщения позволяет удостовериться, что если коду не удастся обработать сообщение из-за сбоя оборудования или программного обеспечения, другой экземпляр кода сможет получить то же сообщение и повторить попытку. Код вызывает DeleteMessage
сразу после обработки сообщения.
//-------------------------------------------------
// 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);
}
}
Использование алгоритма Async-Await со стандартными интерфейсами API хранилища очередей
В этом примере показано использование алгоритма Async-Await со стандартными интерфейсами API хранилища очередей. Вызывается асинхронная версия каждого из методов, на что указывает суффикс Async
в их названиях. При использовании асинхронного метода алгоритм Async-Await приостанавливает локальное выполнение процесса до завершения вызова. Благодаря этому текущий поток может выполнять другие задачи, что позволяет избежать возникновения узких мест и повысить общую скорость реагирования приложения. Дополнительные сведения об использовании алгоритма Async-Await в .NET см. в статье Асинхронное программирование с использованием ключевых слов Async и Await (C# и 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}'");
}
Дополнительные варианты удаления сообщений из очереди
Способ извлечения сообщения из очереди можно настроить двумя способами. Во-первых, можно получить пакет сообщений (до 32 сообщений). Во-вторых, можно задать более длительное или короткое время ожидания видимости, чтобы предоставить коду больше или меньше времени на полную обработку каждого сообщения.
В следующем примере кода метод ReceiveMessages
используется для получения 20 сообщений в одном вызове. Затем он обрабатывает каждое сообщение с помощью цикла foreach
. Он также задает время ожидания невидимости 5 минут для каждого сообщения. Обратите внимание на то, что пятиминутный период начинается для всех сообщений одновременно, поэтому по прошествии пяти минут с момента вызова ReceiveMessages
все сообщения, которые не были удалены, снова становятся видимыми.
//-----------------------------------------------------
// 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);
}
}
}
Получение длины очереди
Вы можете узнать приблизительное количество сообщений в очереди. Метод GetProperties
возвращает свойства очереди, включая число сообщений. Свойство ApproximateMessagesCount
содержит приблизительное количество сообщений в очереди. Это число не меньше фактического числа сообщений в очереди, но может быть больше.
//-----------------------------------------------------
// 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}");
}
}
Удаление очереди
Чтобы удалить очередь и все сообщения в ней, вызовите метод Delete
для объекта очереди.
//-------------------------------------------------
// 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}'");
}
Дальнейшие действия
Вы изучили основные сведения о хранилище очередей. Дополнительные сведения о более сложных задачах по использованию хранилища можно найти по следующим ссылкам.
- Дополнительные сведения о доступных API-интерфейсах см. в справочной документации по хранилищу очередей:
- Просмотрите дополнительные руководства, чтобы изучить дополнительные возможности хранения данных в Azure.
- Приступая к работе с хранилищем таблиц Azure с помощью .NET.
- Приступая к работе с хранилищем BLOB-объектов Azure с помощью .NET.
- Информацию о хранении реляционных данных см. в статье Подключение к базе данных SQL с помощью .NET (C#).
- Узнайте, как упростить код, предназначенный для работы со службой хранилища Azure, с помощью пакета SDK для веб-заданий Azure.
Связанные примеры кода с использованием устаревших пакетов SDK для .NET версии 11.x см. в статье Примеры кода с использованием .NET версии 11.x.