ITaws

AWS lambdaでハマったこと (lambdaからlambdaを呼び出す)

これは、実際に同じ状況になってみると、わかりやすいと思います。

exports.handler = function(event, context) {
   非同期処理.then((param) => {
        paramを使用した処理
      結果を返す
   }
}

こうした処理を行う際に、非同期処理の終了を待ち、その結果から、処理をした内容を返して欲しかったのですが、lambdaでは、親プロセスが終了した時点で、子プロセスも強制的に閉じられてしまうらしく、paramが返ってくる前に処理が終わってしまっていました。 例えば、このコード。 通常の実行であれば、ABCが順番に出力されますが、lambdaで実行した場合には、Aしか出力されずに処理が終了してしまいます。

'use strict';

console.log('A');
setTimeout(() => {
    console.log('B');
    setTimeout(() => {
        console.log('C');
    }, 2000);
}, 1000);

それを解決するためにとった策が、lambdaからlambdaを呼ぶことです。

lambdaで関数を作成する

一緒にサンプルを作成していきましょう。 まず、呼び出される側のlambdaを作成します。 今回は、「Hello from Lambda」を出力するlambda関数を作成します。 まず、以下のリンクからAWSマネジメントコンソールへアクセスします。 https://aws.amazon.com/jp/console/ サービス一覧からLambdaを選択し、 関数メニュー から 関数の作成を押下します。 設定は、以下の通りです。

一応、文字でも書いておきます。 関数名: sample ランタイム : Node.js 10.x アクセス権限  実行ロール :  基本的な Lambda アクセス権限で新しいロールを作成 そして、右下にある「関数の作成」ボタンを押下すれば、関数が作成されます。 ※ 少し時間がかかります。10~15秒くらいかな 最初は、以下のような設定になっていると思います。

もし、なっていない方のために貼っておきます。

exports.handler = async (event) => {
    // TODO implement
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};

どのような出力になるか確認してみます。 右上の「テストボタン」を押下し、 テストイベント名に「test」と入力し、保存します。

保存ができたら、もう一度「テスト」ボタンを押下し、実行します。 結果は、以下の通り。

{
  "statusCode": 200,
  "body": ""Hello from Lambda!""
}

これで、Lambda関数の完成です。 今回は、lambdaからlambdaを呼び出すサンプルの作成が目的なので、関数の内容は編集しません。

lambdaからlambdaを呼び出す

まず、先ほどと同じ手順で新たにlambda関数を作成します。 関数名は、「callSample」としましょう。 関数が作成できたら、以下の内容をindex.jsに張り付けます。

const AWS = require('aws-sdk');
const lambda = new AWS.Lambda();
exports.handler = function(event, context) {
	
    const params = {
        FunctionName: 'sample',
        InvocationType: 'RequestResponse',
    };
    lambda.invoke(params, function(err, data) {
        if (err) {
            context.fail(err);
        } else {
            context.succeed(data);
        }
    });
};

このコードで、lambda関数であるsampleを呼び出そうとしています。 実行できるか試してみましょう。 テストを実行します。

"errorType": "AccessDeniedException",

が返されるはずです。 これは、権限が足りていないことを表しています。 もっと詳しく言うと、「callSample」のlambda関数に他のlambda関数(sample)を呼び出すための権限がないということです。

他のlambda関数を呼び出すための権限ロールを作成する

権限ロールを作成するにはIAMを使用します。 マネジメントコンソールからIAMと検索し、開いてみましょう。 左側のメニューからロールを選択し、ロールの作成を押下します。

AWSサービスを選択し、 権限を利用するサービスにLambdaを指定し、 「次のステップ:アクセス権限」を押下します。

ポリシーのフィルタからlambdaと検索し、「AWSLambdaRole」ポリシーをアタッチします。 設定出来たら、「次のステップ:タグ」を押下します。

タグは、今回利用しないので、「次のステップ:確認」を押下。 ロール名に「lambda_execute」と入力し、ロールの作成を押下します。

」 これで、権限ロールが作成されました。

権限を与え、実行してみる

先程作成したLambda関数に戻ります。 (callSample関数の方)

下へスクロールすると、実行ロールという項目があるため、 「既存のロールを使用する」を選択し、 既存のロールに「lambda_execute」を選択し、保存します。 もう一度、テストを実行してみましょう。

{
  "StatusCode": 200,
  "ExecutedVersion": "$LATEST",
  "Payload": "{"statusCode":200,"body":"\"Hello from Lambda!\""}"
}

という結果が返れば、成功です。 もし、

Task timed out after 3.00 seconds

というエラーが返る方いれば、基本設定のタイムアウトを変更してみて下さい。

関連書籍