クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

キュー、送信、受信、削除

このレッスンのあとで: メッセージが、送信から削除までに、どうなるかを説明できる。

55分のレッスンコマンド6件クラウドラボ:AWS コマンドラインで S3 バケット、SQS キュー、DynamoDB テーブルを練習する

ラーメン店の伝票の列

ラーメン店の厨房には、注文の伝票が順に並びます。ホールの人が伝票を後ろに足し、料理人が先頭の1枚を取って作ります。

SQS のキューは、メッセージについて同じことをします。ネットショップは、新しい注文をキューに入れ、ワーカーが1つずつ取り出します。このレッスンでは、1つのメッセージを、送信から削除まで追います。

このレッスンのゴール

メモ

メッセージが、送信から削除までに、どうなるかを説明できる。

キーワード

ことばいみ
キュー処理を待つメッセージの列
メッセージキューで待つ、1つの文字のかたまり
受信作業するメッセージを、キューに求めること
可視性タイムアウト受信したメッセージが、隠れている時間
レシートハンドル受信したメッセージを削除するための札
少なくとも1回メッセージは2回届くことがあるが、0回にはならない

学生が入力するセルは、このプレビューでは空白です。

受信するとメッセージが届く

send_message は、文字をキューに入れます。答えには MessageId があります。receive_message は、メッセージを求めます。答えには、Messages というリストがあります。

各メッセージは、文字の Body と、ReceiptHandle を持ちます。本文はただの文字です。多くの店は、本文に JSON を入れ、ワーカーが json.loads で辞書に戻します。

例: receive の答え

項目中身例
Messagesメッセージ1つにつき、辞書が1つ入ったリスト2つのメッセージ
MessageId送ったときにキューが付けた idm-1
Body送った文字{"order": 1, "item": "ramen"}
ReceiptHandleこの受信を削除するための札h-1
ApproximateReceiveCount受信された回数。文字で入る"1"

学生が入力するセルは、このプレビューでは空白です。

実行: receive の答えを読む

コード: python
import json
answer = {
    "Messages": [
        {"MessageId": "m-1", "ReceiptHandle": "h-1",
         "Body": "{\"order\": 1, \"item\": \"ramen\"}",
         "Attributes": {"ApproximateReceiveCount": "1"}},
        {"MessageId": "m-2", "ReceiptHandle": "h-2", "Body": "gyoza",
         "Attributes": {"ApproximateReceiveCount": "1"}},
    ]
}
for message in answer["Messages"]:
    print(message["MessageId"], message["Body"])
order = json.loads(answer["Messages"][0]["Body"])
print("品物:", order["item"])
# ループが ReceiptHandle も表示するように変えましょう。

受信したメッセージは隠れる

受信しても、メッセージは消えません。可視性タイムアウトの間、隠れるだけで、取り込んだキューでは30秒です。隠れている間、ほかのワーカーは受信できません。

作業が終わったら、ReceiptHandle を付けて delete_message を呼びます。そのときはじめて、メッセージが消えます。先にワーカーが止まると、タイムアウトが終わり、メッセージはまた見えて、別のワーカーが受け取れます。

例: キューの属性

属性値意味
VisibilityTimeout"30"受信したメッセージが隠れる秒数
ApproximateNumberOfMessages"3"受信を待っているメッセージの数
ApproximateNumberOfMessagesNotVisible"0"受信のあとで隠れているメッセージの数
MessageRetentionPeriod"345600"メッセージを保つ秒数で、4日

学生が入力するセルは、このプレビューでは空白です。

実行: 隠れて、また見える

コード: python
TIMEOUT = 30
received_at = {"m-1": 100}


def is_visible(message_id, now):
    if message_id not in received_at:
        return True
    return now >= received_at[message_id] + TIMEOUT


for now in [100, 120, 130, 160]:
    print(now, is_visible("m-1", now))
print("m-2 は受信されていない:", is_visible("m-2", 100))
# TIMEOUT を 60 に変えましょう。m-1 が見えるのは、いつからですか。

よくある間違い

注意

受信すると、メッセージが取り除かれると考える人が多いです。隠れるだけです。delete_message を呼ばないと、タイムアウトのあとメッセージが戻り、もう一度処理されます。削除は、作業が終わってからです。

少なくとも1回は、重複もある

キューは、削除されるまでメッセージを保つので、同じメッセージが2回届くことがあります。ワーカーが作業を終えて、削除の前に止まる場合です。

受信が、求めた数より少ないメッセージや、0件を返すこともあります。空の答えには Messages がないので、読む前に、あるかどうかを調べます。重複しても害がないように、ワーカーを書きましょう。

実行: 重複を飛ばす

コード: python
deliveries = ["m-1", "m-2", "m-1", "m-3"]
done = []
for message_id in deliveries:
    if message_id in done:
        print(message_id, "2回目: 飛ばす")
    else:
        done.append(message_id)
        print(message_id, "初めて: 作業する")

empty = {}
if "Messages" in empty:
    print("メッセージの数:", len(empty["Messages"]))
else:
    print("メッセージの数: 0")
# 代わりに empty["Messages"] を試しましょう。何が起きますか。

クラウドラボで試す

クラウドラボは、S3、SQS、DynamoDB の練習用の複製です。バーの ラボを起動 を押してから、下の各コマンドの 実行 を押します。本物の AWS コマンドラインを使うので、同じ言葉が本物のアカウントでも通じます。削除したあとでキューをもう一度たずねると、何も表示されません。キューは空に見えます。この手順は練習です。下の課題はふつうの Python のままなので、ラボなしでも解けます。

作り物のキーとラボのアドレスを設定する

コマンド
export AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test AWS_DEFAULT_REGION=us-east-1 AWS_ENDPOINT_URL=http://cloud:4566

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

キューを作る

コマンド
Q=$(aws sqs create-queue --queue-name orders --query QueueUrl --output text)

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

メッセージを送る

コマンド
aws sqs send-message --queue-url $Q --message-body "order 1"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

受け取って返事を保存する

コマンド
aws sqs receive-message --queue-url $Q | tee reply.json

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

受信ハンドルを取っておく

コマンド
H=$(grep -o '"ReceiptHandle": "[^"]*"' reply.json | cut -d'"' -f4)

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

メッセージを削除する

コマンド
aws sqs delete-message --queue-url $Q --receipt-handle "$H"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

このラボとソースについて: クラウドラボ:AWS コマンドラインで S3 バケット、SQS キュー、DynamoDB テーブルを練習する

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。