LocalStackを用いたSNSとSQSのファンアウトパターン検証方法 メモ

* LocalStack上で動作するAmazon SNSとAmazon SQSを使用してファンアウトパターンを試したので、メモしておく。

## ファンアウトパターンとは

* 一つの入力に対して複数の出力を接続する設計パターン。

* 複数の処理を並列処理したい場合に利用する。

* Amazon SNS トピックをAmazon SQSキューでサブスクライブする形で構成されることがある。

  ![fanout.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/fa02c7c7-e66a-a39e-9524-d6ba59a70630.png)


## LocalStack準備

* `docker-compose.yml`

  ```yaml
  version: "3.8"
  networks:
    container-link:
      name: docker.internal
  services:
    localstack:
      container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}"
      image: localstack/localstack
      ports:
        - "127.0.0.1:53:53"                # only required for Pro
        - "127.0.0.1:53:53/udp"            # only required for Pro
        - "127.0.0.1:443:443"              # only required for Pro
        - "127.0.0.1:4510-4530:4510-4530"  # only required for Pro
        - "127.0.0.1:4566:4566"
        - "127.0.0.1:4571:4571"
      environment:
        - SERVICES=${SERVICES- }
        - DEBUG=${DEBUG- }
        - DATA_DIR=${DATA_DIR- }
        - LAMBDA_EXECUTOR=${LAMBDA_EXECUTOR- }
        - LOCALSTACK_API_KEY=${LOCALSTACK_API_KEY- }  # only required for Pro
        - HOST_TMP_FOLDER=${TMPDIR:-/tmp/}localstack
        - DOCKER_HOST=unix:///var/run/docker.sock
      volumes:
        - "${TMPDIR:-/tmp}/localstack:/tmp/localstack"
        - "/var/run/docker.sock:/var/run/docker.sock"
      networks:
        - container-link
  ```

* 起動

  ```shell
  docker-compose up
  ```

  

## 動作確認

* 1つのSNSトピックを3つのSQSキューでサブスクライブさせる。

### SNSトピック作成

```shell
# トピック:test-fanout-topic
aws sns create-topic --name test-fanout-topic --endpoint-url http://localhost:4566 --profile localstack 
{
    "TopicArn": "arn:aws:sns:ap-northeast-1:000000000000:test-fanout-topic"
}
```



### SQSキュー作成

* キューを3つ作成する。

```shell
# キュー:test-fanout-queue1
aws sqs create-queue --queue-name test-fanout-queue1 --endpoint-url http://localhost:4566 --profile localstack 
{
    "QueueUrl": "http://localhost:4566/000000000000/test-fanout-queue1"
}

# キュー:test-fanout-queue2
aws sqs create-queue --queue-name test-fanout-queue2 --endpoint-url http://localhost:4566 --profile localstack 
{
    "QueueUrl": "http://localhost:4566/000000000000/test-fanout-queue2"
}

# キュー:test-fanout-queue3
aws sqs create-queue --queue-name test-fanout-queue3 --endpoint-url http://localhost:4566 --profile localstack 
{
    "QueueUrl": "http://localhost:4566/000000000000/test-fanout-queue3"
}
```



### SQSからSNSトピックに対するサブスクライブ設定

```shell
# キュー:test-fanout-queue1のサブスクライブ設定
aws sns subscribe --topic-arn arn:aws:sns:ap-northeast-1:000000000000:test-fanout-topic --protocol sqs --notification-endpoint http://localhost:4566/000000000000/test-fanout-queue1 --endpoint-url=http://localhost:4566 --profile localstack
{
    "SubscriptionArn": "arn:aws:sns:ap-northeast-1:000000000000:test-fanout-topic:c883bc57-1dcb-47a5-a74b-6926302f88db"
}

# キュー:test-fanout-queue2のサブスクライブ設定
aws sns subscribe --topic-arn arn:aws:sns:ap-northeast-1:000000000000:test-fanout-topic --protocol sqs --notification-endpoint http://localhost:4566/000000000000/test-fanout-queue2 --endpoint-url=http://localhost:4566 --profile localstack
{
    "SubscriptionArn": "arn:aws:sns:ap-northeast-1:000000000000:test-fanout-topic:44e79398-c90b-4e77-b132-37bb77b7152e"
}

# キュー:test-fanout-queue3のサブスクライブ設定
aws sns subscribe --topic-arn arn:aws:sns:ap-northeast-1:000000000000:test-fanout-topic --protocol sqs --notification-endpoint http://localhost:4566/000000000000/test-fanout-queue3 --endpoint-url=http://localhost:4566 --profile localstack
{
    "SubscriptionArn": "arn:aws:sns:ap-northeast-1:000000000000:test-fanout-topic:8421bcac-9726-4cc2-9d31-ac0a75f81212"
}
```



### SNSトピックへのメッセージ配信

* "Hello Fanout Pattern"というメッセージとSNSトピック`test-fanout-topic`に対して配信する。

```shell
aws sns publish --topic-arn arn:aws:sns:ap-northeast-1:000000000000:test-fanout-topic --message "Hello Fanout Pattern" --endpoint-url http://localhost:4566 --profile localstack
{
    "MessageId": "91712e1b-c67e-4d30-9ba1-f0372fff0b73"
}
```

### SQSキューでメッセージ確認

※SNSトピックへ配信したメッセージを各キューで受け取れていることがわかる。

```shell
#test-fanout-queue1
aws sqs receive-message --queue-url 'http://localhost:4566/000000000000/test-fanout-queue1' --endpoint-url http://localhost:4566 --profile localstack
{
    "Messages": [
        {
            "MessageId": "6b1af479-0dba-9866-f186-1fe62bcd2aed",
            "ReceiptHandle": "kpmqgrtpkamdehqljgjadtsvoyijpdnuzsckgabebzspjitxqygwlimsttzkoazqfmmzcysupuepacwiuewdwretedegxpbtdddyeraocgtprvcgelqjftjrpqbqjhvcmhundzpgdwaamngsoeakxtxkswhcahgsrpsgxixcfdoldnlrimomsbtcd",
            "MD5OfBody": "cce9d113a86c56f9f5b9855271124d01",
            "Body": "{\"Type\": \"Notification\", \"MessageId\": \"91712e1b-c67e-4d30-9ba1-f0372fff0b73\", \"TopicArn\": \"arn:aws:sns:ap-northeast-1:000000000000:test-fanout-topic\", \"Message\": \"Hello Fanout Pattern\", \"Timestamp\": \"2021-11-02T11:51:16.507Z\", \"SignatureVersion\": \"1\", \"Signature\": \"EXAMPLEpH+..\", \"SigningCertURL\": \"https://sns.us-east-1.amazonaws.com/SimpleNotificationService-0000000000000000000000.pem\"}"
        }
    ]
}

# test-fanout-queue2
aws sqs receive-message --queue-url 'http://localhost:4566/000000000000/test-fanout-queue2' --endpoint-url http://localhost:4566 --profile localstack
{
    "Messages": [
        {
            "MessageId": "8ae41e45-67ee-26ef-af44-df5150e0f65a",
            "ReceiptHandle": "whfwskrunpfadcvljmwkvsokhwniperievwlwpnraltgeyabzzqfvmmnawchscfyheatnwpkvrtyeuknaqmrdkiumocinzkadjvhdxpbdgznbokhxpkxsziifjycnpxssabhzfnzajlotitwgnfvoyipzdkxgtkxoikpmgacfzoxjwhppitjafpfl",
            "MD5OfBody": "10b73b458452f74549f7270ca793f203",
            "Body": "{\"Type\": \"Notification\", \"MessageId\": \"91712e1b-c67e-4d30-9ba1-f0372fff0b73\", \"TopicArn\": \"arn:aws:sns:ap-northeast-1:000000000000:test-fanout-topic\", \"Message\": \"Hello Fanout Pattern\", \"Timestamp\": \"2021-11-02T11:51:16.544Z\", \"SignatureVersion\": \"1\", \"Signature\": \"EXAMPLEpH+..\", \"SigningCertURL\": \"https://sns.us-east-1.amazonaws.com/SimpleNotificationService-0000000000000000000000.pem\"}"
        }
    ]
}

# test-fanout-queue3
aws sqs receive-message --queue-url 'http://localhost:4566/000000000000/test-fanout-queue3' --endpoint-url http://localhost:4566 --profile localstack
{
    "Messages": [
        {
            "MessageId": "59571140-f202-d66b-463c-b4e7f08ecefc",
            "ReceiptHandle": "myfqljrtunmvekzonlpieemugfpazlspgkdlpfgkgbjddtkvauvigfpttyzsotgaycvagdtscrtmtccntdhgabufomnnonpjmgahnbrbibjscidcdmnprazdvkvfyyxsekydxpfzqdwzjlhbncjbffautjuxhldoaxohnqzjnkhtzicnptfputkai",
            "MD5OfBody": "05609b51a112bb4ea1ea0dbca0d25c20",
            "Body": "{\"Type\": \"Notification\", \"MessageId\": \"91712e1b-c67e-4d30-9ba1-f0372fff0b73\", \"TopicArn\": \"arn:aws:sns:ap-northeast-1:000000000000:test-fanout-topic\", \"Message\": \"Hello Fanout Pattern\", \"Timestamp\": \"2021-11-02T11:51:16.576Z\", \"SignatureVersion\": \"1\", \"Signature\": \"EXAMPLEpH+..\", \"SigningCertURL\": \"https://sns.us-east-1.amazonaws.com/SimpleNotificationService-0000000000000000000000.pem\"}"
        }
    ]
}
```



## 参考情報

* [LocalStack SNS To SQS](https://onexlab-io.medium.com/localstack-sns-to-sqs-47a38f33b8f4)