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」を指定し、必要なサブネットの設定を行うことで利用出来ました。