web-dev-qa-db-ja.com

botoを使用してラムダ関数を呼び出す方法

SOを使用してラムダ関数を呼び出し、バックエンドをテストしています。それらを非同期に呼び出したいです。 「invoke_async」は非推奨であり、使用しないでください。代わりに、InvocationTypeを「Event」に設定した「invoke」を使用して、関数を非同期に実行する必要があります。

しかし、関数が戻ったときに関数から応答を取得する方法を理解できないようです。私は次を試しました:

payload3=b"""{
"latitude": 39.5732160891,
"longitude": -119.672918997,
"radius": 100
}"""

client = boto3.client('lambda')
for x in range (0, 5):
    response = client.invoke(
        FunctionName="loadSpotsAroundPoint",
        InvocationType='Event',
        Payload=payload3
    )
    time.sleep(15)
    print(json.loads(response['Payload'].read()))
    print("\n")

コードを15秒間スリープするように指定しても、応答変数は印刷しようとしても空です。呼び出しInvokationTypeを「RequestResponse」に変更すると、すべて正常に動作し、応答変数が出力されますが、これは同期です。簡単なものが足りませんか?非同期呼び出しが返されたときに、結果を出力するなど、いくつかのコードを実行するにはどうすればよいですか?

ありがとう。

21

非同期に実行されたAWS Lambda関数は、実行結果を返しません。非同期呼び出しリクエストが成功した場合(つまり、アクセス許可などによるエラーがなかった場合)、AWS LambdaはすぐにHTTPステータスコード 202 ACCEPTED を返し、この非同期呼び出し。

AWS Lambda Invoke action のドキュメントから:

応答構文

HTTP/1.1 StatusCode
X-Amz-Function-Error: FunctionError
X-Amz-Log-Result: LogResult

Payload

応答要素

アクションが成功すると、サービスは次のHTTP応答を送り返します。

StatusCode

HTTPステータスコードは、リクエストが成功した場合、200の範囲になります。 RequestResponse呼び出しタイプの場合、このステータスコードは200です。Event呼び出しタイプの場合、このステータスコードは202DryRun呼び出しタイプの場合、ステータスコードは204になります。

[...]

応答は、HTTP本文として次を返します。

ペイロード

Lambda関数によって返されるオブジェクトのJSON表現です。 これは、呼び出しタイプがRequestResponseの場合にのみ存在します。

13
Leon

'async AWS lambda invocation' 'async python code'には違いがあります。 InvocationType'Event'に設定すると、 定義により になり、応答が返されなくなります。

あなたの例では、invoke()はすぐにNoneを返し、後で値を変更するために暗黙的にバックグラウンドで何かを起動しません(ありがとうございます!)。したがって、15秒後にresponseの値を見ると、_Noneのままです。

非同期のPythonコードを持つRequestResponse呼び出しタイプが本当に必要なようです。選択肢はたくさんありますが、私のお気に入りは concurrent.futures です。もう1つは threading です。

concurrent.futuresを使用した例を次に示します。

(Python2を使用している場合、pip install futuresが必要です)

from concurrent.futures import ThreadPoolExecutor
import json

payload = {...}

with ThreadPoolExecutor(max_workers=5) as executor:
    futs = []
    for x in xrange(0, 5):
        futs.append(
            executor.submit(client.invoke,
                FunctionName   = "loadSpotsAroundPoint",
                InvocationType = "RequestResponse",
                Payload        = bytes(json.dumps(payload))
            )
        )
    results = [ fut.result() for fut in futs ]

print results

検討したいもう1つのパターンは、Event呼び出しタイプを使用し、Lambda関数がメッセージをSNSにプッシュし、それが別のLambda関数によって消費されるようにすることです。 SNSトリガーラムダ関数 here のチュートリアルをご覧ください。

18
Julien