AWS関連

【AWS】CLIを使ってSQS操作

今回は以前参加した勉強会『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サービス」ということを知ってビックリでした。

最後まで読んでいただきありがとうございます。