今回は以前参加した勉強会『JAWS-UG CLI専門支部 #152R SQS入門』の復習です。
相変わらずアウトプットのタイミングは遅くなりましたが、一歩ずつ前進していきます。
今回も勉強会への参加をきっかけに、復習することで多くの学びがありました(感謝)。
ざっくりまとめ
- コンポーネントをSQSで”つないで”疎結合化
- キューは「スタンダードキュー」と「FIFOキュー」の2種類
- 「プロデューサー」がメッセージを送信し、「コンシューマ」が受信する
- メッセージの取得方法は「ショートポーリング」と「ロングポーリング」の2種類
- メッセージは受信したら削除する必要あり
- 可視性タイムアウト機能により受信後のメッセージは一定時間見えなくなり、重複取得を避ける
- メッセージには最大で10個の属性を追加できる
- SQSを利用するアプリケーションは冪等性を保つ必要がある
- ハンズオンで使用したコマンド(オプションの記述は省略)
sqs create-queue
キューの作成sqs list-queues
キューの一覧を出力sqs get-queue-url
キューのURLを取得sqs set-queue-attributes
キューの属性を更新sqs get-queue-attributes
キューの属性/メッセージ数を取得sqs send-message
メッセージの送信sqs receive-message
メッセージの受信sqs delete-message
メッセージの削除sqs delete-queue
キューの削除
ハンズオン内容
ここではハンズオン内で使用したコマンドを部分的に抜粋し、ハンズオンの流れを紹介するための記載感になっています。
ハンズオン内容の詳細が気になる方は、本家のハンズオン手順書を御覧ください。
というか、波田野(@tcsh)さんの勉強会めちゃくちゃ勉強になるので参加した方が良いです。
→波田野さんが主催されている「JAWS-UG CLI専門支部」のconnpassグループは『こちら』
1. 構築
1.1.キューの構築
【キューの構築】
aws sqs create-queue \
--queue-name ${SQS_QUEUE_NAME}
【キューの存在確認】
aws sqs list-queues \
--queue-name-prefix ${SQS_QUEUE_NAME} \
--query "QueueUrls[?contains(@, `${SQS_QUEUE_NAME}`)]" \
--output text
※メモ
query 内でcontains関数 [?contains(【キー名】,\
【検索文字】`)]` を使うことにより、部分一致のフィルタが可能。
(マネジメントコンソール:キューが作成されている)
1.2.キュー属性の更新
【キューのURLを取得】
SQS_QUEUE_URL=$( \
aws sqs get-queue-url \
--queue-name ${SQS_QUEUE_NAME} \
--output text \
)
※メモ
「=$()」によりカッコ内の結果を変数に渡す。
【キューの属性を変更】
aws sqs set-queue-attributes \
--queue-url ${SQS_QUEUE_URL} \
--attributes VisibilityTimeout=60
※メモ
属性”VisibilityTimeout”の値を”60″秒に更新
値は0〜43,200(12 hours)の間で設定可能(デフォルト値は”30″)
【キューの属性を取得(VisibilityTimeout の値が60になっていることを確認)】
aws sqs get-queue-attributes \
--queue-url ${SQS_QUEUE_URL} \
--attribute-names ${SQS_QUEUE_ATTRIBUTE_NAME} \
--query "Attributes.${SQS_QUEUE_ATTRIBUTE_NAME}" \
--output text
(マネジメントコンソール:可視性タイムアウトが1分になっている)
2. メッセージの送受信
2.1.キューへのメッセージ送信
【メッセージ送信】
aws sqs send-message \
--queue-url "${SQS_QUEUE_URL}" \
--message-body "${SQS_MESSAGE_BODY}"
【メッセージ数の確認】
aws sqs get-queue-attributes \
--queue-url ${SQS_QUEUE_URL} \
--attribute-names ApproximateNumberOfMessages \
--query 'Attributes.ApproximateNumberOfMessages' \
--output text
(マネジメントコンソール:利用可能なメッセージが1になっている)
2.2.キューからのメッセージ受信
【メッセージ一時格納用ディレクトリの作成】
mkdir -p ${HOME}/environment/tmp-handson-cli-sqs
【メッセージ一時格納用ファイルの作成】
FILE_SQS_MESSAGE="${DIR_SQS_MESSAGE}/$(date +%Y-%m-%d)-${SQS_QUEUE_NAME}.json"
※メモ
「$(date +%Y-%m-%d)」により、「2020-05-20」を出力する。
【メッセージを受信(+ 一時格納用ファイルに書き込む)】
aws sqs receive-message \
--queue-url "${SQS_QUEUE_URL}" \
> ${FILE_SQS_MESSAGE} \
&& cat ${FILE_SQS_MESSAGE}
※メモ
メッセージの受信により、VisibilityTimeoutで設定された時間、他のコンシューマからファイルが見えなくなる(処理中のメッセージになる)
(マネジメントコンソール:処理中のメッセージが1になっている)
【メッセージボディの取得】
SQS_MESSAGE_BODY=$( \
cat ${FILE_SQS_MESSAGE} \
| jp.py 'Messages[].Body' \
| sed 's/[]\"\[]//g' \
) \
&& echo ${SQS_MESSAGE_BODY}
実際の運用時には、このメッセージボディ(本文)を使って何かしらの処理を行う。
属性情報も使うのかもしれない。
【ReceiptHandleの値を取得する(削除時に使用するため)】
SQS_MESSAGE_RECEIPT_HANDLE=$( \
cat ${FILE_SQS_MESSAGE} \
| jp.py 'Messages[].ReceiptHandle' \
| sed 's/[]\"\[]//g' \
)
※メモ
sedコマンドにより配列のカギカッコを外している。
実際の運用時にはReceiptHandleの値取得は誰がどのような方法で行うのだろう?(宿題)
【メッセージの削除】
aws sqs delete-message \
--queue-url "${SQS_QUEUE_URL}" \
--receipt-handle ${SQS_MESSAGE_RECEIPT_HANDLE}
メッセージ数の確認
前述のsqs get-queue-attributes
を使い、”0”が表示されることを確認。
(マネジメントコンソール:メッセージ数が0になっている)
片付け
【キューの破棄】
aws sqs delete-queue \
--queue-url ${SQS_QUEUE_URL}
【ハンズオン用ディレクトリの削除】
rm -Rf ${HOME}/environment/tmp-handson-cli-sqs
ハンズオンここまで。
SQSについて学んだことを整理
ハンズオン内で学んだことと、追加で調べたことを羅列してみます。
SQS活用により柔軟性を高める
- コンポーネントの間をSQSでつなぐことで、疎結合化する
- 疎結合化することで変化に強くなる(柔軟性を高める)
- SQSは、非同期型、Pull型、P2P型に有効
SQSの構成要素
- プロデューサー
- キューにメッセージを送信するアプリケーション
- 任意のタイミングでメッセージを送信
- コンシューマ
- キューのメッセージを取得するアプリケーション
- 任意のタイミングでメッセージを受信
- メッセージ
- プロデューサーが生成するデータ。最大256KB
- キュー
- メッセージをキューイングする。
- 分散キュー。
- メッセージを最大14日間保持可能
キューの種類
- スタンダードキュー
- ほぼ無限のスループット
- 最低1回の配信。順序はベストエフォート
- ベストエフォート(順序が変わることがある)
- FIFOキュー
- 1秒あたり最大300件のメッセージをサポート
- 1回のみ配信
- 順序性を保つ
SQSを利用する場合、冪等性を確保できるようにアプリケーションを設計する
1回だけ操作を行っても、何回行っても結果が変わらないように設計する
メッセージ取得方法
- ショートポーリング
- 即応答
- 分散されたサーバの中からサンプリングされたサーバのメッセージを応答(全サーバーではないため取得できないこともある)
- APIコール数が増え利用料金が増加する可能性あり
- ロングポーリング
- 最大20秒メッセージの受領を待つ
- メッセージがない場合はタイムアウト
- 全てのサーバをクエリしメッセージを応答
- ショートポーリングに比べAPIコール数が抑制できるため利用料金が安価になる可能性あり
メッセージを取得する際のお作法
- ポーリング
- ロングポーリング or ショートポーリング
- (通常はロングポーリングを使う)
- 取得&処理
- 受信したメッセージを利用して処理
- 削除
- キューに削除を指示
その他、機能詳細
- 可視性タイムアウト
- コンシューマがメッセージを取得後、一定時間メッセージが見れなくなる
- 複数のコンシューマが同時に重複して処理を行うことを避けるため
- 遅延キュー
- プロデューサーがメッセージを送信後、一定時間後にメッセージを見ることができる
- デットレターキュー
- 正常処理できないメッセージが残り続けることを避ける
- サーバーサイド暗号化を利用したメッセージの暗号化
- メッセージを暗号化
- ボディーのみ暗号化、属性は暗号化できない
- KMSの権限も必要
- キューへのアクセス制御
- IAMポリシー、+SQSポリシーで制御
- メッセージ属性
- メッセージ本文とは別にメタデータ等を保持させることができる
- 最大10個
- サイズ上限は256KB
- キューのモニタリング
- CloudWatchの利用によりキューの状態を把握可能
- コンシューマのスケールアウト/インに利用
余談ですが、勉強会中で「SQSが最も古いAWSサービス」ということを知ってビックリでした。
最後まで読んでいただきありがとうございます。