Может ли лямбда-функция AWS вызвать другую
У меня есть 2 лямбда-функции - одна, которая производит кавычку, и одна, которая превращает кавычку в заказ. Я бы хотел, чтобы лямбда-функция Order вызывала функцию Quote для генерации цитаты, а не просто получала ее от ненадежного клиента.
Я искал повсюду, что только мог придумать, но не понимаю, как бы я поработал с цепочкой или вызовом функций... конечно, это существует!
22 ответа
Я нашел способ, используя 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
Вы должны приковать Lambda functions
с помощью SNS
, Такой подход обеспечивает хорошую производительность, задержку и масштабируемость при минимальных усилиях.
Ты первый Lambda
публикует сообщения на ваш SNS Topic
а второй Lambda
подписан на эту тему. Как только сообщения приходят в тему, второй Lambda
выполняется с сообщением в качестве входного параметра.
См. Вызов лямбда-функций с помощью уведомлений Amazon SNS.
Вы также можете использовать этот подход для вызова лямбда-функций кросс-счета через SNS.
Вот пример кода для 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": "*"
}
Поскольку этот вопрос был задан, Amazon выпустила пошаговые функции ( https://aws.amazon.com/step-functions/).
Одним из основных принципов AWS Lambda является то, что вы можете больше сосредоточиться на бизнес-логике, а не на логике приложения, которая связывает все это вместе. Шаговые функции позволяют организовать сложные взаимодействия между функциями без необходимости написания кода для этого.
Это решение сделано с использованием 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
Я смотрел на вырезание SNS, пока не увидел это в документации клиента Lambda (версия Java):
Клиент для доступа к AWS Lambda. Все сервисные вызовы, сделанные с помощью этого клиента, блокируются и не возвращаются, пока сервисный вызов не завершится.
Так что у SNS есть очевидное преимущество: он асинхронный. Ваша лямбда не будет ждать завершения следующей лямбды.
Amazon представила функции шага в AWS lambda в 2016 году. Думаю, теперь удобнее использовать функцию шага, поскольку ее действительно легко использовать. Вы можете построить конечный автомат с двумя лямбда-функциями:
- производить цитату
- превращает цитату в заказ
Вы можете легко сделать это, как показано ниже:
Здесь вы можете иметь первое состояние для создания цитаты, а другое для превращения в порядок
{
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
}
}
}
Функции Steps позволяют легко написать несколько лямбда-функций и выполнять их последовательно или параллельно. Вы можете получить больше информации о функциях лямбда-шагов здесь: Функции шагов
Ответов много, но никто не подчеркивает, что вызов другой лямбда-функции не рекомендуется для синхронных вызовов, а тот, который вы должны использовать, на самом деле является пошаговыми функциями.
Причины, по которым это решение не рекомендуется:
- вы платите за обе функции, когда они ждут друг друга
- ваш код отвечает за повторные попытки
Вы также можете использовать его для довольно сложной логики, такой как параллельные шаги и обнаружение сбоев. При каждом выполнении также происходит выход из системы, что значительно упрощает отладку.
В Java мы можем сделать следующее:
AWSLambdaAsync awsLambdaAsync = AWSLambdaAsyncClientBuilder.standard().withRegion("us-east-1").build();
InvokeRequest invokeRequest = new InvokeRequest();
invokeRequest.withFunctionName("youLambdaFunctionNameToCall").withPayload(payload);
InvokeResult invokeResult = awsLambdaAsync.invoke(invokeRequest);
Здесь полезная нагрузка - это ваш строковый java-объект, который необходимо передать как Json-объект другой лямбде, если вам нужно передать некоторую информацию от вызова лямбды к вызываемой лямбде.
Я работал с ответом, предоставленным blueskin, но не смог прочитать ответ Payload, потому что InvocationType='Event' является асинхронным, поэтому я изменил на InvocationType='RequestResponse' и теперь все работает хорошо.
Другие указали на использование SQS и Step Functions. Но оба эти решения добавляют дополнительную стоимость. Предполагается, что переходы между состояниями пошаговой функции очень дороги.
AWS lambda предлагает некоторую логику повтора. Где пробует что-то 3 раза. Я не уверен, действительно ли это, когда вы запускаете его с помощью API.
Возможно, вы сможете использовать функцию водопада Async.js - см. Пример нижней части большого фрагмента кода в шаге 3 этого документа:
https://aws.amazon.com/blogs/compute/better-together-amazon-ecs-and-aws-lambda/
Вот пример Python для вызова другой лямбда-функции и получения ее ответа. Существует два типа вызова : 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)
Вы можете вызвать лямбда-функцию напрямую (по крайней мере, через Java), используя AWSLambdaClient
как описано в сообщении в блоге AWS.
Вот как вы можете сделать это в javascript/typescript без установки полного пакета aws-sdk.
import { InvokeCommand, LambdaClient, LogType } from "@aws-sdk/client-lambda";
const client = new LambdaClient({
region: "US-EAST-1"
});
const payload = JSON.stringify({
data: "your input"
})
const command = new InvokeCommand({
FunctionName: "your function name",
Payload: payload,
LogType: LogType.Tail,
});
const { Payload } = await client.send(command);
const response: any = Payload;
const result = Buffer.from(response).toString();
return result;
У меня та же проблема, но реализованная мной функция Lambda вставит запись в DynamoDB, поэтому мое решение использует триггеры DynamoDB.
Я заставляю БД вызывать функцию Lambda для каждой вставки / обновления в таблице, так что это разделяет реализацию двух функций 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/
Что-то вроде обходного решения, но я просто вызываю конечную точку API для моих лямбда-функций, когда мне нужно их связать. Это позволяет вам при кодировании решить, хотите ли вы, чтобы они были асинхронными или нет.
Если вы не хотите устанавливать запрос POST, вы можете просто настроить простой запрос 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
Вы можете запускать лямбда-функции непосредственно из других лямбда-функций асинхронным способом.
https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html#invocation-async-destinations
Может ли функция AWS Lambda вызывать другой простой код C# ---
InvokeRequest RebookingLambdalambda = new InvokeRequest
{
FunctionName = "Name"
InvocationType = InvocationType.RequestResponse,
Payload = "Json Data"
};
Вызов другой функции из одной функции меньше рассматривается как антипаттерн на сервере. Это хорошо объяснено здесь .
Лучшей реализацией является либо использование очереди для публикации сообщения и его использования в другой лямбде, либо использование пошаговой функции, как описано Блэком .
если вы хотите использовать лямбда-функцию, зависящую от другой лямбда-функции. вы можете использовать [Конечный автомат] https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-state-machine-structure.html , это поможет вам запустить лямбда-функцию в последовательности или на основе результата другой лямбда-функции. Это также позволяет вам интегрировать другие сервисы AWS.
Вы можете установить среду 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();