演習 - キューを使用してメッセージを送受信する

完了

販売担当者が使用しているモバイル アプリと、Azure SQL Database インスタンスに各販売に関する詳細情報を格納する、Azure でホストされた Web サービスとの間で、Service Bus キューを使用して、個々の販売に関するメッセージを処理することを選択しました。

前の演習では、Azure サブスクリプションに必要なオブジェクトを実装しました。 ここでは、そのキューにメッセージを送信したり、キューからメッセージを取得したりするコードを記述します。

このユニットでは、2 つのコンソール アプリケーションをビルドします。1 つのアプリケーションはメッセージを Service Bus キューに入れ、もう 1 つのアプリケーションはメッセージを Service Bus キューから取得します。 これらのアプリケーションは、単一の .NET Core ソリューションの一部です。

Service Bus 名前空間への接続文字列を取得する

Service Bus 名前空間にアクセスし、その名前空間内でキューを使用するには、2 つのコンソール アプリで次の 2 つの情報を構成する必要があります。

  • 名前空間のエンドポイント
  • 認証のための共有アクセス キー

これらの値は、接続文字列から取得できます。

  1. 右側にある Azure Cloud Shell で次のコマンドを実行します。<namespace-name> は、前の演習で作成した Service Bus 名前空間に置き換えます。

    az servicebus namespace authorization-rule keys list \
        --resource-group <rgn>[sandbox resource group name]</rgn> \
        --name RootManageSharedAccessKey \
        --query primaryConnectionString \
        --output tsv \
        --namespace-name <namespace-name>
    

    応答の最後の行が接続文字列です。これには、名前空間のエンドポイントと共有アクセス キーが含まれます。 次の例のようになるはずです。

    Endpoint=sb://example.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=xxxxxxxx
    
  2. Cloud Shell から接続文字列をコピーします。 この接続文字列はこのモジュールを通して複数回必要になるため、すぐ使用できる場所に保存してください。

スターター アプリケーションを複製して開く

Note

わかりやすくするため、以下のタスクでは、両方のコンソール アプリケーションの Program.cs ファイルに接続文字列をハード コーディングするように説明しています。 運用アプリケーションでは、接続文字列の格納には構成ファイルまたは Azure Key Vault を使用します。

  1. Cloud Shell で次のコマンドを実行して、Git プロジェクト ソリューションをクローンします。

    cd ~
    git clone https://github.com/MicrosoftDocs/mslearn-connect-services-together.git
    
  2. 次のコマンドを実行して、クローンしたプロジェクトの start フォルダーに移動し、Cloud Shell エディターを開きます。

    cd ~/mslearn-connect-services-together/implement-message-workflows-with-service-bus/src/start
    code .
    

キューにメッセージを送信するコードを記述する

  1. Cloud Shell エディターで、privatemessagesender/Program.cs を開き、次のコード行を見つけます。

    const string ServiceBusConnectionString = "";
    

    接続文字列を引用符の間に貼り付けます。

  2. キュー名に salesmessages とは異なる名前を使用した場合は、コード内の QueueName プロパティの値を更新します。

    const string QueueName = "salesmessages";
    
  3. 販売に関するメッセージを送信するコンポーネントを完成させるには、非同期操作が完了するまで非同期メソッドの評価を中断する await 演算子を追加する必要があります。 SendSalesMessageAsync() メソッドを見つけます。 そのメソッド内で、次のコード行を見つけます。

    // Create a Service Bus client here
    

    そのコード行を次のコードに置き換えます。

    // By leveraging "await using", the DisposeAsync method will be called automatically once the client variable goes out of scope. 
    // In more realistic scenarios, you would want to store off a class reference to the client (rather than a local variable) so that it can be used throughout your program.
    
    await using var client = new ServiceBusClient(ServiceBusConnectionString);
    
  4. SendSalesMessageAsync() メソッド内で、次のコード行を見つけます。

    // Create a sender here
    

    そのコメントを次のコードに置き換えます。

    await using ServiceBusSender sender = client.CreateSender(QueueName);
    
  5. try...catch ブロック内で、次のコード行を見つけます。

    // Create and send a message here
    

    そのコード行を次のコード行に置き換えます。

    string messageBody = $"$10,000 order for bicycle parts from retailer Adventure Works.";
    var message = new ServiceBusMessage(messageBody);
    
  6. コンソールにメッセージを表示するために、先ほど追加した内容のすぐ下の新しい行に次のコードを挿入します。

    Console.WriteLine($"Sending message: {messageBody}");
    
  7. 次の行に次のコードを挿入します。

    await sender.SendMessageAsync(message);
    
  8. 送信側とクライアントのオブジェクトを破棄するには、ファイルの末尾近くにある次のコメントを見つけます。

    // Close the connection to the sender here
    

    この行を次のコードに置き換えます。

    finally
    {
        // Calling DisposeAsync on client types is required to ensure that network
        // resources and other unmanaged objects are properly cleaned up.
        await sender.DisposeAsync();
        await client.DisposeAsync();
    }
    
  9. privatemessagesender/Program.cs の最終的なコードが次の例のようになっていることを確認します。

    using System;
    using System.Text;
    using System.Threading.Tasks;
    using Azure.Messaging.ServiceBus;
    
    namespace privatemessagesender
    {
        class Program
        {
            const string ServiceBusConnectionString = "Endpoint=sb://example.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=xxxxxx";
            const string QueueName = "salesmessages";
    
            static void Main(string[] args)
            {
                Console.WriteLine("Sending a message to the Sales Messages queue...");
                SendSalesMessageAsync().GetAwaiter().GetResult();
                Console.WriteLine("Message was sent successfully.");
            }
    
            static async Task SendSalesMessageAsync()
            {
                await using var client = new ServiceBusClient(ServiceBusConnectionString);
    
                await using ServiceBusSender sender = client.CreateSender(QueueName);
                try
                {
                    string messageBody = $"$10,000 order for bicycle parts from retailer Adventure Works.";
                    var message = new ServiceBusMessage(messageBody);
                    Console.WriteLine($"Sending message: {messageBody}");
                    await sender.SendMessageAsync(message);
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
                }
                finally
                {
                    // Calling DisposeAsync on client types is required to ensure that network
                    // resources and other unmanaged objects are properly cleaned up.
                    await sender.DisposeAsync();
                    await client.DisposeAsync();
                }
            }
        }
    }
    
  10. 変更を保存するには、Ctrl + S キーを押します。また、エディターを閉じるには、Ctrl + Q キーを押します。

メッセージをキューに送信する

  1. Cloud Shell で次のコマンドを実行して、販売に関するメッセージを送信します。 最初の行で確実に正しいパスを表示します。

    cd ~/mslearn-connect-services-together/implement-message-workflows-with-service-bus/src/start
    dotnet run --project ./privatemessagesender
    

    Note

    この演習でのアプリの初回実行時に、dotnet でリモート ソースからパッケージを復元し、アプリをビルドします。

    プログラムが実行されると、アプリがメッセージを送信中であることを示すメッセージがコンソールに出力されます。

    Sending a message to the Sales Messages queue...
    Sending message: $10,000 order for bicycle parts from retailer Adventure Works.
    Message was sent successfully.
    
  2. アプリが完了したら、次のコマンドを実行します。<namespace-name> は、Service Bus 名前空間の名前に置き換えてください。 このコマンドは、キューに入っているメッセージの数を返します。

    az servicebus queue show \
        --resource-group <rgn>[sandbox resource group name]</rgn> \
        --name salesmessages \
        --query messageCount \
        --namespace-name <namespace-name>
    
  3. ステップ 1 の dotnet run コマンドをもう一度実行してから、servicebus queue show コマンドをもう一度実行します。 dotnet アプリを実行するたびに、新しいメッセージがキューに追加されます。 Azure コマンドを実行するたびに、messageCount が増加することがわかります。

キューからメッセージを受信するコードの作成

  1. 次のコマンドを入力して、もう一度エディターを開きます。

    code .
    
  2. エディターで、privatemessagereceiver/Program.cs を開き、次のコード行を見つけます。

    const string ServiceBusConnectionString = "";
    

    引用符の間に、先に保存した接続文字列を貼り付けます。

  3. ReceiveSalesMessageAsync() メソッドを見つけます。 そのメソッド内で、次のコード行を見つけます。

    // Create a Service Bus client that will authenticate using a connection string
    

    この行を次のコードに置き換えます。

    var client = new ServiceBusClient(ServiceBusConnectionString);
    
  4. メッセージ処理オプションを構成するには、次のコード行を見つけます。

    // Create the options to use for configuring the processor
    

    その行を次のコード行に置き換えます。

    var processorOptions = new ServiceBusProcessorOptions
    {
        MaxConcurrentCalls = 1,
        AutoCompleteMessages = false
    };
    
  5. プロセッサを作成するには、次のコード行を見つけます。

    // Create a processor that we can use to process the messages
    

    この行を次のコードに置き換えます。

    await using ServiceBusProcessor processor = client.CreateProcessor(QueueName, processorOptions);
    
  6. ハンドラーを構成するには、次のコード行を見つけます。

    // Configure the message and error handler to use
    

    この行を次のコードに置き換えます。

    processor.ProcessMessageAsync += MessageHandler;
    processor.ProcessErrorAsync += ErrorHandler;
    
  7. 処理を開始するには、次のコード行を見つけます。

    // Start processing
    

    この行を次のコードに置き換えます。

    await processor.StartProcessingAsync();
    
  8. Service Bus への接続を閉じるには、次のコード行を見つけます。

    // Close the processor here
    

    この行を次のコードに置き換えます。

    await processor.CloseAsync();
    
  9. MessageHandler メソッドのコードを確認します。

    // handle received messages
    static async Task MessageHandler(ProcessMessageEventArgs args)
    {
        // extract the message
        string body = args.Message.Body.ToString();
    
        // print the message
        Console.WriteLine($"Received: {body}");
    
        // complete the message so that message is deleted from the queue. 
        await args.CompleteMessageAsync(args.Message);
    }
    
  10. ErrorHandler メソッドのコードを確認します。

    // handle any errors when receiving messages
    static Task ErrorHandler(ProcessErrorEventArgs args)
    {
        // print the exception message
        Console.WriteLine(args.Exception.ToString());
        return Task.CompletedTask;
    }    
    
  11. privatemessagereceiver/Program.cs の最終的なコードが次の例のようになっていることを確認します。

    using System;
    using System.Text;
    using System.Threading.Tasks;
    using Azure.Messaging.ServiceBus;
    
    namespace privatemessagereceiver
    {
        class Program
        {
    
            const string ServiceBusConnectionString = "Endpoint=sb://<examplenamespace.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
            const string QueueName = "salesmessages";
    
            static void Main(string[] args)
            {
    
                ReceiveSalesMessageAsync().GetAwaiter().GetResult();
    
            }
    
            static async Task ReceiveSalesMessageAsync()
            {
    
                Console.WriteLine("======================================================");
                Console.WriteLine("Press ENTER key to exit after receiving all the messages.");
                Console.WriteLine("======================================================");
    
    
                var client = new ServiceBusClient(ServiceBusConnectionString);
    
                var processorOptions = new ServiceBusProcessorOptions
                {
                    MaxConcurrentCalls = 1,
                    AutoCompleteMessages = false
                };
    
                await using ServiceBusProcessor processor = client.CreateProcessor(QueueName, processorOptions);
    
                processor.ProcessMessageAsync += MessageHandler;
                processor.ProcessErrorAsync += ErrorHandler;
    
    
                await processor.StartProcessingAsync();
    
                Console.Read();
    
                await processor.CloseAsync();
    
            }
    
            // handle received messages
            static async Task MessageHandler(ProcessMessageEventArgs args)
            {
                string body = args.Message.Body.ToString();
                Console.WriteLine($"Received: {body}");
    
                // complete the message. messages is deleted from the queue. 
                await args.CompleteMessageAsync(args.Message);
            }
    
            // handle any errors when receiving messages
            static Task ErrorHandler(ProcessErrorEventArgs args)
            {
                Console.WriteLine(args.Exception.ToString());
                return Task.CompletedTask;
            }
        }
    }
    
    
  12. 変更を保存するには、Ctrl + S キーを押します。また、エディターを閉じるには、Ctrl + Q キーを押します。

キューからメッセージを受信する

  1. 販売に関するメッセージを受信するコンポーネントを実行するには、Cloud Shell で次のコマンドを実行します。

    dotnet run --project privatemessagereceiver
    
  2. Cloud Shell で通知を確認します。 Azure portal で Service Bus 名前空間に移動し、[メッセージ] グラフを確認します。

    Received: $10,000 order for bicycle parts from retailer Adventure Works.
    
  3. Cloud Shell でメッセージが受信されたことを確認したら、Enter キーを押してアプリを停止します。

メッセージ数を調べる

以下のコードを実行して、すべてのメッセージがキューから削除されたことを確認します。<namespace-name> は、必ず Service Bus 名前空間に置き換えてください。

az servicebus queue show \
    --resource-group <rgn>[sandbox resource group name]</rgn> \
    --name salesmessages \
    --query messageCount \
    --namespace-name <namespace-name>

すべてのメッセージが削除されている場合、出力は 0 となります。

個々の販売に関するメッセージを Service Bus キューに送信するコードを記述しました。 営業部門の分散アプリケーションでは、販売担当者がデバイスで使用するモバイル アプリにこのコードを記述する必要があります。

Service Bus キューからメッセージを受信するコードも記述しました。 営業部門の分散アプリケーションでは、Azure で実行されて受信メッセージを処理する Web サービスにこのコードを記述する必要があります。