web-dev-qa-db-fra.com

À l'aide de boto pour appeler des fonctions lambda, comment procéder de manière asynchrone?

J'utilise donc boto pour appeler mes fonctions lambda et tester mon backend. Je veux les invoquer de manière asynchrone. J'ai noté que "invoke_async" est obsolète et ne doit pas être utilisé. Au lieu de cela, vous devez utiliser "invoke" avec un InvocationType de "Event" pour effectuer la fonction de manière asynchrone.

Je n'arrive pas à comprendre comment obtenir les réponses des fonctions à leur retour. J'ai essayé ce qui suit:

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")

Même si je dis au code de dormir pendant 15 secondes, la variable de réponse est toujours vide lorsque j'essaie de l'imprimer. Si je change l'invocation InvokationType en "RequestResponse", tout fonctionne bien et les impressions de variables de réponse, mais c'est synchrone. Suis-je en train de manquer quelque chose de facile? Comment puis-je exécuter du code, par exemple imprimer le résultat, lorsque l'invocation asynchrone revient ??

Merci.

21
sometimesiwritecode

Une fonction AWS Lambda exécutée de manière asynchrone ne renvoie pas le résultat de l'exécution. Si une demande d'appel asynchrone aboutit (c.-à-d. Qu'il n'y a pas eu d'erreurs dues aux autorisations, etc.), AWS Lambda renvoie immédiatement le code d'état HTTP 202 ACCEPTED et n'assume aucune autre responsabilité pour la communication d'informations sur le résultat de cette invocation asynchrone.

À partir de la documentation de action AWS Lambda Invoke :

Syntaxe de réponse

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

Payload

Éléments de réponse

Si l'action réussit, le service renvoie la réponse HTTP suivante.

StatusCode

Le code d'état HTTP sera dans la plage 200 pour une demande réussie. Pour le type d'invocation RequestResponse, ce code d'état sera 200. Pour le type d'invocation Event, ce code d'état sera 202 . Pour le type d'appel DryRun, le code d'état sera 204.

[...]

La réponse renvoie ce qui suit en tant que corps HTTP.

Charge utile

Il s'agit de la représentation JSON de l'objet retourné par la fonction Lambda. Ceci n'est présent que si le type d'appel est RequestResponse.

13
Leon

Il existe une différence entre un 'async AWS lambda invocation' et 'async python code' . Lorsque vous définissez InvocationType sur 'Event', par définition , il ne renvoie jamais de réponse.

Dans votre exemple, invoke() renvoie immédiatement None et ne démarre implicitement rien en arrière-plan pour modifier cette valeur ultérieurement (Dieu merci!). Ainsi, lorsque vous regardez la valeur de response 15 secondes plus tard, c'est toujours None.

Il semble que ce que vous voulez vraiment, c'est le type d'appel RequestResponse, avec un code asynchrone Python. Vous avez le choix entre plusieurs options, mais mon préféré est concurrent.futures . Un autre est threading .

Voici un exemple utilisant concurrent.futures:

(Si vous utilisez Python2, vous devrez 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

Un autre modèle que vous voudrez peut-être examiner consiste à utiliser le type d'invocation Event et à envoyer vos messages Push à la fonction Lambda à SNS, qui sont ensuite consommés par une autre fonction Lambda. Vous pouvez consulter un tutoriel pour les fonctions lambda déclenchées par SNS - ici .

18
Julien