EatSmartシステム部ブログ

ウェブサイトの開発や運営に関する情報です。

AWS Lambda で非同期に処理を実行する

先日、AWSを利用した開発を経験することが出来ました。

Lambda関数を利用してAPIを実装していますが、時間のかかる処理を分離する必要がでてきました。 どのような方法があるのか調査したところ、方法を2つ知ることが出来たので、書き残したいと思います。

Amazon SQS を利用する

Amazon SQS とは、メッセージキューイングサービスです。 処理したい内容をキューへ登録しておき、「Lambdaトリガ」へ処理を実行するLambda関数を指定します。

APIは以下のように、SQSへメッセージを送信します。

const AWS = require('aws-sdk');
AWS.config.update({region: 'REGION'});
const SQS = new AWS.SQS();
const MessageBody = JSON.stringify([{"key": "A"}, {"key": "B"}])
const QueueUrl = 'https://sqs.ap-northeast-1.amazonaws.com/xxxx/yyyy';
const result = await SQS.sendMessage({ MessageBody, QueueUrl }).promise()

トリガに指定されたLambda関数は、以下のようにeventからメッセージを取り出すことが出来ます。

exports.handler = async (event) => {
  const datas = [];
  for (let i = 0; i < event.Records.length; i++) {
    const record = event.Records[i];
    let json = JSON.parse(record.body);
    for (let j = 0; j < json.length; j++) {
      datas.push(json[j]);   
    }
  }
  console.log('datas->', datas);
  ....
};

Lambda関数を非同期実行する

Lambda関数からLambda関数を呼び出すことが出来ます。 今回は非同期で処理したいので、InvocationTypeに"Event"を指定しました。

const AWS = require('aws-sdk');
const lambda = new AWS.Lambda();
const params = {
  FunctionName: "[非同期実行するLambda関数名]",
  InvocationType: "Event",
  Payload: JSON.stringify([{"key": "A"}, {"key": "B"}])
}
await lambda.invoke(params).promise();

非同期で実行されたLambda関数は、eventからPayloadで指定した値を取り出すことが出来ます。

exports.handler = async (event) => {
  const datas = [];
  for (let i = 0; i < event.length; i++) {
    datas.push(event[i]);
  }
  console.log('datas->', datas);
  ....
};

VPCを設定したLambda関数で実行する方法

いずれの方法も、VPCを設定したLambda関数で実行するとタイムアウトが発生します。 その場合、VPCエンドポイントを利用することで、実行することができるようになります。

エンドポイントの作成から、SQS用はサービス名に「com.amazonaws.ap-northeast-1.sqs」を、Lambda関数用はサービス名に「com.amazonaws.ap-northeast-1.sqs」を指定し、必要なサブネットの設定を行うことで利用出来ました。