- LocalStack上で動くAWS SQSのキューに対してAWS SAM CLIで動くLambdaからメッセージ送受信を行う方法をメモする。
構成
LocalStack準備
docker-compose.yml
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
- 起動
docker-compose up
SQS準備
キュー作成
aws sqs create-queue --queue-name test-queue --endpoint-url http://localhost:4566 --profile localstack
{
"QueueUrl": "http://localhost:4566/000000000000/test-queue"
}
キューの確認
aws sqs list-queues --endpoint-url http://localhost:4566 --profile localstack
{
"QueueUrls": [
"http://localhost:4566/000000000000/test-queue"
]
}
Lambda準備
Lambda
- ひな形作成
sam init
※ランタイムはPython3.8を選択。
-
template.yml
- Hello World Exampleを利用する。
- POST(メッセージ送信)/GET(メッセージ受信)用に以下修正
Events: SendMessage: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: Path: /message Method: post ReceiveMessage: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: Path: /message Method: get
requrements.txt
requests
boto3
※SQSアクセス用にboto3追加
- Lambda処理(
app.py
)修正
import json
from boto3.session import Session
from datetime import datetime
# SQS 接続設定
session = Session(
aws_access_key_id='dummy',
aws_secret_access_key='dummy',
region_name='ap-northeast-1'
)
client = session.client(
service_name='sqs',
endpoint_url='http://localstack:4566'
)
def lambda_handler(event, context):
# キューURL
queue_url="http://localstack:4566/000000000000/test-queue"
if event["httpMethod"] == "POST":
# メッセージ送信
response = client.send_message(QueueUrl=queue_url, MessageBody=json.dumps(event["body"]))
res = {"MD5OfMessageBody":response["MD5OfMessageBody"],"MessageId":response["MessageId"]}
return {
"statusCode": 200,
"body": json.dumps(res),
}
if event["httpMethod"] == "GET":
# メッセージ受信
response = client.receive_message(QueueUrl=queue_url, MaxNumberOfMessages=1, VisibilityTimeout=60)
# メッセージ削除
for message in response["Messages"]:
client.delete_message(QueueUrl=queue_url, ReceiptHandle=message["ReceiptHandle"])
return {
"statusCode": 200,
"body": json.dumps(response["Messages"][0]),
}
動作確認
- ビルド
sam build
- 実行
sam local start-api --docker-network docker.internal
-
メッセージ送信
- リクエスト
POST /message HTTP/1.1 Host: localhost:3000 Content-Type: application/json Content-Length: 34 { "message":"test message1" }
- レスポンス
{ "MD5OfMessageBody": "65b7b348e7f42918ad0d487de1a20c47", "MessageId": "2cafdcd9-2620-14b4-645a-da15dbddf8b5" }
-
メッセージ受信
- リクエスト
GET /message HTTP/1.1 Host: localhost:3000 Content-Type: application/json
- レスポンス
{ "MessageId": "2cafdcd9-2620-14b4-645a-da15dbddf8b5", "ReceiptHandle": "imvqeantfgqrgtkzhwowwzywsxmtdrakkhjdqkwyybxlevsltiefnfjrmoksniovizimonlkixhdixufzqlmejbmtwcxvwuaintwwojbompbfqjhsmokjtojxdlnxquvqslbrevmrinvzxeymkrcpstcmzrtfzhlclwpmkcuokfqjdahkiqhlxcli", "MD5OfBody": "65b7b348e7f42918ad0d487de1a20c47", "Body": "\"{\\n \\\"message\\\":\\\"test message1\\\"\\n}\"" }