AWS Lambda関数は別の関数を呼び出すことができますか


320

私には2つのLambda関数があります。1つは見積もりを生成する関数で、もう1つは見積もりを注文に変換する関数です。Order lambda関数で、信頼されていないクライアントから単に受け取るのではなく、Quote関数を呼び出して、見積もりを再生成したいと思います。

私は考えられるあらゆるところを見てきましたが、関数のチェーンや呼び出しをどのように行うのかわかりません...これは確かに存在します!


1
ここに到達しましたが、最初のLambda関数でAWS JavaScript SDKに依存し、AWS.Lambdaクライアントを作成して、2番目の関数を呼び出すことができないのはなぜですか?
devonlazarus

それは私が試そうとしていたことですが、別のLambda関数からそれを行う例がなかったので、どうすればよいか完全にはわかりませんでした。
シルバー

1
どうやらHTTP経由でLambda関数を呼び出すこともできます
devonlazarus 2015

4
そしてもう1つのアイデアは、SNSを介してそれらをチェーンすることです。これはおそらく、よりスケーラブルな戦略として私が行く方法です
devonlazarus '30 / 07/30

6
ここで言及されていないもう1つの一般的な代替手段は、Step FunctionsまたはSWFです。
リブリアント2017年

回答:


365

を使用する方法を見つけましたaws-sdk

var aws = require('aws-sdk');
var lambda = new aws.Lambda({
  region: 'us-west-2' //change to your region
});

lambda.invoke({
  FunctionName: 'name_of_your_lambda_function',
  Payload: JSON.stringify(event, null, 2) // pass params
}, function(error, data) {
  if (error) {
    context.done('error', error);
  }
  if(data.Payload){
   context.succeed(data.Payload)
  }
});

あなたはここでドキュメントを見つけることができます:http : //docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html


28
SNSを使用する方がおそらく良い方法ですが、これが正解です。
シルバー

29
私は間違っている可能性がありますが、最初のラムダが2番目のラムダの終了を待機する呼び出しは同期しているため、両方のラムダの実行中に料金が発生します。SNSを使用すると、最初のラムダが終了し、2番目のラムダが独立して実行できるようになります。
dev

81
InvocationType: 'Event'パラメータのおかげでこれを機能させることができました(FunctionNameandの後に追加してくださいPayload)。ドキュメントから:「必要に応じて、InvocationTypeとしてEventを指定することにより、非同期実行をリクエストできます。」非同期実行では、コールバック関数は確実に呼び出されますが、呼び出されたラムダの実行が完了するのを待つ必要はありません。
アレッサンドロ

25
呼び出し側のラムダ関数の役割にはIAMポリシーを含める必要があることに注意してくださいAWSLambdaRole。または、次のステートメントオブジェクトをロールの既存のポリシーに追加できます: '{"Effect": "Allow"、 "Action":["lambda:InvokeFunction"]、 "Resource":["*"]} `
Bob 2017

4
実際、AWSは、別のラムダからラムダを呼び出す必要なしに複数のラムダを呼び出すことができるようにするStepFunctionsをリリースしました。最初の1つは2番目の1つが終了するまで「待機」しません
Sebastien H.

116

Lambda functionsvia をチェーンする必要がありますSNS。このアプローチは、最小限の労力で優れたパフォーマンス、遅延、およびスケーラビリティを提供します。

最初のLambdaユーザーは自分にメッセージを公開SNS Topicし、2番目のLambdaユーザーはこのトピックにサブスクライブしています。メッセージがトピックに到着するとすぐにLambda、そのメッセージを入力パラメーターとして、second が実行されます。

Amazon SNS通知を使用したLambda関数の呼び出しを参照してください。

このアプローチを使用して、SNS経由でクロスアカウントLambda関数呼び出すこともできます


2
Kinesisはもう少し複雑かもしれませんが、より堅牢なソリューションを検討している場合は、それが適切なオプションになる可能性があります。また、SNSは着信イベントを保存しません。Kinesisは保存します。
kixorz

7
「Lambda関数をSNS経由でチェーンする必要があります」-証拠/ドキュメントへのリンクでこれをサポートできますか?私は両方の方法がどのように機能するかを見て、どちらが好ましいものであるかについての意見/明確な声明を見ることに興味があります
Claude

30
非同期にする必要がある場合は、これは良いアイデアです。ただし、最初のラムダ関数で2番目のラムダからの戻り値が必要な場合は、ラムダをチェーンして、最初のラムダ関数で2番目のラムダ関数を直接呼び出す必要があります。
Noel Llevares、2016

3
SNSの利用はお勧めしません。複数のサブスクライバーに通知して別のラムダ関数をトリガーするだけでなく、SNSを使用する理由がない限り、ラムダ関数の非同期呼び出しAPIを利用できます。

6
SNSには配信が保証されていないため、メッセージを配信してもメッセージが届かない場合があることに注意してください。
Bart Van Remortele 2017

79

これがPythonのサンプルコードです、

from boto3 import client as boto3_client
from datetime import datetime
import json

lambda_client = boto3_client('lambda')

def lambda_handler(event, context):
    msg = {"key":"new_invocation", "at": datetime.now()}
    invoke_response = lambda_client.invoke(FunctionName="another_lambda_",
                                           InvocationType='Event',
                                           Payload=json.dumps(msg))
    print(invoke_response)

ところで、ラムダロールにもこのようなポリシーを追加する必要があります

   {
        "Sid": "Stmt1234567890",
        "Effect": "Allow",
        "Action": [
            "lambda:InvokeFunction"
        ],
        "Resource": "*"
    }

ドキュメントはペイロードがJSONでなければならないことを示唆しているようです。バイナリデータを送ることはできますか?
mbatchkarov 2017

2
私もこの方法を好みますが、1つ問題があります。をdatetime.now()文字列に変換する(または何らかの方法で処理する)必要があります。そうでない場合、エラーが発生しますdatetime.datetime(2017, 9, 11, 14, 40, 53, 23834) is not JSON serializable
John C

最初のラムダの役割をもっと制限することは可能ですか?つまり、それをすべてではなく特定の関数の呼び出しに結び付けるためですか?
Phil

@「多分」「リソース」フィールドは特定の機能のセットのみを許可するように設定できますが、私は完全には
わかり

2
InvocationType次のようになりますRequestResponse。呼び出そうとしているラムダから応答を取得する。
ambigus9 '10 / 09/19

31

この質問があったため、AmazonはStep Functions(https://aws.amazon.com/step-functions/)をリリースしました。

AWS Lambdaの背後にある主要な原則の1つは、ビジネスロジックに集中でき、それをすべて結び付けるアプリケーションロジックに集中できないということです。ステップ関数を使用すると、コードを記述しなくても、関数間の複雑な相互作用を調整できます。


12

このソリューションはboto3とPythonを使用して行われます。

import boto3
import json

invokeLambda = boto3.client('lambda', region_name='eu-west-1')

def lambda_handler(event, context):
    invokeLambda.invoke(FunctionName = 'function_name', InvocationType = 'RequestResponse', Payload = json.dumps(event))

    return True

2
InvocationType次のオプションから選択します。RequestResponse(デフォルト)-関数を同期的に呼び出します。関数が応答を返すか、タイムアウトするまで、接続を開いたままにします。イベント-関数を非同期的に呼び出します。複数回失敗するイベントを関数の配信不能キューに送信します(構成されている場合)。DryRun-パラメータ値を検証し、ユーザーまたはロールに関数を呼び出す権限があることを確認します。
Trilok Nagvenkar

11

Lambdaクライアントのドキュメント(Javaバージョン)でこれが見られるまで、私はSNSの切り取りを検討していました。

AWS Lambdaにアクセスするためのクライアント。このクライアントを使用して行われたすべてのサービス呼び出しはブロックされており、サービス呼び出しが完了するまで戻りません。

したがって、SNSには明らかな利点があります。それは非同期です。ラムダは、後続のラムダが完了するのを待ちません。


17
InvocationType = 'Event'は非同期にします。docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/...
Ankit

3
選択された答えであるはずの@Ankitは、誰もこの情報で答えなかったので、SNSを使用することが非同期呼び出しを行う唯一の方法であると誤解されました。

@AnkitあなたはInvocationType = 'Event'を使用しているがJavaScriptの代わりにJavaの例を知っていますか?
大量

SNSは依然としてその使用にコストを追加します
Sebastien H.

1
@SebastienH。SNSがLambdaを呼び出すのに費用はかかりません。aws.amazon.com/sns/pricing
fabdouglas

8

Amazonは2016年にAWS lambdaにステップ関数を導入しました。今では、ステップ関数を本当に簡単に使用できるので、ステップ関数を使用する方が便利です。次の2つのラムダ関数を使用してステートマシンを構築できます。

  • 見積もりを作成する
  • 見積もりを注文に変える

あなたは以下のようにそれを簡単に行うことができます:

ここでは、最初の状態で見積もりを作成し、別の状態で注文を作成できます

{
  Comment: "Produce a quote and turns into an order",
  StartAt: "ProduceQuote",
  States: {
    ProduceQuote: {
      "Type": Task,
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:ProduceQuote",
      "next": TurnsToOrder
    }
    TurnsToOrder: {
      Type: Task,
      Resource: "arn:aws:lambda:us-east-1:123456789012:function:ProduceQuote",
      end: true
    }
  }
}

ステップ関数を使用すると、複数のラムダ関数を簡単に作成して、シーケンスまたは並列で実行できます。ラムダステップ関数の詳細については、こちらをご覧ください: ステップ関数


5

Blueskinから提供された回答を使用して作業していましたが、InvocationType = 'Event'asyncであるため、ペイロード応答を読み取ることができなかったため、InvocationType = 'RequestResponse'に変更し、すべて正常に機能します。


5

Javaでは、次のようにできます。

AWSLambdaAsync awsLambdaAsync = AWSLambdaAsyncClientBuilder.standard().withRegion("us-east-1").build();

InvokeRequest invokeRequest = new InvokeRequest();
invokeRequest.withFunctionName("youLambdaFunctionNameToCall").withPayload(payload);

InvokeResult invokeResult = awsLambdaAsync.invoke(invokeRequest); 

ここで、payloadは文字列化された javaオブジェクトであり、ラムダの呼び出しからラムダの呼び出しに情報を渡す必要がある場合に備えて、Jsonオブジェクトとして別のラムダに渡す必要があります。



2

AWSLambdaClientAWSのブログ投稿に記載されているように使用して、ラムダ関数を直接(少なくともJava経由で)呼び出すことができます。


2

同じ問題がありますが、実装するLambda関数がDynamoDBにエントリを挿入するため、私のソリューションではDynamoDBトリガーを使用します。

テーブル内のすべての挿入/更新に対してDBにLambda関数を呼び出させるため、これにより2つのLambda関数の実装が分離されます。

ドキュメントはこちら:http : //docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.Lambda.html

これがガイド付きのウォークスルーです:https : //aws.amazon.com/blogs/aws/dynamodb-update-triggers-streams-lambda-cross-region-replication-app/


1

一種のラウンドアバウトソリューションですが、ラムダ関数をチェーンする必要があるときは、ラムダ関数のAPIエンドポイントを呼び出すだけです。これにより、コーディング中に非同期にするかどうかを決定できます。

POSTリクエストを設定したくない場合は、イベントを簡単に渡すために、クエリ文字列パラメーターを2つまたはまったく使用しない単純なGETリクエストを設定できます。

-編集-

参照:https : //docs.aws.amazon.com/apigateway/api-reference/making-http-requests/

および:http : //docs.aws.amazon.com/lambda/latest/dg/with-on-demand-https-example.html


1
これはSNSに比べるとかなり遠回りですが、SNSの使用経験はあまりありません
Brandon

ラムダ内からAPIエンドポイントを呼び出すために必要なコードを共有できますか?
Glenn、

@Glennそれは単なるajaxリクエストです。クエリパラメータとして必要なパラメータにタグを付けます。参照:docs.aws.amazon.com/apigateway/api-reference/...docs.aws.amazon.com/lambda/latest/dg/...
アンセルム

4
別の問題は、API Gatewayを経由することは、別のLambda関数を呼び出すことに比べて比較的コストがかかることです。100ミリ秒(最小)で実行される128 MBの関数のコストは、100万コールあたり0.21ドルですが、API Gatewayは100万ドルあたり3.50ドルです。明らかに、より多くの時間を実行している場合、またはより多くのRAMを使用している場合は、21セントを掛ける必要がありますが、それでも100万ドルあたり3.50ドルは本当に高価です。(これらの価格は2017年8月の時点で有効)
Patrick Chu

1

SQSとステップ関数の使用を指摘する人もいます。ただし、どちらのソリューションも追加のコストがかかります。ステップ関数の状態遷移は、おそらく非常に負荷がかかります。

AWS lambdaは、いくつかの再試行ロジックを提供します。3回何かを試すところ。APIを使用してトリガーしたときに、それがまだ有効かどうかはわかりません。


0

これは、別のラムダ関数を呼び出してその応答を取得するPythonの例です。2つの呼び出しタイプ'RequestResponse''Event'があります。ラムダ関数の応答を取得する場合は「RequestResponse」を使用し、ラムダ関数を非同期に呼び出すには「イベント」を使用します。したがって、非同期と同期の両方の方法が利用できます。

    lambda_response = lambda_client.invoke(
                FunctionName = lambda_name,
                InvocationType = 'RequestResponse',
                Payload = json.dumps(input)
                )
    resp_str = lambda_response['Payload'].read()
    response = json.loads(resp_str)

-1

AWS_REGION環境を設定できます。

assert(process.env.AWS_REGION, 'Missing AWS_REGION env (eg. ap-northeast-1)');
const aws = require('aws-sdk');
const lambda = new aws.Lambda();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.