![[チュートリアル] Amazon SQSメッセージを処理するLambda関数を作成してみた](https://devio2023-media.developers.io/wp-content/uploads/2019/04/amazon-sqs.png)
[チュートリアル] Amazon SQSメッセージを処理するLambda関数を作成してみた
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、CX事業本部 IoT事業部の若槻です。
Amazon SQSは、AWS上で疎結合でスケーラブルなシステムを実装するのに役立つフルマネージド型のメッセージキューイングサービスです。
しかし私は今までAmazon SQSを使う機会がなかなか無く、いい加減触ってみようかなと思っていたところ、ちょうど良さそうなチュートリアルを見つけたので、今回やってみました。
やってみた
やってみたのは、次のAmazon SQSメッセージを処理するLambda関数を作成するチュートリアルです。
実行ロールを作成する
Lambda関数実行用のIAMロールを作成します。
https://console.aws.amazon.com/iam/home#/roles を開き、[ロールの作成]をクリック。

[信頼されたエンティティ]でAWS サービス、[ユースケースの選択]でLambdaを選択し、[次のステップ]をクリック。

AWSLambdaSQSQueueExecutionRoleを選択し、[次のステップ]をクリック。

ちなみにAWSLambdaSQSQueueExecutionRoleのポリシーの概要は次のようになります。Lambda関数がSQSメッセージを読み取り、CloudWatch Logsにログを書き込むためのアクセス許可です。
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "sqs:ReceiveMessage",
        "sqs:DeleteMessage",
        "sqs:GetQueueAttributes",
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "*"
    }
  ]
}
[タグの追加]では何もせずに[次のステップ]をクリック。
[確認]では、[ロール名]でlambda-sqs-roleを指定して、[ロールの作成]をクリック。

作成できました。

関数を作成する
Node.jsランタイムで実行可能なLambda関数のハンドラーコードindex.jsを次の通り作成します。
exports.handler = async function(event, context) {
  event.Records.forEach(record => {
    const { body } = record;
    console.log(body);
  });
  return {};
}
デプロイパッケージを作成します。
$ zip function.zip index.js
AWS CLIのlambda create-functionコマンドを実行してLambda関数を作成します。
$ ACCOUNT_ID=<アカウントID>
$ aws lambda create-function \
  --function-name ProcessSQSRecord \
  --zip-file fileb://function.zip \
  --handler index.handler \
  --runtime nodejs12.x \
  --role arn:aws:iam::${ACCOUNT_ID}:role/lambda-sqs-role
マネジメントコンソールを見るとLambda関数がちゃんと作成されています。

関数をテストする
次のSQSメッセージのレコードを記載したinput.txtファイルを作成します。
{
  "Records": [
    {
      "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
      "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
      "body": "test",
      "attributes": {
          "ApproximateReceiveCount": "1",
          "SentTimestamp": "1545082649183",
          "SenderId": "AIDAIENQZJOLO23YVJ4VO",
          "ApproximateFirstReceiveTimestamp": "1545082649185"
      },
      "messageAttributes": {},
      "md5OfBody": "098f6bcd4621d373cade4e832627b4f6",
      "eventSource": "aws:sqs",
      "eventSourceARN": "arn:aws:sqs:ap-northeast-1:123456789012:my-queue",
      "awsRegion": "ap-northeast-1"
    }
  ]
}
lambda invokeコマンドを次の通り実行します。するとInvalid base64というエラーとなりました。
$ aws lambda invoke \
  --function-name ProcessSQSRecord \
  --payload file://input.txt outputfile.txt
Invalid base64: "{
  "Records": [
    {
      "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
      "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
      "body": "test",
      "attributes": {
          "ApproximateReceiveCount": "1",
          "SentTimestamp": "1545082649183",
          "SenderId": "AIDAIENQZJOLO23YVJ4VO",
          "ApproximateFirstReceiveTimestamp": "1545082649185"
      },
      "messageAttributes": {},
      "md5OfBody": "098f6bcd4621d373cade4e832627b4f6",
      "eventSource": "aws:sqs",
      "eventSourceARN": "arn:aws:sqs:ap-northeast-1:123456789012:my-queue",
      "awsRegion": "ap-northeast-1"
    }
  ]
}
"
なるほどAWS CLI v2を使っている場合はペイロードをBase64エンコードする必要があるんですね。
簡単にまとめれば、バイナリパラメーター(blob)を指定する際にはBase64でエンコードしてね、ということです。lambda invokeの--payloadはblobで指定することになっています。そのためAWS CLI v2ではペイロードをBase64でエンコードする必要があるわけです。それでは実例も交えて確認してみましょう。
作業環境のAWS CLIバージョンを確認するとV2です。なのでBase64エンコードが必要です。
$ aws --version aws-cli/2.0.28 Python/3.7.4 Darwin/20.6.0 botocore/2.0.0dev32
今回はとりあえずの回避策としてマネジメントコンソールからテストをしてみます。

実行できました。関数がSQSのメッセージのレコードを処理できています。

Amazon SQS キュー を作成する
Amazon SQS コンソールを開き、[キューを作成]をクリック。

ここでキューの設定が色々出来るのですが、標準キューで[名前]をMyQueueと指定し、

[キューを作成]をクリック。

キューを作成できました。このキューのARNを控えます。

イベントソースを設定する
先程のARNを指定して、create-event-source-mappingコマンドを次の通り実行します。これによりAmazon SQS キューと Lambda 関数の間イベントソースマッピングを設定します。
$ QUEUE_ARN=<キューのARN>
$ aws lambda create-event-source-mapping \
  --function-name ProcessSQSRecord \
  --batch-size 10 \
  --event-source-arn ${QUEUE_ARN}
動作確認
先程作成したキューの詳細ページで[メッセージを送受信]をクリック。

[メッセージ本文]を指定して、[メッセージを送信]をクリックしキューメッセージを送信します。

Lambda関数のCloudWatch Logsのログイベントを見ると、キューメッセージを受信していることを確認できました!
おわりに
Amazon SQSメッセージを処理するLambda関数を作成するチュートリアルをやってみました。
Amazon SQSに関して今までは認定試験の勉強で仕様や実装パターンを覚えるだけの机上の知識しかありませんでしたが、今回触ってみて何となくの雰囲気がつかめました。
以上






