.NET を使用して Azure Queue Storage の使用を開始する

概要

Azure Queue Storage を使用すると、アプリケーション コンポーネント間のクラウド メッセージングが提供されます。 スケールを考慮したアプリケーションを設計では、多くの場合、アプリケーション コンポーネントは分離されるため、個別にスケーリングすることができます。 Queue Storage を使用すれば、アプリケーション コンポーネントがクラウド、デスクトップ、オンプレミスのサーバー、またはモバイル デバイス上のいずれで実行されている場合でも、アプリケーション コンポーネント間に非同期メッセージングを提供できます。 また、非同期タスクの管理とプロセス ワークフローの構築も Queue Storage でサポートされています。

このチュートリアルについて

このチュートリアルでは、Azure Queue Storage を使用していくつかの一般的なシナリオの .NET コードを記述する方法を示します。 紹介するシナリオは、キューの作成と削除、およびキュー メッセージの追加、読み取り、削除です。

推定所要時間: 45 分

前提条件

Queue storage とは

Azure キュー ストレージは、HTTP または HTTPS を使用した認証された呼び出しを介して世界中のどこからでもアクセスできる大量のメッセージを格納するためのサービスです。 キューの 1 つのメッセージの最大サイズは 64 KB で、1 つのキューには、ストレージ アカウントの合計容量の上限に達するまで、数百万のメッセージを格納できます。 Queue storage は、多くの場合、非同期的な処理用に作業のバックログを作成するために使用されます。

Queue サービスの概念

Azure Queue サービスには、次のコンポーネントが含まれます。

Azure Queue サービス コンポーネント

  • ストレージ アカウント: Azure のストレージにアクセスする場合には必ず、ストレージ アカウントを使用します。 ストレージ アカウントの詳細については、「ストレージ アカウントの概要」を参照してください。

  • キュー: キューは、メッセージのセットを格納します。 すべてのメッセージはキューに 格納されている必要があります。 キュー名は小文字で入力する必要があります。 キューの名前付け規則については、「 Naming Queues and Metadata (キューとメタデータの名前付け規則)」を参照してください。

  • メッセージ: 形式を問わず、メッセージのサイズは最大で 64 KB です。 メッセージをキューで保持できる最長時間は 7 日間です。 バージョン 2017-07-29 以降では、最大有効期間を任意の正の数にすることができます。また、-1 は、メッセージが期限切れにならないことを示します。 このパラメーターを省略すると、既定の有効期間は 7 日になります。

  • URL 形式: キューは次の URL 形式を使って処理できます: http://<storage account>.queue.core.windows.net/<queue>

    次の URL を使用すると、図のいずれかのキューをアドレス指定できます。

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

Azure のストレージ アカウントの作成

最初の Azure ストレージ アカウントを作成する最も簡単な方法は、Azure Portal を利用することです。 詳細については、「 ストレージ アカウントの作成」を参照してください。

Azure Storage アカウントは、Azure PowerShellAzure CLI、または .NET 用 Azure ストレージ リソース プロバイダーを使用して作成することもできます。

現時点で Azure にストレージ アカウントを作成しない場合は、Azure ストレージ エミュレーターを使って、ローカル環境でコードの実行とテストを行うこともできます。 詳細については、ローカルでの Azure Storage の開発に Azurite エミュレーターを使用する方法に関するページを参照してください。

開発環境を設定する

次に、このガイドのコード例を試すことができるように、Visual Studio で開発環境を設定します。

Windows コンソール アプリケーション プロジェクトの作成

Visual Studio で、新しい Windows コンソール アプリケーションを作成します。 次の手順では、Visual Studio 2019 でコンソール アプリケーションを作成する方法を説明します。 この手順は Visual Studio の他のバージョンでも同様です。

  1. [ファイル]>[新規]>[プロジェクト] の順に選択します。
  2. [プラットフォーム]>[Windows] の順に選択します
  3. [コンソール アプリ (.NET Framework)] を選択します。
  4. [次へ] を選択します
  5. [プロジェクト名] フィールドに、アプリケーションの名前を入力します
  6. [作成]

このチュートリアルのすべてのコード例は、コンソール アプリケーションの Program.cs ファイルの Main() メソッドに追加できます。

Azure クラウド サービス、Web アプリ、デスクトップ アプリケーション、モバイル アプリケーションなど、どの種類の .NET アプリケーションでも Azure Storage クライアント ライブラリを使用できます。 このガイドでは、わかりやすくするためにコンソール アプリケーションを使用します。

NuGet を使用した必要なパッケージのインストール

このチュートリアルを完了するには、プロジェクトで以下の 4 つのパッケージを参照する必要があります。

NuGet を使用してこれらのパッケージを取得できます。 次の手順に従います。

  1. ソリューション エクスプローラーでプロジェクトを右クリックし、 [NuGet パッケージの管理] をクリックします。
  2. [参照] を選択します。
  3. Azure.Storage.Queues をオンラインで検索し、 [インストール] を選択して Azure Storage クライアント ライブラリとその依存関係をインストールします。 これにより、キュー ライブラリの依存関係である Azure.Storage.Common と Azure.Core libraries もインストールされます。
  4. System.Configuration.ConfigurationManager をオンラインで検索し、 [インストール] を選択して Configuration Manager をインストールします。

ターゲット環境の決定

このガイドの例を実行するための環境オプションとして次の 2 つがあります。

  • クラウド内の Azure ストレージ アカウントに対してコードを実行できます。
  • Azurite ストレージ エミュレーターに対してコードを実行できます。 Azurite は、クラウド内の Azure Storage アカウントをエミュレートするローカル環境です。 Azurite を使用すると、アプリケーションの開発中にコードのテストとデバッグを無料で実行できます。 エミュレーターでは既知のアカウントとキーを使用します。 詳細については、「ローカルでの Azure Storage の開発とテストに Azurite エミュレーターを使用する」を参照してください。

Note

ストレージ エミュレーターをターゲットにすると、Azure Storage に関連する利用料金の発生を回避できます。 ただし、クラウド内の Azure ストレージ アカウントをターゲットとしても、このチュートリアルを実行するための利用料金はごくわずかです。

ストレージ接続文字列の取得

.NET 用 Azure Storage クライアント ライブラリでは、ストレージ接続文字列を使用して、ストレージ サービスにアクセスするためのエンドポイントおよび資格情報を構成できます。 詳細については、「ストレージ アカウントのアクセス キーの管理」を参照してください。

Azure Portal で資格情報をコピーする

サンプル コードで、ストレージ アカウントへのアクセスを承認する必要があります。 承認するには、ストレージ アカウントの資格情報を接続文字列形式でアプリケーションに提供します。 ストレージ アカウントの資格情報を表示するには、次のように操作します。

  1. Azure Portal に移動します。

  2. 自分のストレージ アカウントを探します。

  3. ストレージ アカウントの概要の [設定] セクションで、 [アクセス キー] を選択します。 アカウント アクセス キーと、各キーの完全な接続文字列が表示されます。

  4. [Key1][接続文字列] の値を見つけて [コピー] ボタンをクリックし、接続文字列をコピーします。 すぐ後の手順で、接続文字列の値を環境変数に追加します。

    Azure portal から接続文字列をコピーする方法を示すスクリーンショット

接続文字列の詳細については、Azure Storage の接続文字列の構成に関するページを参照してください。

Note

ストレージ アカウント キーは、ストレージ アカウントの root パスワードに似ています。 ストレージ アカウント キーは常に慎重に保護してください。 このキーを他のユーザーに配布したり、ハードコーディングしたり、他のユーザーがアクセスできるプレーン テキスト ファイルに保存したりしないでください。 キーが侵害されたと思われる場合は、Azure Portal を使用してキーを再生成してください。

ストレージ接続文字列を管理するには、構成ファイルの中に保持することをお勧めします。 接続文字列を構成するには、Visual Studio のソリューション エクスプローラーから app.config ファイルを開きます。 ここに示す <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 ディレクティブを追加する

次の using ディレクティブを 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

Queue Storage クライアントを作成する

QueueClient クラスを使用すると、Queue Storage に格納されているキューを取得できます。 サービス クライアントを作成する方法の 1 つを次に示します。

//-------------------------------------------------
// 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 クラスを使用して送信するメッセージは、UTF-8 エンコードを使用して XML 要求に含めることができる形式である必要があります。 必要に応じて、MessageEncoding オプションを Base64 に設定して、準拠していないメッセージを処理できます。

これで、Queue Storage に対してデータの読み取りと書き込みを実行するコードを記述する準備が整いました。

キューを作成する

この例では、キューを作成する方法を示します。

//-------------------------------------------------
// 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 パラメーターの値を渡さない場合、既定では 1 つのメッセージがピークされます。

//-------------------------------------------------
// 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 秒延長します。 これにより、メッセージに関連付けられている作業の状態が保存され、クライアントにメッセージの操作を続行する時間が 1 分与えられます。 この方法を使用すると、キュー メッセージに対する複数の手順から成るワークフローを追跡でき、ハードウェアまたはソフトウェアの問題が原因で処理手順が失敗した場合に最初からやり直す必要がなくなります。 通常は、さらに再試行回数を保持し、メッセージの再試行回数が 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
            );
    }
}

次のメッセージをデキューする

キューからのメッセージのデキューは、2 つの手順で行います。 ReceiveMessagesを呼び出すと、キュー内の次のメッセージを取得します。 ReceiveMessages から返されたメッセージは、このキューからメッセージを読み取る他のコードから参照できなくなります。 既定では、このメッセージを参照できない状態は 30 秒間続きます。 また、キューからのメッセージの削除を完了するには、DeleteMessage を呼び出す必要があります。 このようにメッセージを 2 つの手順で削除することで、ハードウェアまたはソフトウェアの問題が原因でコードによるメッセージの処理が失敗した場合に、コードの別のインスタンスで同じメッセージを取得し、もう一度処理することができます。 ご自分のコードで、メッセージが処理された直後に 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 パターンを使用すると、呼び出しが完了するまでローカルでの実行が中断されます。 この動作により、現在のスレッドで別の作業を実行できるようになるため、パフォーマンスのボトルネックを回避し、アプリケーションの全体的な応答性を向上させることができます。 .NET での Async-Await パターンの使用方法の詳細については、 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}'");
}

メッセージをデキューするためのその他のオプションを使用する

キューからのメッセージの取得をカスタマイズする方法は 2 つあります。 1 つ目の方法では、(最大 32 個の) メッセージのバッチを取得できます。 2 つ目の方法では、コードで各メッセージを完全に処理できるように、非表示タイムアウトの設定を長くまたは短くすることができます。

次のコード例では、ReceiveMessages メソッドを使用して、1 回の呼び出しで 20 個のメッセージを取得します。 その後、foreach ループを使用して、各メッセージを処理します。 また、各メッセージの非表示タイムアウトを 5 分に設定します。 この 5 分間は、すべてのメッセージに対して同時に開始されます。そのため、ReceiveMessages の呼び出しから 5 分が経過すると、削除されていないすべてのメッセージが再び表示されます。

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

次のステップ

これで、Queue Storage の基本を学習できました。さらに複雑なストレージ タスクを実行するには、次のリンク先を参照してください。

非推奨の .NET バージョン 11.x SDK を使用する関連コード サンプルについて、詳しくは「.NET バージョン 11.x を使用したコード サンプル」をご覧ください。