【MS Learn】アプリケーションと Azure Queue Storage の間で通信する をやってみた
はじめに
やってみたシリーズです。
今回は Azure Queue Storage を使ってみます。
対象のトレーニングはこちら。
演習 - ストレージ アカウントを作成する
サンドボックス環境が用意されるので、その環境で実行していきます。
Azure CLI を使用してストレージ アカウントを作成する
生成されたコマンドを元に用意された Azure Cloud Shell で実行します。
$ az storage account create -g learn-759f9aad-33f7-473a-9f8b-c3d324621976 --kind StorageV2 --sku Standard_LRS --name learn759f9aadstorage
{
"accessTier": "Hot",
"accountMigrationInProgress": null,
"allowBlobPublicAccess": false,
"allowCrossTenantReplication": false,
"allowSharedKeyAccess": null,
"allowedCopyScope": null,
"azureFilesIdentityBasedAuthentication": null,
"blobRestoreStatus": null,
"creationTime": "2023-12-18T08:26:51.707246+00:00",
"customDomain": null,
"defaultToOAuthAuthentication": null,
"dnsEndpointType": null,
"enableHttpsTrafficOnly": true,
"enableNfsV3": null,
"encryption": {
"encryptionIdentity": null,
"keySource": "Microsoft.Storage",
"keyVaultProperties": null,
"requireInfrastructureEncryption": null,
"services": {
"blob": {
"enabled": true,
"keyType": "Account",
"lastEnabledTime": "2023-12-18T08:26:51.972880+00:00"
},
"file": {
"enabled": true,
"keyType": "Account",
"lastEnabledTime": "2023-12-18T08:26:51.972880+00:00"
},
"queue": null,
"table": null
}
},
"extendedLocation": null,
"failoverInProgress": null,
"geoReplicationStats": null,
"id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/learn-759f9aad-33f7-473a-9f8b-c3d324621976/providers/Microsoft.Storage/storageAccounts/learn759f9aadstorage",
"identity": null,
"immutableStorageWithVersioning": null,
"isHnsEnabled": null,
"isLocalUserEnabled": null,
"isSftpEnabled": null,
"isSkuConversionBlocked": null,
"keyCreationTime": {
"key1": "2023-12-18T08:26:51.800968+00:00",
"key2": "2023-12-18T08:26:51.800968+00:00"
},
"keyPolicy": null,
"kind": "StorageV2",
"largeFileSharesState": null,
"lastGeoFailoverTime": null,
"location": "westus",
"minimumTlsVersion": "TLS1_0",
"name": "learn759f9aadstorage",
"networkRuleSet": {
"bypass": "AzureServices",
"defaultAction": "Allow",
"ipRules": [],
"ipv6Rules": [],
"resourceAccessRules": null,
"virtualNetworkRules": []
},
"primaryEndpoints": {
"blob": "https://learn759f9aadstorage.blob.core.windows.net/",
"dfs": "https://learn759f9aadstorage.dfs.core.windows.net/",
"file": "https://learn759f9aadstorage.file.core.windows.net/",
"internetEndpoints": null,
"microsoftEndpoints": null,
"queue": "https://learn759f9aadstorage.queue.core.windows.net/",
"table": "https://learn759f9aadstorage.table.core.windows.net/",
"web": "https://learn759f9aadstorage.z22.web.core.windows.net/"
},
"primaryLocation": "westus",
"privateEndpointConnections": [],
"provisioningState": "Succeeded",
"publicNetworkAccess": null,
"resourceGroup": "learn-759f9aad-33f7-473a-9f8b-c3d324621976",
"routingPreference": null,
"sasPolicy": null,
"secondaryEndpoints": null,
"secondaryLocation": null,
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"statusOfPrimary": "available",
"statusOfSecondary": null,
"storageAccountSkuConversionStatus": null,
"tags": {},
"type": "Microsoft.Storage/storageAccounts"
}
演習 - キューを識別する
スターター アプリケーションを複製して開く
- ソリューションを複製します。
$ cd ~
$ git clone https://github.com/MicrosoftDocs/mslearn-communicate-with-storage-queues.git
- ディレクトリをスターター フォルダーに変更し、Cloud Shell エディターを開きます。
$ cd mslearn-communicate-with-storage-queues/start/
$ code .
Azure.Storage.Queues NuGet パッケージ
スターター アプリケーションには、Azure.Storage.Queues パッケージが既にインストールされています。
これのことですかね。
<ItemGroup>
<PackageReference Include="Azure.Storage.Queues" Version="12.8.0" />
</ItemGroup>
接続文字列を取得する
Azure CLI で取得します。
$ export MY_STORAGE_CONNECTION_STRING=`az storage account show-connection-string -g learn-759f9aad-33f7-473a-9f8b-c3d324621976 --output tsv -n learn759f9aadstorage`
$ echo $MY_STORAGE_CONNECTION_STRING
DefaultEndpointsProtocol=https;EndpointSuffix=core.windows.net;AccountName=learn759f9aadstorage;AccountKey=xxxxxxxxxx7zxQ+aHniRpt5rkGHokcGz7a2zrJe5SKgSmIdH2jHgKbqGPOE5JcjKGIH2OV/yWotY+AStB3/gWA==;BlobEndpoint=https://learn759f9aadstorage.blob.core.windows.net/;FileEndpoint=https://learn759f9aadstorage.file.core.windows.net/;QueueEndpoint=https://learn759f9aadstorage.queue.core.windows.net/;TableEndpoint=https://learn759f9aadstorage.table.core.windows.net/
QueueClient を作成するコードを追加する
QueueClient クラスは、ストレージ キューとの通信を管理します。
QueueClient クラスを使うと、キューを作成し、キューとの間でメッセージを送受信できます。
ちなみに、QueueClinet はスレッドセーフなようです。
なのでアプリケーション全体で一つのインスタンスを使いまわせばよいみたい。
アプリケーションがやり取りするキューごとに、1 つの QueueClient オブジェクトを作成します。 そして、キューにアクセスする必要のあるコード内のすべてのメソッドに、その QueueClient インスタンスを渡します。 この QueueClient クラスはスレッドセーフなので、1 つのインスタンスをアプリケーション全体で使用することができます。
- コード エディターで Program.cs ファイルを開きます。
- Main メソッドの先頭に、次のコードを追加します。
class Program
{
static async Task Main(string[] args)
{
// Add code to create QueueClient and Storage Queue Here
+ string connectionString = Environment.GetEnvironmentVariable("MY_STORAGE_CONNECTION_STRING");
+ QueueClient queueClient = new QueueClient(connectionString, "newsqueue");
bool exitProgram = false;
while (exitProgram == false)
ストレージ アカウント キューを作成する
キューからメッセージを送受信する前に、キュー自体を作成する必要があります。 キューは、Azure portal、Azure CLI、Azure PowerShell から、またはコード内で作成できます。 このアプリケーションのサンプルでは、コードからキューを作成します。
ということでコードからキューを作成します。
以下の1文をProgram.csに追加します。
class Program
{
static async Task Main(string[] args)
{
// Add code to create QueueClient and Storage Queue Here
string connectionString = Environment.GetEnvironmentVariable("MY_STORAGE_CONNECTION_STRING");
QueueClient queueClient = new QueueClient(connectionString, "newsqueue");
+ await queueClient.CreateIfNotExistsAsync();
bool exitProgram = false;
while (exitProgram == false)
演習 - メッセージをキューに追加する
メッセージを送信するためのコードを追加する
- Program.cs を開きます。
- SendMessageAsync メソッドを見つけます。
- NotImplementedException をスローする行を削除します。
- SendMessageAsync メソッドの先頭に次のコードを追加して、ユーザーからの NewsArticle を取得します。
static async Task SendMessageAsync(QueueClient queueClient)
{
- throw new NotImplementedException();
+ Console.WriteLine("Enter headline: ");
+ string headline = Console.ReadLine();
+ Console.WriteLine("Enter location: ");
+ string location = Console.ReadLine();
+ NewsArticle article = new NewsArticle() { Headline = headline, Location = location };
}
- キューに格納する NewsArticle オブジェクトをJSON にシリアル化し、SendMessageAsync メソッドを使用してメッセージをキューに送信します。
static async Task SendMessageAsync(QueueClient queueClient)
{
Console.WriteLine("Enter headline: ");
string headline = Console.ReadLine();
Console.WriteLine("Enter location: ");
string location = Console.ReadLine();
NewsArticle article = new NewsArticle() { Headline = headline, Location = location };
+ string message = JsonSerializer.Serialize(article);
+ Response<SendReceipt> response = await queueClient.SendMessageAsync(message);
+ SendReceipt sendReceipt = response.Value;
}
- メッセージを送信した際の応答に含まれていた SendReceipt に関する情報をコンソールに出力します。
static async Task SendMessageAsync(QueueClient queueClient)
{
// Get input from user
Console.WriteLine("Enter headline: ");
string headline = Console.ReadLine();
Console.WriteLine("Enter location: ");
string location = Console.ReadLine();
NewsArticle article = new NewsArticle() { Headline = headline, Location = location };
// Build and send the message to the queue
string message = JsonSerializer.Serialize(article);
Response<SendReceipt> response = await queueClient.SendMessageAsync(message);
SendReceipt sendReceipt = response.Value;
+ Console.WriteLine($"Message sent. Message id={sendReceipt.MessageId} Expiration time={sendReceipt.ExpirationTime}");
+ Console.WriteLine();
}
アプリケーションを実行する
- Cloud Shell で dotnet build コマンドを使用してアプリケーションをビルドします。
$ dotnet build
- アプリケーションを実行します。
$ dotnet run
- アプリケーションが起動したら、オプション 1 を選択してメッセージを送信し、お好みの見出しと場所を入力して、キューにメッセージを送信します。
What operation would you like to perform?
1 - Send message
2 - Peek at the next message
3 - Receive message
X - Exit program
1
Enter headline:
近所のネコの生態について
Enter location:
日本
Message sent. Message id=5d5f677e-4162-4d3e-87c7-151da69ed3ca Expiration time=12/25/2023 8:56:12 AM +00:00
What operation would you like to perform?
1 - Send message
2 - Peek at the next message
3 - Receive message
X - Exit program
X
結果を確認する
キューの確認は、Azure portal で Azure CLI を使用するか、Azure PowerShell を使用して行うことができます。
ここでは Azure CLI で確認します。
$ az storage message peek --queue-name newsqueue --connection-string $MY_STORAGE_CONNECTION_STRING
Command group 'storage message' is in preview and under development. Reference and support levels: https://aka.ms/CLI_refstatus
[
{
"content": "{\"Headline\":\"\\u8FD1\\u6240\\u306E\\u30CD\\u30B3\\u306E\\u751F\\u614B\\u306B\\u3064\\u3044\\u3066\",\"Location\":\"\\u65E5\\u672C\"}",
"dequeueCount": 0,
"expirationTime": "2023-12-25T08:56:12+00:00",
"id": "5d5f677e-4162-4d3e-87c7-151da69ed3ca",
"insertionTime": "2023-12-18T08:56:12+00:00",
"popReceipt": null,
"timeNextVisible": null
}
]
がっつりエンコードされていてわかりませんが、なにか入ったようです。
演習 - キューからメッセージを取得する
次のメッセージをクイック表示する
- Program.cs を開きます。
- PeekMessageAsync メソッドを見つけ、NotImplementedException をスローする行を削除します。
- メソッドに次のコードを追加します。 このコードは、キューの次のメッセージをクイック表示し、メッセージに関する情報を出力します。
static async Task PeekMessageAsync(QueueClient queueClient)
{
- throw new NotImplementedException();
+ Response<PeekedMessage> response = await queueClient.PeekMessageAsync();
+ PeekedMessage message = response.Value;
+ Console.WriteLine($"Message id : {message.MessageId}");
+ Console.WriteLine($"Inserted on : {message.InsertedOn}");
+ Console.WriteLine("We are only peeking at the message, so another consumer could dequeue this message");
}
メッセージの受信と処理
- ReceiveMessageAsync メソッドを見つけ、NotImplementedException をスローする行を削除します。
- ReceiveMessageAsync メソッドの先頭に次のコードを追加して、キューからメッセージを取得します。
static async Task ReceiveMessageAsync(QueueClient queueClient)
{
- throw new NotImplementedException();
+ Response<QueueMessage> response = await queueClient.ReceiveMessageAsync();
+ QueueMessage message = response.Value;
}
- 次のコードを追加します。JSON 形式の生メッセージの本文など、受信したメッセージに関するプロパティを出力します。
static async Task ReceiveMessageAsync(QueueClient queueClient)
{
Response<QueueMessage> response = await queueClient.ReceiveMessageAsync();
QueueMessage message = response.Value;
+ Console.WriteLine($"Message id : {message.MessageId}");
+ Console.WriteLine($"Inserted on : {message.InsertedOn}");
+ Console.WriteLine($"Message (raw) : {message.Body}");
}
- メッセージの内容を、自分のコード内で使用できるオブジェクトにデシリアライズするため、QueueMessage オブジェクトの Body プロパティに ToObjectFromJson メソッドを追加します。
static async Task ReceiveMessageAsync(QueueClient queueClient)
{
Response<QueueMessage> response = await queueClient.ReceiveMessageAsync();
QueueMessage message = response.Value;
Console.WriteLine($"Message id : {message.MessageId}");
Console.WriteLine($"Inserted on : {message.InsertedOn}");
Console.WriteLine($"Message (raw) : {message.Body}");
+ NewsArticle article = message.Body.ToObjectFromJson<NewsArticle>();
+ Console.WriteLine("News Article");
+ Console.WriteLine($"- Headline : {article.Headline}");
+ Console.WriteLine($"- Location : {article.Location}");
}
- 最後に、メッセージの処理を終了するときに、他のコンシューマーによって処理されないよう、キューからメッセージを削除します。
static async Task ReceiveMessageAsync(QueueClient queueClient)
{
Response<QueueMessage> response = await queueClient.ReceiveMessageAsync();
QueueMessage message = response.Value;
Console.WriteLine($"Message id : {message.MessageId}");
Console.WriteLine($"Inserted on : {message.InsertedOn}");
Console.WriteLine($"Message (raw) : {message.Body}");
NewsArticle article = message.Body.ToObjectFromJson<NewsArticle>();
Console.WriteLine("News Article");
Console.WriteLine($"- Headline : {article.Headline}");
Console.WriteLine($"- Location : {article.Location}");
+ Console.WriteLine("The processing for this message is just printing it out, so now it will be deleted");
+ await queueClient.DeleteMessageAsync(message.MessageId, message.PopReceipt);
+ Console.WriteLine($"Message deleted");
}
- Program.cs を保存します。
アプリケーションを実行する
- アプリケーションをビルドします。
$ dotnet build
- アプリケーションを実行します。
$ dotnet run
- キューにメッセージを追加したり、表示したりしましょう。
What operation would you like to perform?
1 - Send message
2 - Peek at the next message
3 - Receive message
X - Exit program
1
Enter headline:
近所のネコに新しい仲間が増えました
Enter location:
日本
Message sent. Message id=1c04af1a-8686-4fbe-af9e-94e8c24d29d0 Expiration time=12/25/2023 9:11:04 AM +00:00
What operation would you like to perform?
1 - Send message
2 - Peek at the next message
3 - Receive message
X - Exit program
2
Message id : 5d5f677e-4162-4d3e-87c7-151da69ed3ca
Inserted on : 12/18/2023 8:56:12 AM +00:00
We are only peeking at the message, so another consumer could dequeue this message
What operation would you like to perform?
1 - Send message
2 - Peek at the next message
3 - Receive message
X - Exit program
3
Message id : 5d5f677e-4162-4d3e-87c7-151da69ed3ca
Inserted on : 12/18/2023 8:56:12 AM +00:00
Message (raw) : {"Headline":"\u8FD1\u6240\u306E\u30CD\u30B3\u306E\u751F\u614B\u306B\u3064\u3044\u3066","Location":"\u65E5\u672C"}
News Article
- Headline : 近所のネコの生態について
- Location : 日本
The processing for this message is just printing it out, so now it will be deleted
Message deleted
What operation would you like to perform?
1 - Send message
2 - Peek at the next message
3 - Receive message
X - Exit program
3
Message id : 1c04af1a-8686-4fbe-af9e-94e8c24d29d0
Inserted on : 12/18/2023 9:11:04 AM +00:00
Message (raw) : {"Headline":"\u8FD1\u6240\u306E\u30CD\u30B3\u306B\u65B0\u3057\u3044\u4EF2\u9593\u304C\u5897\u3048\u307E\u3057\u305F","Location":"\u65E5\u672C"}
News Article
- Headline : 近所のネコに新しい仲間が増えました
- Location : 日本
The processing for this message is just printing it out, so now it will be deleted
Message deleted
What operation would you like to perform?
1 - Send message
2 - Peek at the next message
3 - Receive message
X - Exit program
なんだか良さそう!
おわりに
今回はすんなり動きました。
そしてSDK使うので簡単で良いですね。
それではまた。
Discussion