教程:在 .NET 中使用 Azure 存储队列Tutorial: Work with Azure storage queues in .NET

Azure 队列存储实现基于云的队列以在分布式应用程序的组件之间实现通信。Azure Queue storage implements cloud-based queues to enable communication between components of a distributed application. 每个队列维护一个可由发送方组件添加的、由接收方组件处理的消息列表。Each queue maintains a list of messages that can be added by a sender component and processed by a receiver component. 使用队列时,应用程序可根据需求立即缩放。With a queue, your application can scale immediately to meet demand. 本文介绍有关使用 Azure 存储队列的基本步骤。This article shows the basic steps for working with an Azure storage queue.

本教程介绍如何执行下列操作:In this tutorial, you learn how to:

  • 创建 Azure 存储帐户Create an Azure storage account
  • 创建应用程序Create the app
  • 添加 Azure 客户端库Add the Azure client libraries
  • 支持异步代码的支持Add support for asynchronous code
  • 创建队列Create a queue
  • 将消息插入队列Insert messages into a queue
  • 取消消息的排队Dequeue messages
  • 删除空队列Delete an empty queue
  • 检查命令行参数Check for command-line arguments
  • 生成并运行应用Build and run the app

先决条件Prerequisites

创建 Azure 存储帐户Create an Azure storage account

首先创建 Azure 存储帐户。First, create an Azure storage account. 有关创建存储帐户的分步指南,请参阅创建存储帐户快速入门。For a step-by-step guide to creating a storage account, see the Create a storage account quickstart.

创建应用程序Create the app

创建名为 QueueApp 的 .NET Core 应用程序。Create a .NET Core application named QueueApp. 为方便起见,此应用将通过队列发送和接收消息。For simplicity, this app will both send and receive messages through the queue.

  1. 在控制台窗口(例如 CMD、PowerShell 或 Azure CLI)中,使用 dotnet new 命令创建名为 QueueApp 的新控制台应用。In a console window (such as CMD, PowerShell, or Azure CLI), use the dotnet new command to create a new console app with the name QueueApp. 此命令将创建包含单个源文件的简单“Hello World”C# 项目:Program.csThis command creates a simple "Hello World" C# project with a single source file: Program.cs.

    dotnet new console -n QueueApp
    
  2. 切换到新建的 QueueApp 文件夹,并生成应用以验证一切是否正常。Switch to the newly created QueueApp folder and build the app to verify that all is well.

    cd QueueApp
    
    dotnet build
    

    应看到结果类似于以下输出:You should see results similar to the following output:

    C:\Tutorials>dotnet new console -n QueueApp
    The template "Console Application" was created successfully.
    
    Processing post-creation actions...
    Running 'dotnet restore' on QueueApp\QueueApp.csproj...
      Restore completed in 155.63 ms for C:\Tutorials\QueueApp\QueueApp.csproj.
    
    Restore succeeded.
    
    C:\Tutorials>cd QueueApp
    
    C:\Tutorials\QueueApp>dotnet build
    Microsoft (R) Build Engine version 16.0.450+ga8dc7f1d34 for .NET Core
    Copyright (C) Microsoft Corporation. All rights reserved.
    
      Restore completed in 40.87 ms for C:\Tutorials\QueueApp\QueueApp.csproj.
      QueueApp -> C:\Tutorials\QueueApp\bin\Debug\netcoreapp3.1\QueueApp.dll
    
    Build succeeded.
        0 Warning(s)
        0 Error(s)
    
    Time Elapsed 00:00:02.40
    
    C:\Tutorials\QueueApp>_
    

添加 Azure 客户端库Add the Azure client libraries

  1. 使用 dotnet add package 命令将 Azure 存储客户端库添加到项目。Add the Azure Storage client libraries to the project by using the dotnet add package command.

    在控制台窗口中从项目文件夹执行以下命令。Execute the following command from the project folder in the console window.

    dotnet add package Azure.Storage.Queues
    

添加 using 语句Add using statements

  1. 在项目目录中的命令行下,键入 code . 以在当前目录中打开 Visual Studio Code。From the command line in the project directory, type code . to open Visual Studio Code in the current directory. 请将命令行窗口保持打开状态。Keep the command-line window open. 稍后需要执行更多的命令。There will be more commands to execute later. 如果系统提示是否要添加用于生成和调试的 C# 资产,请单击“是”按钮。If you're prompted to add C# assets required to build and debug, click the Yes button.

  2. 打开 Program.cs 源文件,紧接在 using System; 语句的后面添加以下命名空间。Open the Program.cs source file and add the following namespaces right after the using System; statement. 此应用将使用这些命名空间中的类型来连接 Azure 存储和使用队列。This app uses types from these namespaces to connect to Azure Storage and work with queues.

    using System.Threading.Tasks;
    using Azure.Storage.Queues;
    using Azure.Storage.Queues.Models;
    
  3. 保存 Program.cs 文件。Save the Program.cs file.

支持异步代码的支持Add support for asynchronous code

由于该应用使用云资源,因此代码将以异步方式运行。Since the app uses cloud resources, the code runs asynchronously.

  1. 更新 Main 方法以异步运行。Update the Main method to run asynchronously. void 替换为异步任务返回值。Replace void with an async Task return value.

    static async Task Main(string[] args)
    
  2. 保存 Program.cs 文件。Save the Program.cs file.

创建队列Create a queue

在对 Azure API 进行任何调用之前,必须从 Azure 门户获取凭据。Before making any calls into Azure APIs, you must get your credentials from the Azure portal.

从 Azure 门户复制凭据Copy your credentials from the Azure portal

当示例应用程序向 Azure 存储发出请求时,必须对其进行授权。When the sample application makes a request to Azure Storage, it must be authorized. 若要对请求进行授权,请将存储帐户凭据以连接字符串形式添加到应用程序中。To authorize a request, add your storage account credentials to the application as a connection string. 按照以下步骤查看存储帐户凭据:View your storage account credentials by following these steps:

  1. 登录 Azure 门户Sign in to the Azure portal.

  2. 找到自己的存储帐户。Locate your storage account.

  3. 在存储帐户概述的“设置”部分,选择“访问密钥”。 In the Settings section of the storage account overview, select Access keys. 在这里,可以查看你的帐户访问密钥以及每个密钥的完整连接字符串。Here, you can view your account access keys and the complete connection string for each key.

  4. 找到“密钥 1”下面的“连接字符串”值,选择“复制”按钮复制该连接字符串。 Find the Connection string value under key1, and select the Copy button to copy the connection string. 下一步需将此连接字符串值添加到某个环境变量。You will add the connection string value to an environment variable in the next step.

    显示如何从 Azure 门户复制连接字符串的屏幕截图

配置存储连接字符串Configure your storage connection string

复制连接字符串以后,请将其写入运行应用程序的本地计算机的新环境变量中。After you have copied your connection string, write it to a new environment variable on the local machine running the application. 若要设置环境变量,请打开控制台窗口,并遵照适用于操作系统的说明。To set the environment variable, open a console window, and follow the instructions for your operating system. <yourconnectionstring> 替换为实际的连接字符串。Replace <yourconnectionstring> with your actual connection string.

WindowsWindows

setx AZURE_STORAGE_CONNECTION_STRING "<yourconnectionstring>"

在 Windows 中添加环境变量后,必须启动命令窗口的新实例。After you add the environment variable in Windows, you must start a new instance of the command window.

LinuxLinux

export AZURE_STORAGE_CONNECTION_STRING="<yourconnectionstring>"

macOSmacOS

export AZURE_STORAGE_CONNECTION_STRING="<yourconnectionstring>"

重新启动程序Restart programs

添加环境变量后,重启需要读取环境变量的任何正在运行的程序。After you add the environment variable, restart any running programs that will need to read the environment variable. 例如,重启开发环境或编辑器,然后再继续。For example, restart your development environment or editor before continuing.

将连接字符串添加到应用Add the connection string to the app

将连接字符串添加到应用中,使应用可以访问存储帐户。Add the connection string into the app so it can access the storage account.

  1. 切回到 Visual Studio Code。Switch back to Visual Studio Code.

  2. 在 Main 方法中,将 Console.WriteLine("Hello World!"); 代码替换为以下行,该行从环境变量中获取连接字符串。In the Main method, replace the Console.WriteLine("Hello World!"); code with the following line that gets the connection string from the environment variable.

    string connectionString = Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING");
    
  3. 将以下代码添加到 Main 以创建 queue 对象,稍后要将它传入到 send 和 receive 方法。Add the following code to Main to create a queue object, which is later passed into the send and receive methods.

    QueueClient queue = new QueueClient(connectionString, "mystoragequeue");
    
  4. 保存文件。Save the file.

将消息插入队列Insert messages into the queue

创建一个新方法用于将消息发送到队列。Create a new method to send a message into the queue.

  1. 将以下 InsertMessageAsync 方法添加到 Program 类 。Add the following InsertMessageAsync method to your Program class.

    向此方法传递一个队列引用。This method is passed a queue reference. 通过调用 CreateIfNotExistsAsync 创建新队列(如果尚不存在)。A new queue is created, if it doesn't already exist, by calling CreateIfNotExistsAsync. 然后,它通过调用 SendMessageAsync,将 newMessage 添加到队列中。Then, it adds the newMessage to the queue by calling SendMessageAsync.

    static async Task InsertMessageAsync(QueueClient theQueue, string newMessage)
     {
        if (null != await theQueue.CreateIfNotExistsAsync())
        {
            Console.WriteLine("The queue was created.");
        }
    
        await theQueue.SendMessageAsync(newMessage);
     }
    
  2. (可选)默认情况下,消息的最大生存时间默认设置为 7 天。Optional By default, the maximum time-to-live for a message is set to seven days. 可以为消息生存时间指定任何正数。You can specify any positive number for the message time-to-live. 下面的代码片段添加一个永不过期的消息。The following code snippet adds a message that never expires.

    若要添加未过期的消息,请在对 SendMessageAsync 的调用中使用 Timespan.FromSeconds(-1)To add a message that doesn't expire, use Timespan.FromSeconds(-1) in your call to SendMessageAsync.

    await theQueue.SendMessageAsync(newMessage, default, TimeSpan.FromSeconds(-1), default);
    
  3. 保存文件。Save the file.

队列消息必须采用与使用 UTF-8 编码的 XML 请求兼容的格式。A queue message must be in a format compatible with an XML request using UTF-8 encoding. 消息的大小最大可为 64 KB。A message may be up to 64 KB in size. 如果消息包含二进制数据,则对消息进行 Base64 编码If a message contains binary data, Base64-encode the message.

取消消息的排队Dequeue messages

创建一个新方法,用于从队列检索消息。Create a new method to retrieve a message from the queue. 成功收到消息后,必须从队列中删除该消息,以免再次处理该消息。Once the message is successfully received, it's important to delete it from the queue so it isn't processed more than once.

  1. 将名为 RetrieveNextMessageAsync 的新方法添加到 Program 类中 。Add a new method called RetrieveNextMessageAsync to your Program class.

    此方法通过调用 ReceiveMessagesAsync 接收来自队列的消息,在第一个参数中传递 1,仅检索队列中的下一条消息。This method receives a message from the queue by calling ReceiveMessagesAsync, passing 1 in the first parameter to retrieve only the next message in the queue. 收到消息后,请调用 DeleteMessageAsync 从队列中删除该消息。After the message is received, delete it from the queue by calling DeleteMessageAsync.

    static async Task<string> RetrieveNextMessageAsync(QueueClient theQueue)
    {
        if (await theQueue.ExistsAsync())
        {
            QueueProperties properties = await theQueue.GetPropertiesAsync();
    
            if (properties.ApproximateMessagesCount > 0)
            {
                QueueMessage[] retrievedMessage = await theQueue.ReceiveMessagesAsync(1);
                string theMessage = retrievedMessage[0].MessageText;
                await theQueue.DeleteMessageAsync(retrievedMessage[0].MessageId, retrievedMessage[0].PopReceipt);
                return theMessage;
            }
    
            return null;
        }
    
        return null;
    }
    
  2. 保存文件。Save the file.

删除空队列Delete an empty queue

在项目结束时,最好是确定是否仍然需要所创建的资源。It's a best practice at the end of a project to identify whether you still need the resources you created. 持续运行资源可能会产生费用。Resources left running can cost you money. 如果存在空队列,请询问用户是否要删除该队列。If the queue exists but is empty, ask the user if they would like to delete it.

  1. 扩展 RetrieveNextMessageAsync 方法以包含有关是否删除空队列的提示。Expand the RetrieveNextMessageAsync method to include a prompt to delete the empty queue.

       static async Task<string> RetrieveNextMessageAsync(QueueClient theQueue)
    {
        if (await theQueue.ExistsAsync())
        {
            QueueProperties properties = await theQueue.GetPropertiesAsync();
    
            if (properties.ApproximateMessagesCount > 0)
            {
                QueueMessage[] retrievedMessage = await theQueue.ReceiveMessagesAsync(1);
                string theMessage = retrievedMessage[0].MessageText;
                await theQueue.DeleteMessageAsync(retrievedMessage[0].MessageId, retrievedMessage[0].PopReceipt);
                return theMessage;
            }
            else
            {
                Console.Write("The queue is empty. Attempt to delete it? (Y/N) ");
                string response = Console.ReadLine();
    
                if (response.ToUpper() == "Y")
                {
                    await theQueue.DeleteIfExistsAsync();
                    return "The queue was deleted.";
                }
                else
                {
                    return "The queue was not deleted.";
                }
            }
        }
        else
        {
            return "The queue does not exist. Add a message to the command line to create the queue and store the message.";
        }
    }
    
  2. 保存文件。Save the file.

检查命令行参数Check for command-line arguments

如果在应用中传入了任何命令行参数,系统会假设这些参数是要添加到队列的消息。If there are any command-line arguments passed into the app, assume they're a message to be added to the queue. 将参数联接到一起以构成一个字符串。Join the arguments together to make a string. 调用前面添加的 InsertMessageAsync 方法,将此字符串添加到消息队列。Add this string to the message queue by calling the InsertMessageAsync method we added earlier.

如果没有任何命令行参数,请尝试检索操作。If there are no command-line arguments, attempt a retrieve operation. 调用 RetrieveNextMessageAsync 方法检索队列中的下一条消息。Call the RetrieveNextMessageAsync method to retrieve the next message in the queue.

最后,等待用户输入,然后调用 Console.ReadLine 退出。Finally, wait for user input before exiting by calling Console.ReadLine.

  1. 扩展 Main 方法以检查命令行参数并等待用户输入。Expand the Main method to check for command-line arguments and wait for user input.

    static async Task Main(string[] args)
    {
        string connectionString = Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING");
    
        QueueClient queue = new QueueClient(connectionString, "mystoragequeue");
    
        if (args.Length > 0)
        {
            string value = String.Join(" ", args);
            await InsertMessageAsync(queue, value);
            Console.WriteLine($"Sent: {value}");
        }
        else
        {
         string value = await RetrieveNextMessageAsync(queue);
         Console.WriteLine($"Received: {value}");
        }
    
        Console.Write("Press Enter...");
        Console.ReadLine();
    }
    
  2. 保存文件。Save the file.

完整代码Complete code

下面是此项目的完整代码列表。Here is the complete code listing for this project.

using System;
using System.Threading.Tasks;
using Azure.Storage.Queues;
using Azure.Storage.Queues.Models;

namespace QueueApp
{
    class Program
    {
        static async Task Main(string[] args)
        {
            string connectionString = Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING");

            QueueClient queue = new QueueClient(connectionString, "mystoragequeue");

            if (args.Length > 0)
            {
                string value = String.Join(" ", args);
                await InsertMessageAsync(queue, value);
                Console.WriteLine($"Sent: {value}");
            }
            else
            {
                string value = await RetrieveNextMessageAsync(queue);
                Console.WriteLine($"Received: {value}");
            }

            Console.Write("Press Enter...");
            Console.ReadLine();
        }

        static async Task InsertMessageAsync(QueueClient theQueue, string newMessage)
        {
            if (null != await theQueue.CreateIfNotExistsAsync())
            {
                Console.WriteLine("The queue was created.");
            }

            await theQueue.SendMessageAsync(newMessage);
        }

        static async Task<string> RetrieveNextMessageAsync(QueueClient theQueue)
        {
            if (await theQueue.ExistsAsync())
            {
                QueueProperties properties = await theQueue.GetPropertiesAsync();

                if (properties.ApproximateMessagesCount > 0)
                {
                    QueueMessage[] retrievedMessage = await theQueue.ReceiveMessagesAsync(1);
                    string theMessage = retrievedMessage[0].MessageText;
                    await theQueue.DeleteMessageAsync(retrievedMessage[0].MessageId, retrievedMessage[0].PopReceipt);
                    return theMessage;
                }
                else
                {
                    Console.Write("The queue is empty. Attempt to delete it? (Y/N) ");
                    string response = Console.ReadLine();

                    if (response.ToUpper() == "Y")
                    {
                        await theQueue.DeleteIfExistsAsync();
                        return "The queue was deleted.";
                    }
                    else
                    {
                        return "The queue was not deleted.";
                    }
                }
            }
            else
            {
                return "The queue does not exist. Add a message to the command line to create the queue and store the message.";
            }
        }
    }
}

生成并运行应用Build and run the app

  1. 从项目目录中的命令行运行以下 dotnet 命令以生成项目。From the command line in the project directory, run the following dotnet command to build the project.

    dotnet build
    
  2. 项目成功生成后,运行以下命令将第一个消息添加到队列。After the project builds successfully, run the following command to add the first message to the queue.

    dotnet run First queue message
    

    你应该会看到以下输出:You should see this output:

    C:\Tutorials\QueueApp>dotnet run First queue message
    The queue was created.
    Sent: First queue message
    Press Enter..._
    
  3. 不结合任何命令行参数运行该应用可以接收和删除队列中的第一个消息。Run the app with no command-line arguments to receive and remove the first message in the queue.

    dotnet run
    
  4. 继续运行应用,直到已删除所有消息。Continue to run the app until all the messages are removed. 如果多次运行该应用,将会收到一条指出队列为空的消息,以及一条有关是否要删除该队列的提示。If you run it one more time, you'll get a message that the queue is empty and a prompt to delete the queue.

    C:\Tutorials\QueueApp>dotnet run First queue message
    The queue was created.
    Sent: First queue message
    Press Enter...
    
    C:\Tutorials\QueueApp>dotnet run Second queue message
    Sent: Second queue message
    Press Enter...
    
    C:\Tutorials\QueueApp>dotnet run Third queue message
    Sent: Third queue message
    Press Enter...
    
    C:\Tutorials\QueueApp>dotnet run
    Received: First queue message
    Press Enter...
    
    C:\Tutorials\QueueApp>dotnet run
    Received: Second queue message
    Press Enter...
    
    C:\Tutorials\QueueApp>dotnet run
    Received: Third queue message
    Press Enter...
    
    C:\Tutorials\QueueApp>dotnet run
    The queue is empty. Attempt to delete it? (Y/N) Y
    Received: The queue was deleted.
    Press Enter...
    
    C:\Tutorials\QueueApp>_
    

后续步骤Next steps

在本教程中,你已学习了如何执行以下操作:In this tutorial, you learned how to:

  1. 创建队列Create a queue
  2. 在队列中添加和删除消息Add and remove messages from a queue
  3. 删除 Azure 存储队列Delete an Azure storage queue

查看 Azure 队列快速入门了解详细信息。Check out the Azure queues quickstarts for more information.