教程:使用 Azure 存储队列Tutorial: Work with Azure storage queues

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
  • 支持异步代码的支持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:

    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.62 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\netcoreapp2.1\QueueApp.dll
    
    Build succeeded.
        0 Warning(s)
        0 Error(s)
    
    Time Elapsed 00:00:02.40
    
    C:\Tutorials\QueueApp>_
    

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

由于该应用使用云资源,因此代码将以异步方式运行。Since the app uses cloud resources, the code runs asynchronously. 但是,在 C# 7.1 推出之前,C# 中的 asyncawaitMain 方法中不是有效的关键字。However, C#'s async and await weren't valid keywords in Main methods until C# 7.1. 可以通过 csproj 文件中的一个标志轻松切换到该编译器。You can easily switch to that compiler through a flag in the csproj file.

  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. 在编辑器中打开 QueueApp.csproj 文件。Open the QueueApp.csproj file in the editor.

  3. <LangVersion>7.1</LangVersion> 添加到生成文件中的第一个 PropertyGroupAdd <LangVersion>7.1</LangVersion> into the first PropertyGroup in the build file. 请确保只添加 LangVersion 标记,因为你的 TargetFramework 可能有所不同,具体取决于安装的 .NET 版本。Make sure that you only add the LangVersion tag as your TargetFramework may be different depending on which version of .NET you have installed.

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp2.1</TargetFramework>
        <LangVersion>7.1</LangVersion>
      </PropertyGroup>
    
    ...
    
    
  4. 保存 QueueApp.csproj 文件。Save the QueueApp.csproj file.

  5. 打开 Program.cs 源文件,并将 Main 方法更新为以异步方式运行。Open the Program.cs source file and update the Main method to run asynchronously. void 替换为异步任务返回值。Replace void with an async Task return value.

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

创建队列Create a queue

  1. 使用 dotnet add package 命令将 Microsoft.Azure.Storage.Common 和 Microsoft.Azure.Storage.Queue 包安装到项目 。Install the Microsoft.Azure.Storage.Common and Microsoft.Azure.Storage.Queue packages to the project with the dotnet add package command. 在控制台窗口中从项目文件夹执行以下 dotnet 命令。Execute the following dotnet commands from the project folder in the console window.

    dotnet add package Microsoft.Azure.Storage.Common
    dotnet add package Microsoft.Azure.Storage.Queue
    
  2. Program.cs 文件的顶部,紧接在 using System; 语句的后面添加以下命名空间。At the top of the Program.cs file, 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 Microsoft.Azure.Storage;
    using Microsoft.Azure.Storage.Queue;
    
  3. 保存 Program.cs 文件。Save the Program.cs file.

获取连接字符串Get your connection string

客户端库使用连接字符串来建立连接。The client library uses a connection string to establish your connection. Azure 门户中存储帐户的“设置”部分提供了该连接字符串。 Your connection string is available in the Settings section of your storage account in the Azure portal.

  1. 在 Web 浏览器中登录到 Azure 门户In your web browser, sign in to the Azure portal.

  2. 导航到 Azure 门户中的存储帐户。Navigate to your storage account in the Azure portal.

  3. 选择“访问密钥”。 Select Access keys.

  4. 单击“连接字符串”字段右侧的“复制”按钮。 Click the Copy button to the right of the Connection string field.

连接字符串

连接字符串是按以下格式:The connection string is in this format:

"DefaultEndpointsProtocol=https;AccountName=<your storage account name>;AccountKey=<your key>;EndpointSuffix=core.chinacloudapi.cn"

将连接字符串添加到应用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. Program 类中,添加一个 private const string connectionString = 成员用于保存连接字符串。In the Program class, add a private const string connectionString = member to hold the connection string.

  3. 在等号的后面,粘贴先前在 Azure 门户中复制的字符串值。After the equal sign, paste the string value that you copied earlier in your Azure portal. connectionString 值是与你的帐户相关的唯一值。The connectionString value will be unique to your account.

  4. Main 中删除“Hello World”代码。Remove the "Hello World" code from Main. 代码应如下所示,但使用了唯一的连接字符串值。Your code should look similar to the following but with your unique connection string value.

    namespace QueueApp
    {
        class Program
        {
            private const string connectionString = "DefaultEndpointsProtocol=https; ...";
    
            static async Task Main(string[] args)
            {
            }
        }
    }
    
  5. 更新 Main 以创建 CloudQueue 对象,稍后要将它传入到 send 和 receive 方法。Update Main to create a CloudQueue object, which is later passed into the send and receive methods.

         static async Task Main(string[] args)
         {
             CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
             CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
             CloudQueue queue = queueClient.GetQueueReference("mystoragequeue");
         }
    
  6. 保存文件。Save the file.

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

创建一个新方法用于将消息发送到队列。Create a new method to send a message into the queue. 将以下方法添加到 Program 类。Add the following method to your Program class. 此方法获取队列引用,然后通过调用 CreateIfNotExistsAsync 创建一个新队列(如果尚不存在)。This method gets a queue reference, then creates a new queue if it doesn't already exist by calling CreateIfNotExistsAsync. 然后,它通过调用 AddMessageAsync 将消息添加到该队列。Then, it adds the message to the queue by calling AddMessageAsync.

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

    static async Task SendMessageAsync(CloudQueue theQueue, string newMessage)
    {
        bool createdQueue = await theQueue.CreateIfNotExistsAsync();
    
        if (createdQueue)
        {
            Console.WriteLine("The queue was created.");
        }
    
        CloudQueueMessage message = new CloudQueueMessage(newMessage);
        await theQueue.AddMessageAsync(message);
    }
    
  2. 保存文件。Save the file.

消息必须采用可包含在 XML 请求中的 UTF-8 编码格式,大小不能超过 64 KB。A message must be in a format that can be included in an XML request with UTF-8 encoding, and may be up to 64 KB in size. 如果消息包含二进制数据,则我们建议对消息进行 Base64 编码。If a message contains binary data, we recommend that you Base64-encode the message.

消息的最大生存时间默认设置为 7 天。By default, the maximum time-to-live for a message is set to 7 days. 可以为消息生存时间指定任何正数。You can specify any positive number for the message time-to-live. 若要添加未过期的消息,请在对 AddMessageAsync 的调用中使用 Timespan.FromSeconds(-1)To add a message that does not expire, use Timespan.FromSeconds(-1) in your call to AddMessageAsync.

await theQueue.AddMessageAsync(message, TimeSpan.FromSeconds(-1), null, null, null);

取消消息的排队Dequeue messages

创建名为 ReceiveMessageAsync 的新方法。Create a new method called ReceiveMessageAsync. 此方法通过调用 GetMessageAsync 从队列接收消息。This method receives a message from the queue by calling GetMessageAsync. 成功收到消息后,必须从队列中删除该消息,以免再次处理该消息。Once the message is successfully received, it's important to delete it from the queue so it isn't processed more than once. 收到消息后,请调用 DeleteMessageAsync 从队列中删除该消息。After the message is received, delete it from the queue by calling DeleteMessageAsync.

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

    static async Task<string> ReceiveMessageAsync(CloudQueue theQueue)
    {
        bool exists = await theQueue.ExistsAsync();
    
        if (exists)
        {
            CloudQueueMessage retrievedMessage = await theQueue.GetMessageAsync();
    
            if (retrievedMessage != null)
            {
                string theMessage = retrievedMessage.AsString;
                await theQueue.DeleteMessageAsync(retrievedMessage);
                return theMessage;
            }
        }
    }
    
  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. 扩展 ReceiveMessageAsync 方法以包含有关是否删除空队列的提示。Expand the ReceiveMessageAsync method to include a prompt to delete the empty queue.

    static async Task<string> ReceiveMessageAsync(CloudQueue theQueue)
    {
        bool exists = await theQueue.ExistsAsync();
    
        if (exists)
        {
            CloudQueueMessage retrievedMessage = await theQueue.GetMessageAsync();
    
            if (retrievedMessage != null)
            {
                string theMessage = retrievedMessage.AsString;
                await theQueue.DeleteMessageAsync(retrievedMessage);
                return theMessage;
            }
            else
            {
                Console.Write("The queue is empty. Attempt to delete it? (Y/N) ");
                string response = Console.ReadLine();
    
                if (response == "Y" || response == "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. 调用前面添加的 SendMessageAsync 方法,将此字符串添加到消息队列。Add this string to the message queue by calling the SendMessageAsync method we added earlier.

如果没有任何命令行参数,请执行检索操作。If there are no command-line arguments, execute a retrieve operation. 调用 ReceiveMessageAsync 方法检索队列中的第一个消息。Call the ReceiveMessageAsync method to retrieve the first 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)
         {
             CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
             CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
             CloudQueue queue = queueClient.GetQueueReference("mystoragequeue");
    
             if (args.Length > 0)
             {
                 string value = String.Join(" ", args);
                 await SendMessageAsync(queue, value);
                 Console.WriteLine($"Sent: {value}");
             }
             else
             {
                 string value = await ReceiveMessageAsync(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 Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Queue;

namespace QueueApp
{
 class Program
 {
     // The string value is broken up for better onscreen formatting
     private const string connectionString = "DefaultEndpointsProtocol=https;" +
                                             "AccountName=<your storage account name>;" +
                                             "AccountKey=<your key>;" +
                                             "EndpointSuffix=core.chinacloudapi.cn";

     static async Task Main(string[] args)
     {
         CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
         CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
         CloudQueue queue = queueClient.GetQueueReference("mystoragequeue");

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

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

     static async Task SendMessageAsync(CloudQueue theQueue, string newMessage)
     {
         bool createdQueue = await theQueue.CreateIfNotExistsAsync();

         if (createdQueue)
         {
             Console.WriteLine("The queue was created.");
         }

         CloudQueueMessage message = new CloudQueueMessage(newMessage);
         await theQueue.AddMessageAsync(message);
     }

     static async Task<string> ReceiveMessageAsync(CloudQueue theQueue)
     {
         bool exists = await theQueue.ExistsAsync();

         if (exists)
         {
             CloudQueueMessage retrievedMessage = await theQueue.GetMessageAsync();

             if (retrievedMessage != null)
             {
                 string theMessage = retrievedMessage.AsString;
                 await theQueue.DeleteMessageAsync(retrievedMessage);
                 return theMessage;
             }
             else
             {
                 Console.Write("The queue is empty. Attempt to delete it? (Y/N) ");
                 string response = Console.ReadLine();

                 if (response == "Y" || response == "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..._
  1. 不结合任何命令行参数运行该应用可以接收和删除队列中的第一个消息。Run the app with no command-line arguments to receive and remove the first message in the queue.

    dotnet run
    
  2. 继续运行应用,直到已删除所有消息。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 quickstart for more information.