LocalStackを使ってファンアウトしてみた
IT技術
はじめに
先日業務でLocalStackを使ってSNS/SQSを利用したファンアウト構成の動作検証を実施しまして、その際に得た備忘録です.
単語の整理
LocalStack
AWSのエミュレータでローカルマシンにAWSテスト実行環境を構築できちゃう素敵なツール/サービス.
※ 以前ハクさん書いた素敵記事にも記載されてます. 併せてどーぞ.
SNS/SQS
AWSのメッセージングサービス.
SNSはプッシュ通知やSMS(ショートメッセージサービス)通知で利用される.
SQSはキューイングサービスです.
※ メッセージングサービスはシステム間/コンポーネント間を非同期で通信する方法でマイクロサービスや疎結合な構成でよく利用されます
ファンアウト
メッセージングサービスの構成/パターンの1形態.
ざっくり言うと1箇所でメッセージを受け取りそれを複数箇所に通知するって仕組みです. 広義のブロードキャスト.
ECサイトの商品購入後で例えると 商品を購入した をトリガーに サンクスメール送信、外部システム連携、分析用データ登録 などを非同期に実施する仕組みとなります.
- それ何がうれしーの ?
- 複数箇所で同じメッセージを元に異なる処理を非同期/並行に実施できる → パフォーマンス向上、拡張性向上、依存性の排除などなどが見込める
- 良いことずくしじゃないですか?
- しかし前後の処理や並行処理との間に整合性が求めらる場合は大変になりがち. 運用でどう/どこまでカバーするかなどを調整する/決めるのが大事.
ファンアウトしてみる
ではローカルでファンアウトしてみます.
前提
- docker / docker-compose、awscli を使用します.
- トピックとキューは以下名前で作成. 各キューはトピックをサブスクライブ.
- トピック
- xxx-topic
- キュー
- do-queue
- re-queue
- mi-queue
- トピック
準備
- awscli の プロファイル(LocalStack用)を追加する
1aws configure --profile localstack
2> AWS Access Key ID [None]: dummy
3> AWS Secret Access Key [None]: dummy
4> Default region name [None]: ap-northeast-1
5> Default output format [None]: json
- docker-compose.yml を定義する
- 公式サイト上にdocker-compose.ymlの定義が記載されてまして、それをまるっとコピーしてローカルの任意の場所に配置します.
LocalStackを起動する
作成したdocker-compose.yml と同階層でdockerを起動するだけでツール起動します. 簡単です.
1docker-compose up -d
2> [+] Building 0.0s (0/0) docker:desktop-linux
3> [+] Running 2/2
4> ✔ Network localstack_default Created 0.1s
5> ✔ Container localstack_main Started 0.1s
6
7docker ps
8> CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9> cf72a7b8d031 localstack/localstack "docker-entrypoint.sh" 40 seconds ago Up 38 seconds (healthy) 127.0.0.1:4510-4559->4510-4559/tcp, 127.0.0.1:4566->4566/tcp, 5678/tcp localstack_main
SNSトピックとSQSキューを作成しサブスクライブする
1# トピック作成
2aws sns create-topic --name xxx-topic --endpoint-url http://localhost:4566
3
4# キュー作成
5aws sqs create-queue --queue-name do-queue --endpoint-url http://localhost:4566
6
7aws sqs create-queue --queue-name re-queue --endpoint-url http://localhost:4566
8
9aws sqs create-queue --queue-name mi-queue --endpoint-url http://localhost:4566
10
11# キューのARN取得
12aws sqs get-queue-attributes --queue-url http://localhost:4566/000000000000/do-queue --attribute-names All --endpoint-url http://localhost:4566
13
14# サブスクライブ
15aws sns subscribe --topic-arn arn:aws:sns:ap-northeast-1:000000000000:xxx-topic --protocol sqs --notification-endpoint arn:aws:sqs:ap-northeast-1:000000000000:do-queue --attributes '{"RawMessageDelivery":"true"}' --endpoint-url http://localhost:4566
16
17aws sns subscribe --topic-arn arn:aws:sns:ap-northeast-1:000000000000:xxx-topic --protocol sqs --notification-endpoint arn:aws:sqs:ap-northeast-1:000000000000:re-queue --attributes '{"RawMessageDelivery":"true"}' --endpoint-url http://localhost:4566
18
19aws sns subscribe --topic-arn arn:aws:sns:ap-northeast-1:000000000000:xxx-topic --protocol sqs --notification-endpoint arn:aws:sqs:ap-northeast-1:000000000000:mi-queue --attributes '{"RawMessageDelivery":"true"}' --endpoint-url http://localhost:4566
- 補足
- awscliでLocasStackを操作する場合
--endpoint-url http://localhost:4566
を指定しないとエラーになる - snsはrawメッセージ配信設定
- sns publish時に送信したメッセージのみをsqsへリレーする. これしないとsqsで受け取ったペイロードにメッセージ意外の属性情報が付与される.
- awscliでLocasStackを操作する場合
動作確認する
トピックへメッセージ送信し3つのキューそれぞれにメッセージが届くよね?の確認.
1# SNS Publish
2aws sns publish --topic-arn arn:aws:sns:ap-northeast-1:000000000000:xxx-topic --message 'メッセージ送信.' --endpoint-url http://localhost:4566
do-queue 受信確認
1aws sqs receive-message --queue-url http://localhost:4566/000000000000/do-queue --endpoint-url http://localhost:4566
2
3>{
4> "Messages": [
5> {
6> "MessageId": "96f30a77-8e24-474a-8811-a6403b1c462f",
7> "ReceiptHandle": "NmUxOTVkMzEtYzcxNy00ZjhlLTg1N2EtNWQ0OWFmM2U0MDg3IGFybjphd3M6c3FzOmFwLW5vcnRoZWFzdC0xOjAwMDAwMDAwMDAwMDpkby1xdWV1ZSA5NmYzMGE3Ny04ZTI0LTQ3NGEtODgxMS1hNjQwM2IxYzQ2MmYgMTY5ODI0NjMxNC4yMjg4OA==",
8> "MD5OfBody": "bee88f839d229750a4aa0b3695159ec2",
9> "Body": "メッセージ送信."
10> }
11> ]
12>}
re-queue 受信確認
1aws sqs receive-message --queue-url http://localhost:4566/000000000000/re-queue --endpoint-url http://localhost:4566
2
3>{
4> "Messages": [
5> {
6> "MessageId": "1b6f1665-c3d0-42c1-bb0c-a9e26de5984f",
7> "ReceiptHandle": "ZGZkZWNhMzEtY2I0YS00MDFhLWJjMjAtMzBhYTg4NWY1YTE4IGFybjphd3M6c3FzOmFwLW5vcnRoZWFzdC0xOjAwMDAwMDAwMDAwMDpyZS1xdWV1ZSAxYjZmMTY2NS1jM2QwLTQyYzEtYmIwYy1hOWUyNmRlNTk4NGYgMTY5ODI0NjQyMC4yOTIyNTk3",
8> "MD5OfBody": "bee88f839d229750a4aa0b3695159ec2",
9> "Body": "メッセージ送信."
10> }
11> ]
12>}
mi-queue 受信確認
1aws sqs receive-message --queue-url http://localhost:4566/000000000000/mi-queue --max-number-of-messages 5 --endpoint-url http://localhost:4566
2
3>{
4> "Messages": [
5> {
6> "MessageId": "ddd18572-3025-47f3-99f6-157ec893efe5",
7> "ReceiptHandle": "N2EzODZhMWUtNjNlNy00OGE3LTkyODQtZTRkOGQwNGZmMmZmIGFybjphd3M6c3FzOmFwLW5vcnRoZWFzdC0xOjAwMDAwMDAwMDAwMDptaS1xdWV1ZSBkZGQxODU3Mi0zMDI1LTQ3ZjMtOTlmNi0xNTdlYzg5M2VmZTUgMTY5ODI0NjQ3Ny42NjQ3NDk5",
8> "MD5OfBody": "bee88f839d229750a4aa0b3695159ec2",
9> "Body": "メッセージ送信."
10> }
11> ]
12>}
おけー、できました.
まとめ
AWSのSNS/SQSを利用したファンアウト構成を非常に簡単にローカルで試すことができました. 興味ある方は是非やってみてください.
延長戦
上記だけだとちょっとつまらないのでプログラムで実際にキューを刈り取ってみるサンプル作ってみました.
みんな大好きpython、js/ts、phpの3つで (TIOBE Index (2023年10月時点)のLL言語上位3つだったのは偶然).
- 仕様
- sns/sqs は上記のを使用する.
- awscliでsnsトピックへメッセージを送る.
- 各プログラムでキューを刈り取り、メッセージをコンソール出力する、ただそれだけ.
で、作ってみたのがコチラ となります. 興味あるかたはどーぞ.
おまけ
- どの言語も同じような書き方でメッセージを受け取れました. まぁですよね.
- 単にキューを刈り取ってキューを削除しただけです. ほんとはもっと色々考慮が必要(デッドレターキューとかリトライとかなにやかや...).
- 全てタイマー処理設定してます(1秒おきに刈り取り). これ設定しないとPCのファンがファンファンしちゃいまして. ファンアウトだけに.
- jsのランタイムは Bun でしてみましたが、公式マスコットがかわいすぎる.
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ