分享方式:


教學課程:在 .NET 中使用 Azure 佇列儲存體佇列

Azure 佇列儲存體可實作雲端式佇列,使分散式應用程式的元件之間可進行通訊。 每個佇列都會維護一份可由傳送端元件新增、且可由接收端元件處理的訊息清單。 透過佇列,您的應用程式將可立即進行調整以因應需求。 本文說明使用 Azure 佇列儲存體佇列的基本步驟。

在本教學課程中,您會了解如何:

  • 建立 Azure 儲存體帳戶
  • 建立 應用程式
  • 新增 Azure 用戶端程式庫
  • 新增非同步程式碼的支援
  • 建立佇列
  • 將訊息插入佇列中
  • 清除佇列中的訊息
  • 刪除空的佇列
  • 檢查命令列引數
  • 建置並執行應用程式

必要條件

建立 Azure 儲存體帳戶

首先,請建立 Azure 儲存體帳戶。 如需建立儲存體帳戶的逐步指南,請參閱建立儲存體帳戶。 這是您在必要條件中建立免費的 Azure 帳戶之後所執行的個別步驟。

建立 應用程式

建立名為 QueueApp 的 .NET Core 應用程式。 為了方便說明,此應用程式將可透過佇列傳送和接收訊息。

  1. 在主控台視窗中 (例如 CMD、PowerShell 或 Azure CLI),使用 dotnet new 命令建立名為 QueueApp 的新主控台應用程式。 此命令會建立簡單的 "hello world" C# 專案,內含名為 Program.cs 的單一來源檔案。

    dotnet new console -n QueueApp
    
  2. 切換至新建立的 QueueApp 資料夾,然後建置應用程式來確認一切正常。

    cd QueueApp
    
    dotnet build
    

    您應該會看到類似下面輸出的結果:

    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 用戶端程式庫

  1. 使用 dotnet add package 命令,將 Azure 儲存體用戶端程式庫新增至專案。

    從主控台視窗中的專案資料夾執行下列命令。

    dotnet add package Azure.Storage.Queues
    

新增 using 陳述式

  1. 從專案目錄中的命令列輸入 code .,以在目前的目錄中開啟 Visual Studio Code。 將命令列視窗保持開啟。 稍後將會執行更多命令。 如果系統提示您新增建置和偵錯所需的 C# 資產,請按一下 [是] 按鈕。

  2. 開啟 Program.cs 來源檔案,並緊接在 using System; 陳述式後面新增下列命名空間。 此應用程式會使用這些命名空間中的類型連線至 Azure 儲存體,並使用佇列。

    using System.Threading.Tasks;
    using Azure.Storage.Queues;
    using Azure.Storage.Queues.Models;
    
  3. 儲存Program.cs檔案。

新增非同步程式碼的支援

由於應用程式使用雲端資源,因此程式碼會以非同步方式執行。

  1. 更新 Main 方法,以非同步方式執行。 將 void 取代為 async Task 傳回值。

    static async Task Main(string[] args)
    
  2. 儲存Program.cs檔案。

建立佇列

在對 Azure Api 進行任何呼叫之前,您必須先從 Azure 入口網站取得您的認證。

從 Azure 入口網站複製您的認證

當應用程式範例向 Azure 儲存體發出要求時,該要求必須獲得授權。 若要對要求授權,請以連接字串的形式將儲存體帳戶認證新增至應用程式。 若要檢視您的儲存體帳戶認證,請遵循下列步驟:

  1. 登入 Azure 入口網站

  2. 找出您的儲存體帳戶。

  3. 在 [儲存體帳戶] 功能表窗格的 [安全性 + 網路] 下方,選取 [存取金鑰]。 在此處,您可以檢視帳戶存取金鑰,和每個金鑰的完整連接字串。

    Screenshot that shows where the access key settings are in the Azure portal

  4. 在 [存取金鑰] 窗格中,選取 [顯示金鑰]

  5. 在 [金鑰 1] 區段中,找出連接字串值。 選取 [複製到剪貼簿] 圖示以複製連接字串。 在下一小節中,您會將該連接字串值新增至環境變數。

    Screenshot showing how to copy a connection string from the Azure portal

設定儲存體連接字串

在複製連接字串後,請在執行應用程式的本機電腦上,將該字串寫入至新的環境變數中。 若要設定環境變數,請開啟主控台視窗,並遵循您的作業系統所適用的指示。 將 <yourconnectionstring> 用實際的連接字串取代。

setx AZURE_STORAGE_CONNECTION_STRING "<yourconnectionstring>"

在 Windows 中新增環境變數之後,您必須啟動新的命令視窗執行個體。

重新啟動程式

新增環境變數之後,請重新啟動任何需要讀取環境變數的執行中程式。 例如,請先重新啟動您的開發環境或編輯器,然後再繼續。

將連接字串新增至應用程式

將連接字串新增至應用程式,使其能夠存取儲存體帳戶。

  1. 切換回 Visual Studio Code。

  2. Main 方法中,將 Console.WriteLine("Hello, World"); 程式碼取代為下列行,以從環境變數取得連接字串。

    string connectionString = Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING");
    
  3. 將下列程式碼新增至 Main 以建立佇列物件,此物件稍後會傳入 send 和 receive 方法中。

    QueueClient queue = new QueueClient(connectionString, "mystoragequeue");
    
  4. 儲存檔案。

將訊息插入佇列中

建立將訊息傳送至佇列中的新方法。

  1. 將下列 InsertMessageAsync 方法新增至您的 Program 類別。

    已傳遞佇列參考給這個方法。 藉由呼叫 CreateIfNotExistsAsync,建立新的佇列 (如果尚未存在)。 然後該佇列會呼叫 SendMessageAsync,將 newMessage 新增至佇列。

    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 天。 您可以指定任何正數的訊息存留時間。 下列程式碼片段會新增「永不」過期的訊息。

    若要新增不會過期的訊息,請在 SendMessageAsync 的呼叫中使用 Timespan.FromSeconds(-1)

    await theQueue.SendMessageAsync(newMessage, default, TimeSpan.FromSeconds(-1), default);
    
  3. 儲存檔案。

佇列訊息的格式必須與使用 UTF-8 編碼的 XML 要求相容。 一則訊息的大小可能高達 64 KB。 如果訊息包含二進位資料,則將訊息編碼為 Base64

清除佇列中的訊息

建立新方法已從佇列中擷取訊息。 在成功接收訊息後,務必要從佇列中刪除該訊息,以免受到多次處理。

  1. 將稱為 RetrieveNextMessageAsync 的新方法新增至您的 Program 類別。

    此方法會藉由呼叫 ReceiveMessagesAsync,在第一個參數中傳遞 1 僅擷取佇列中的下一則訊息,以接收佇列中的訊息。 收到訊息後,請呼叫 DeleteMessageAsync 以從佇列中刪除該訊息。

    當使用 v12 之前的 SDK 版本將訊息傳送至佇列時,會自動以 Base64 編碼。 從 v12 開始,已移除該功能。 使用 v12 SDK 來擷取訊息時,不會自動進行 Base64 解碼。 您必須自行明確地對內容進行 Base64 解碼

    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].Body.ToString();
                await theQueue.DeleteMessageAsync(retrievedMessage[0].MessageId, retrievedMessage[0].PopReceipt);
                return theMessage;
            }
    
            return null;
        }
    
        return null;
    }
    
  2. 儲存檔案。

刪除空的佇列

在專案結束後確認您是否還需要您建立的資源,是最佳做法。 資源若繼續執行,將需付費。 如果佇列存在,但是空的,請詢問使用者是否要加以刪除。

  1. 展開 RetrieveNextMessageAsync 方法,以納入刪除空佇列的提示。

    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].Body.ToString();
                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. 儲存檔案。

檢查命令列引數

如果在應用程式中傳入了任何命令列引數,請假設它們是要新增至佇列的訊息。 引數聯結在一起,組成字串。 藉由呼叫我們先前新增的 InsertMessageAsync 方法,將此字串新增至訊息佇列。

如果沒有任何命令列引數,請嘗試擷取作業。 呼叫 RetrieveNextMessageAsync 方以擷取佇列中的下一則訊息。

最後,等到使用者輸入後,再呼叫 Console.ReadLine 結束。

  1. 展開 Main 方法以檢查命令列引數,並等候使用者輸入。

    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. 儲存檔案。

完整程式碼

以下列出此專案的完整程式碼。

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].Body.ToString();
                    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.";
            }
        }
    }
}

建置並執行應用程式

  1. 從專案目錄中的命令列執行下列 dotnet 命令,以建置專案。

    dotnet build
    
  2. 專案成功建置後,請執行下列命令,將第一個訊息新增至佇列。

    dotnet run First queue message
    

    您應該會看見下列輸出:

    C:\Tutorials\QueueApp>dotnet run First queue message
    The queue was created.
    Sent: First queue message
    Press Enter..._
    
  3. 執行未使用命令列引數的應用程式,以接收和移除佇列中的第一個訊息。

    dotnet run
    
  4. 繼續執行應用程式,直到所有訊息皆移除。 如果您再執行一次,應該會出現佇列空白的訊息,以及刪除佇列的提示。

    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>_
    

下一步

在本教學課程中,您已了解如何:

  1. 建立佇列
  2. 從佇列新增和移除訊息
  3. 刪除 Azure 佇列儲存體佇列

如需詳細資訊,請參閱 Azure 佇列儲存體快速入門。

如需使用已淘汰 .NET 11.x 版 SDK 的相關程式碼範例,請參閱使用 .NET 11.x 版的程式碼範例