# AWS再入門ブログリレー SQS編
こんにちは、コンサルティング部 もこ@札幌オフィス です！
当エントリは弊社コンサルティング部による『AWS再入門ブログリレー 2019』の22日目のエントリです。
このブログリレーの企画は、普段AWSサービスについて最新のネタ・深い/細かいテーマを主に書き連ねてきたメンバーの手によって、 今一度初心に返って、基本的な部分を見つめ直してみよう、解説してみようというコンセプトが含まれています。
AWSをこれから学ぼう！という方にとっては文字通りの入門記事として、またすでにAWSを活用されている方にとってもAWSサービスの再発見や2019年のサービスアップデートのキャッチアップの場となればと考えておりますので、ぜひ最後までお付合い頂ければ幸いです。
本日22日目のテーマは『Amazon Simple Queue Service』です。
## 目次
- 目次
- Amazon Simple Queue Service(SQS)とは？
- SQSのタイプ
- SQSのライフサイクル
- SQSを使ってアプリケーションを作ってみた
- (レジ) ハンバーガーの注文を受け付ける
- (厨房) ハンバーガーの注文を処理する
- まとめ
## Amazon Simple Queue Service(SQS)とは？
Amazon Simple Queue Service(以下SQS)はフルマネージド型のメッセージキューサービスです。
「メッセージをSQSの送信」、「SQSからメッセージをポーリング」することができ、SQSを利用することによって
- 軽い受付処理をした結果をSQSに登録し、別のサーバーからメッセージをポーリングし、重い処理を済ませる
-
SQS側で処理予定のタスクをバッファーでき、スパイク的なアクセスに耐えれる構成を作成できる
SQSに登録されているキューに基づいてSQSをポーリングし、処理を行うサーバーをスケールする事ができる
SQSをトリガーにLambdaをキックし、サーバーレスが捗る
などなどで、お店で例えて言うと
「注文はチーズバーガー→お会計130円です→チーズバーガーを作成→チーズバーガーを返す」
ような同期的なアプリケーションを
「レジ側: 注文はチーズバーガー→お会計130円です(SQSにキューを登録)」
「厨房側: SQSをポーリング、チーズバーガーを作成、チーズバーガーを返す」
のように、レジと厨房を非同期で処理できるため、レジでは注文と会計のみの仕事に集中もできますし、何よりチーズバーガーを作る作業は厨房に丸投げするため、お客様にも待たさずに次々と注文を受け付けられます。
また、キューの量をトリガーにスケールすることも可能です。
### 前提知識
メッセージをSQSに送信するアプリケーションのことを「プロデューサー」と呼び、
SQSからメッセージをポーリングするアプリケーションのことを「コンシューマー」と呼びます。
SQSに送信できる最大256KBのメッセージを送信でき、SQS側での最長保持期間は14日です。
## SQSのタイプ
SQSには２つの種類があり、「標準キュー」、「FIFOキュー」があります。
### 標準キュー
「順不同な可能性がある」、「複数回配信される可能背がある」、「ほぼ無制限に送信ができる」、標準的なキューです。
のように順不同で配信される可能性があり、同じメッセージを複数回配信される可能性があります。
複数回同じメッセージを受け取っても悪影響が出ないよう、DynamoDBなどを利用して重複が無いようにする必要があります。
### FIFOキュー
「順番配信」、「重複キューの削除」、「一回だけの配信」、「1秒に送信できるキューに制限がある」キューです。
つまり、
となり、DynamoDBなどを利用して重複処理を回避する必要もなくなります！
#### FIFOキューの制限
SendMessageBatch、DeleteMessageBatch、ChangeMessageVisibilityBatchを利用すると最大 3000 Message/sとなります。
(SendMessageBatchなどのBatch系では最大10件のメッセージを一つのリクエストで送信することができます)
また、FIFOキューではLambda, SNSなどの連携をサポートしていないため、利用する場合は標準キューを利用する必要があります。
## SQSのライフサイクル
SQSには主に「可視性タイムアウト」、「メッセージ保持期間」の設定があります。
可視性タイムアウトは、「コンシューマーがメッセージを受信してから可視性タイムアウトの間、他のコンシューマーなどにキューを配信しない」ものです。
メッセージ保持期間は「SQSにメッセージ保持する期間」で、SQSに登録されてから処理されずにSQSに溜まったメッセージが削除されるまでの期間です。
## SQSを使ってアプリケーションを作ってみた
ここまでSQSについて紹介しましたが、実際に使ってみないとよくわからないと思います。
実際にSQSを利用し、「ハンバーガーの注文を受け、厨房で作成する」ものを作ってみたいと思います。
## (レジ) ハンバーガーの注文を受け付ける
## (厨房) ハンバーガーの注文を処理する
//@ts-check const AWS = require("aws-sdk"); const sqs = new AWS.SQS({ region: "ap-northeast-1" }); const QueueUrl = " const receiveMessage = QueueUrl => new Promise((resolve, reject) => { const params = { QueueUrl, MaxNumberOfMessages: 10, WaitTimeSeconds: 10 }; sqs.receiveMessage(params, (err, data) => { if (err || !data.Messages) return reject(err); return resolve(data); }); }); const deleteMessage = (ReceiptHandle, QueueUrl) => { const params = { QueueUrl, ReceiptHandle }; sqs.deleteMessage(params, (err, data) => { if (err) return console.error(err); console.log("delete queue"); console.log(data); }); }; const createBurger = burger => new Promise(resolve => { setTimeout(() => resolve("?"), 0); }); async function main() { const messageids = []; while (true) { const data = await receiveMessage(QueueUrl).catch(console.error); if (!data) continue; for (const message of data.Messages) { // すでに処理済みだったらスキップする // DynamoDBなどを利用するといい感じにできます。 if (messageids.includes(message.MessageId)) return; // ハンバーガーを作る const order = JSON.parse(message.Body); // 重い処理 console.log(order.burger) const result = await createBurger(order.burger); console.log(result) messageids.push(message.MessageId); deleteMessage(message.ReceiptHandle, QueueUrl); } } } main();
標準SQSを利用しているため、実際に利用する場合はDynamoDBを使うなどで受信側で重複を回避する必要があるので、注意が必要です。
## まとめ
このように、SQSを利用すると簡単にサービスを分離することができ、AWS側にキューの処理などをまるまる任せられるので、とても便利です！
今回の「AWS再入門ブログリレー」もおかげさまで非常に皆様の高評価を戴いた企画となりました。ご支持戴き誠にありがとうございました！
本リレーを通してAWSのたくさんある様々なサービスに再入門できたなら幸いです！