¿Puede una función AWS Lambda llamar a otra?

320

Tengo 2 funciones Lambda: una que produce una cotización y otra que convierte una cotización en un pedido. Me gustaría que la función Lambda de pedido llame a la función de presupuesto para regenerar el presupuesto, en lugar de recibirlo de un cliente no confiable.

He buscado en todas partes, pero no puedo ver cómo encadenaría o llamaría a las funciones ... ¡seguramente esto existe!

Plata
fuente
1
Estoy llegando aquí, pero ¿por qué no podría depender del SDK de AWS JavaScript en la primera función Lambda, crear un cliente AWS.Lambda e invocar la segunda función?
devonlazarus
Es lo que iba a intentar, pero no estaba completamente seguro de cómo hacerlo, ya que no había ejemplos de hacerlo desde otra función de Lambda.
Plata
1
aparentemente también puede invocar una función Lambda a través de HTTP .
devonlazarus
44
y una idea más, podría encadenarlos a través de SNS , que es probablemente la forma en que yo seguiría como una estrategia más escalable
devonlazarus
66
Otras alternativas comunes que no se mencionan aquí son Step Functions o SWF.
lebryant

Respuestas:

365

Encontré una manera de usar el 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)
  }
});

Puede encontrar el documento aquí: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html

Nicolas Grenié
fuente
28
El uso de SNS es probablemente el mejor enfoque, pero esta es la respuesta correcta.
Plata
29
podría estar equivocado, pero creo que debido a que la invocación es sincrónica, la primera lambda espera a que termine la segunda lambda, por lo tanto, acumulará cargos mientras ambas lambdas se están ejecutando. usando SNS, la primera lambda debe terminar y permitir que la segunda lambda se ejecute independientemente.
dev
81
Pude hacer que esto funcionara gracias al InvocationType: 'Event'parámetro (agréguelo después FunctionNamey Payload). De los documentos: "Opcionalmente, puede solicitar la ejecución asincrónica especificando Event como InvocationType". Con la ejecución asíncrona, la función de devolución de llamada se llamará de manera confiable, pero sin tener que esperar a que la lambda invocada termine de ejecutarse.
Alessandro
25
Tenga en cuenta que el rol de la función lambda que llama debe incluir la política de IAM AWSLambdaRole. O bien, puede agregar el siguiente objeto de declaración a la política existente de su rol: '{"Efecto": "Permitir", "Acción": ["lambda: InvokeFunction"], "Recurso": ["*"]} `
Bob Arlof 01 de
44
En realidad, AWS lanzó StepFunctions que le permite llamar a múltiples lambda sin tener que invocar una lambda desde otra lambda, por lo que, por ejemplo. el primero no "espera" a que termine el segundo
Sebastien H.
116

Deberías encadenar tu Lambda functionsvía SNS. Este enfoque proporciona buen rendimiento, latencia y escalabilidad para un esfuerzo mínimo.

El primero Lambdapublica mensajes para usted SNS Topicy el segundo Lambdase suscribe a este tema. Tan pronto como los mensajes llegan al tema, el segundo Lambdase ejecuta con el mensaje como parámetro de entrada.

Consulte Invocación de funciones de Lambda mediante notificaciones de Amazon SNS .

También puede usar este enfoque para invocar funciones Lambda de cuenta cruzada a través de SNS .

kixorz
fuente
2
Kinesis puede ser un poco más complicado, pero si está buscando una solución más robusta, puede ser una buena opción para usted. Además, SNS no almacena los eventos entrantes, Kinesis sí.
kixorz
77
"Debe encadenar sus funciones de Lambda a través de SNS". ¿Puede respaldar esto con evidencia / enlaces a documentos? Veo cómo funcionarían ambos métodos, me interesaría ver algunas opiniones / declaraciones definitivas sobre cuál es la preferida
Claude
30
Esta es una buena idea si necesita que sea asíncrona. Pero si su primera función lambda necesita el valor devuelto de la segunda lambda, debe encadenar las lambdas y hacer que la primera función lambda invoque la segunda función lambda directamente.
Noel Llevares
3
No recomendaría usar SNS. Puede utilizar la API de invocación asincrónica para la función lambda; no hay razón para usar SNS a menos que desee notificar a varios suscriptores y no solo desencadenar otra función lambda.
66
Tenga en cuenta que SNS no tiene garantía de entrega, por lo que podría enviar el mensaje pero podría no llegar.
Bart Van Remortele
79

Aquí hay un código de muestra para 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)

Por cierto, también necesitarías agregar una política como esta a tu rol lambda

   {
        "Sid": "Stmt1234567890",
        "Effect": "Allow",
        "Action": [
            "lambda:InvokeFunction"
        ],
        "Resource": "*"
    }
piel azul
fuente
La documentación parece sugerir que la carga útil debe ser JSON. ¿Es posible enviar datos binarios?
mbatchkarov
2
También prefiero este método, pero tiene un problema técnico. Tendrá que convertirlo datetime.now()en una cadena (o manejarlo de alguna manera). De lo contrario, obtendrá el errordatetime.datetime(2017, 9, 11, 14, 40, 53, 23834) is not JSON serializable
John C
¿Es posible ser más restrictivo en el papel de la primera lambda? Es decir, ¿limitarlo a invocar funciones específicas , en lugar de cualquiera y todas?
Phil
@Phil tal vez el campo "Recurso" se puede configurar para permitir solo un conjunto específico de funciones, aunque no estoy completamente seguro
blueskin
2
El InvocationTypedebe ser: RequestResponse. Para obtener la respuesta de la lambda que está intentando invocar.
ambigus9
31

Desde que se hizo esta pregunta, Amazon ha lanzado Step Functions ( https://aws.amazon.com/step-functions/ ).

Uno de los principios fundamentales de AWS Lambda es que puede centrarse más en la lógica empresarial y menos en la lógica de la aplicación que lo une todo. Las funciones de paso le permiten organizar interacciones complejas entre funciones sin tener que escribir el código para hacerlo.

dustinnoe
fuente
12

Esta solución se realiza usando boto3 y 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
Trilok Nagvenkar
fuente
2
Tipo de invocación Elija entre las siguientes opciones. RequestResponse (predeterminado): invoca la función sincrónicamente. Mantenga la conexión abierta hasta que la función devuelva una respuesta o se agote el tiempo de espera. Evento: invoque la función de forma asincrónica. Envíe eventos que fallan varias veces a la cola de mensajes no entregados de la función (si está configurada). DryRun: valida los valores de los parámetros y verifica que el usuario o rol tenga permiso para invocar la función.
Trilok Nagvenkar
11

Estaba buscando cortar el SNS hasta que vi esto en los documentos del cliente Lambda (versión Java) :

Cliente para acceder a AWS Lambda. Todas las llamadas de servicio realizadas con este cliente están bloqueadas y no se devolverán hasta que finalice la llamada de servicio.

Entonces, SNS tiene una ventaja obvia: es asíncrono. Su lambda no esperará a que se complete la posterior lambda.

Ben Iggulden
fuente
17
InvocationType = 'Evento' lo hace asíncrono. docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/…
Ankit
3
@Ankit esa debería ser la respuesta seleccionada, me engañaron al creer que usar SNS era la única forma de hacer una invocación asincrónica porque nadie respondió con esta información.
@Ankit, ¿conoce algún ejemplo que use InvocationType = 'Event' pero de Java en lugar de JavaScript? Hay un montón de documentación de Java, pero no tantos ejemplos como JavaScript
Talador12
SNS todavía agrega costos por su uso
Sebastien H.
1
@SebastienH. No hay costo para SNS invocando a Lambda. aws.amazon.com/sns/pricing
fabdouglas
8

Amazon ha introducido funciones de pasos en AWS lambda en 2016. Creo que ahora es más conveniente usar la función de pasos, ya que es realmente fácil de usar. Puede construir una máquina de estados con dos funciones lambda como:

  • para producir una cotización
  • convierte una cotización en un pedido

Puede hacerlo fácilmente de la siguiente manera:

Aquí puede tener un primer estado para producir una cotización y otro para convertir en orden

{
  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
    }
  }
}

Las funciones Steps facilitan la escritura de múltiples funciones lambda y su ejecución en secuencia o en paralelo. Puede obtener más información sobre las funciones de pasos lambda aquí: Funciones de pasos

Sunil Kapil
fuente
5

Estaba trabajando con la respuesta proporcionada por blueskin pero no pude leer la respuesta de Carga útil porque InvocationType = 'Event' es asíncrono , así que cambié como InvocationType = 'RequestResponse' y ahora todo funciona bien.

antonio
fuente
5

En java, podemos hacer lo siguiente:

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

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

InvokeResult invokeResult = awsLambdaAsync.invoke(invokeRequest); 

Aquí, la carga útil es su objeto java stringificado que debe pasarse como objeto Json a otro lambda en caso de que necesite pasar alguna información de llamar a lambda a llamar a lambda.

Suyash
fuente
2

Puede invocar la función lambda directamente (por lo menos a través de Java) usando AWSLambdaClientcomo se describe en el blog de AWS' posterior .

Neil
fuente
2

Tengo el mismo problema, pero la función Lambda que implemento insertará una entrada en DynamoDB, por lo que mi solución utiliza activadores de DynamoDB.

Hago que el DB invoque una función Lambda para cada inserción / actualización en la tabla, por lo que esto separa la implementación de dos funciones Lambda.

La documentación está aquí: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.Lambda.html

Aquí hay un tutorial guiado: https://aws.amazon.com/blogs/aws/dynamodb-update-triggers-streams-lambda-cross-region-replication-app/

Lewen
fuente
1

Es una solución indirecta, pero solo llamo al punto final de la API para mis funciones lambda cuando necesito encadenarlas. Esto le permite decidir mientras codifica si desea que sean asíncronos o no.

En caso de que no desee configurar una solicitud POST, puede configurar una solicitud GET simple con un par, o ninguno, de parámetros de cadena de consulta para pasar el evento fácilmente.

- Editar -

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

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

Anselmo
fuente
1
esto parece mucho menos indirecto que el SNS, pero no tengo mucha experiencia en el uso del SNS
Brandon
¿Puedes compartir el código necesario para llamar a un punto final API desde una lambda?
Glenn
@Glenn es solo una solicitud de ajax. Etiquete los parámetros que necesita como parámetros de consulta. Ver: docs.aws.amazon.com/apigateway/api-reference/… y docs.aws.amazon.com/lambda/latest/dg/…
Anselm
44
Otro problema es que pasar por API Gateway es relativamente costoso en comparación con llamar a otra función Lambda. Una función de 128 MB que se ejecuta durante 100 ms (el mínimo) cuesta $ 0.21 por 1 millón de llamadas, mientras que API Gateway cuesta $ 3.50 por 1 millón. Obviamente, si está corriendo por más tiempo o usa más ram, tendría que multiplicar los 21 centavos, pero aún así, $ 3.50 por millón es realmente costoso. (Estos precios entraron en vigencia a partir de agosto de 2017)
Patrick Chu
1

Otros señalaron usar SQS y funciones de paso. Pero ambas soluciones agregan un costo adicional. Paso Las transiciones de estado de función son supuestamente muy caras.

AWS lambda ofrece una lógica de reintento. Donde intenta algo por 3 veces. No estoy seguro de si eso todavía es válido cuando lo activa, use la API.

nnrales
fuente
0

Aquí está el ejemplo de Python de llamar a otra función lambda y obtiene su respuesta. Hay dos tipos de invocación 'RequestResponse' y 'Event' . Use 'RequestResponse' si desea obtener la respuesta de la función lambda y use 'Event' para invocar la función lambda de forma asincrónica. Entonces, las dos formas asíncrona y síncrona están disponibles.

    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)
Gangwar lalit
fuente
-1

Puede configurar el entorno 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();
hojin
fuente