• トップ
  • ブログ一覧
  • LocalStackを使ってファンアウトしてみた
  • LocalStackを使ってファンアウトしてみた

    はじめに

    先日業務でLocalStackを使ってSNS/SQSを利用したファンアウト構成の動作検証を実施しまして、その際に得た備忘録です.

    単語の整理

    LocalStack

    AWSのエミュレータでローカルマシンにAWSテスト実行環境を構築できちゃう素敵なツール/サービス.

    https://localstack.cloud/

    ※ 以前ハクさん書いた素敵記事にも記載されてます. 併せてどーぞ.

    featureImg2023.06.16【macOS】LocalStack+terraformでEC2+RDSを立ててみた注意LocalStackのPro版(有料版)のAPIキーが必要Pro版の体験版(14日間)があるので、そちらを使用して...

    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で受け取ったペイロードにメッセージ意外の属性情報が付与される.

    動作確認する

    トピックへメッセージ送信し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 でしてみましたが、公式マスコットがかわいすぎる.

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background