Может ли лямбда-функция AWS вызвать другую

320

У меня есть 2 лямбда-функции - одна, которая производит кавычку, и одна, которая превращает кавычку в заказ. Я бы хотел, чтобы лямбда-функция Order вызывала функцию Quote для генерации цитаты, а не просто получала ее от ненадежного клиента.

Я искал повсюду, что только мог придумать, но не понимаю, как бы я поработал с цепочкой или вызовом функций ... конечно, это существует!

Серебряный
источник
1
Я подхожу к этому, но почему вы не можете зависеть от AWS JavaScript SDK в первой функции Lambda, создать клиент AWS.Lambda и вызвать вторую функцию?
devonlazarus
Это то, что я собирался попробовать - но я не был полностью уверен, как это сделать, поскольку не было никаких примеров сделать это из другой функции Lambda.
Серебро
1
очевидно, вы также можете вызывать лямбда-функцию через HTTP .
devonlazarus
4
и еще одна идея, вы могли бы связать их через SNS , что, вероятно, я
выбрал
6
Другими распространенными альтернативами, не упомянутыми здесь, являются пошаговые функции или SWF.
17

Ответы:

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
я могу ошибаться, но я думаю, потому что вызов синхронный, так как первая лямбда ожидает окончания второй лямбды, поэтому вы будете накапливать расходы, пока обе лямбды работают. используя SNS, первая лямбда должна завершиться и позволить второй лямбде работать независимо.
Dev
81
Я смог заставить это работать благодаря InvocationType: 'Event'параметру (добавить его после FunctionNameи Payload). Из документов: «При желании вы можете запросить асинхронное выполнение, указав Event в качестве InvocationType». При асинхронном выполнении функция обратного вызова будет вызываться надежно, но без необходимости ждать завершения вызванной лямбды.
Алессандро
25
Обратите внимание, что роль вызывающей лямбда-функции должна включать политику IAM AWSLambdaRole. Или вы можете добавить следующий объект оператора в существующую политику вашей роли: '{"Effect": "Allow", "Action": ["lambda: InvokeFunction"], "Resource": ["*"]} `
Bob Арлоф
4
На самом деле AWS выпустила StepFunctions, которая позволяет вам вызывать несколько лямбда без необходимости вызывать лямбда из другой лямбды, так что для ie. первый не «ждет» второго, чтобы закончить
Себастьен Х.
116

Вы должны связать свой Lambda functionsпуть через SNS. Такой подход обеспечивает хорошую производительность, задержку и масштабируемость при минимальных усилиях.

Ваш первый Lambdaпубликует ваши сообщения, SNS Topicа второй Lambdaподписывается на эту тему. Как только сообщения поступают в тему, Lambdaвыполняется секунда с сообщением в качестве входного параметра.

См. Вызов лямбда-функций с помощью уведомлений Amazon SNS .

Вы также можете использовать этот подход для вызова лямбда-функций кросс-счета через SNS .

kixorz
источник
2
Кинезис может быть немного сложнее, но если вы ищете более надежное решение, то это может быть хорошим вариантом для вас. Кроме того, SNS не хранит входящие события, Kinesis делает.
kixorz
7
«Вы должны связать свои лямбда-функции через SNS» - можете ли вы подтвердить это доказательствами / ссылками на документы? Я вижу, как будут работать оба метода, мне было бы интересно увидеть некоторые мнения / определенные высказывания, по которым один из них предпочтителен
Клод
30
Это хорошая идея, если вам нужно, чтобы она была асинхронной. Но если вашей первой лямбда-функции требуется возвращаемое значение из второй лямбды, вы должны связать лямбда-цепочки и заставить первую лямбда-функцию напрямую вызывать вторую лямбда-функцию.
Ноэль Льеварес
3
Я бы не рекомендовал использовать SNS. Вы можете просто использовать API асинхронного вызова для лямбда-функции - нет причин использовать SNS, если вы не хотите уведомлять нескольких подписчиков, а не просто запускать другую лямбда-функцию.
6
Помните, что у SNS нет гарантии доставки, поэтому вы можете отправить сообщение, но оно может не прийти.
Барт Ван Ремортеле
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": "*"
    }
blueskin
источник
Документация предполагает, что полезная нагрузка должна быть JSON. Можно ли отправить двоичные данные?
mbatchkarov
2
Я тоже предпочитаю этот метод, но у него есть один глюк. Вам нужно будет преобразовать в datetime.now()строку (или обработать как-нибудь). В противном случае вы получите ошибкуdatetime.datetime(2017, 9, 11, 14, 40, 53, 23834) is not JSON serializable
Джон С
Можно ли быть более ограничительным в роли первой лямбды? То есть связать его с вызовом конкретных функций, а не каких-либо и всех?
Фил
@Phil, возможно, поле «Ресурс» может быть настроено так, чтобы разрешить только определенный набор функций, хотя я не совсем уверен
blueskin
2
InvocationTypeДолжно быть: RequestResponse. Чтобы получить ответ от лямбды, которую вы пытаетесь вызвать.
ambigus9
31

Поскольку этот вопрос был задан, Amazon выпустила пошаговые функции ( https://aws.amazon.com/step-functions/ ).

Одним из основных принципов AWS Lambda является то, что вы можете больше сосредоточиться на бизнес-логике и меньше на логике приложения, которая связывает все это вместе. Шаговые функции позволяют организовать сложные взаимодействия между функциями без необходимости написания кода для этого.

dustinnoe
источник
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 - проверка значений параметров и проверка того, что пользователь или роль имеет разрешение на вызов функции.
Трилок Нагвенкар
11

Я смотрел на вырезание SNS, пока не увидел это в документации клиента Lambda (версия Java) :

Клиент для доступа к AWS Lambda. Все сервисные вызовы, сделанные с помощью этого клиента, блокируются и не возвращаются, пока сервисный вызов не завершится.

Так что у SNS есть очевидное преимущество: он асинхронный. Ваша лямбда не будет ждать окончания следующей лямбды.

Бен Иггулден
источник
17
InvocationType = 'Event' делает его асинхронным. docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/…
Ankit,
3
@ Ankit, который должен быть выбранным ответом, я ошибочно полагал, что использование SNS было единственным способом сделать асинхронный вызов, потому что никто не ответил с этой информацией.
@ Ankit вы знаете пример использования InvocationType = 'Event', но из Java вместо JavaScript? Существует тонна документации по Java, но не так много примеров, как JavaScript
Talador12
SNS по-прежнему добавляет затраты на его использование
Себастьен Х.
1
@SebastienH. Плата за SNS, вызывающую Lambda, не взимается. aws.amazon.com/sns/pricing
fabdouglas
8

В 2016 году Amazon представила функции шага в AWS lambda. Думаю, теперь удобнее использовать функцию шага, поскольку их действительно легко использовать. Вы можете создать конечный автомат с двумя лямбда-функциями:

  • производить цитату
  • превращает цитату в заказ

Вы можете легко сделать это, как показано ниже:

Здесь вы можете иметь первое состояние для создания цитаты, а другое для превращения в порядок

{
  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 позволяет действительно легко написать несколько лямбда-функций и выполнять их последовательно или параллельно. Вы можете получить больше информации о функциях лямбда-шагов здесь: Функции шагов

Сунил Капил
источник
5

Я работал с ответом, предоставленным blueskin, но не смог прочитать ответ Payload, потому что InvocationType = 'Event' является асинхронным , поэтому я изменил на 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); 

Здесь полезная нагрузка - это ваш строковый java-объект, который нужно передать как Json-объект другой лямбде, если вам нужно передать некоторую информацию от вызова лямбды к вызываемой лямбде.

Suyash
источник
2

Вы можете вызвать функцию лямбда непосредственно (по крайней мере , с помощью Java), используя , AWSLambdaClientкак описано в блоге АМС» пост .

Нил
источник
2

У меня та же проблема, но реализованная мной функция 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/

Lewen
источник
1

Что-то вроде обходного решения, но я просто вызываю конечную точку 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

Ансельм
источник
1
это кажется намного менее окольным, чем SNS, но тогда у меня нет большого опыта использования SNS
Брэндон
Можете ли вы поделиться кодом, необходимым для вызова конечной точки API из лямбды?
Гленн
@ Гленн, это всего лишь запрос ajax. Отметьте ваши параметры, которые вам нужны в качестве параметров запроса. См. Docs.aws.amazon.com/apigateway/api-reference/… и docs.aws.amazon.com/lambda/latest/dg/…
Ансельм
4
Другая проблема заключается в том, что проход через API-шлюз является относительно дорогим по сравнению с вызовом другой лямбда-функции. Функция 128 МБ, работающая в течение 100 мс (минимум), стоит 0,21 доллара за 1 миллион вызовов, тогда как API-шлюз стоит 3,50 доллара за 1 миллион. Очевидно, что если вы бежите больше времени или используете больше оперативной памяти, вам придется умножить 21 цент, но все же $ 3,50 за миллион действительно дорого. (Эти цены действовали по состоянию на август 2017 года)
Патрик Чу
1

Другие указали на использование SQS и пошаговых функций. Но оба эти решения добавляют дополнительную стоимость. Переходы состояний ступенчатой ​​функции предположительно очень дороги.

AWS лямбда предлагает некоторую логику повторов. Где то пробует 3 раза. Я не уверен, что это все еще действует, когда вы запускаете его с помощью API.

nnrales
источник
0

Вот пример на 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)
Лалит Гангвар
источник
-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();
ходзин
источник