一个AWS Lambda函数可以调用另一个


320

我有2个Lambda函数-一个产生报价,另一个将报价变成订单。我希望Order lambda函数调用Quote函数来重新生成报价,而不是仅仅从不受信任的客户端接收报价。

我到处都可以想到的地方-但是看不到如何链接或调用函数...肯定存在!


1
我要到达这里,但是为什么您不能在第一个Lambda函数中依赖AWS JavaScript SDK,创建一个AWS.Lambda客户端并调用第二个函数?
devonlazarus 2015年

这就是我要尝试的方法-但我不确定如何执行此操作,因为没有其他Lambda函数执行此操作的示例。
银色

1
显然,您也可以通过HTTP调用Lambda函数。
devonlazarus

4
还有一个想法,您可以通过SNS链接它们,这可能是我采用的一种更具可扩展性的策略
devonlazarus 2015年

6
此处未提及的另一个常见替代方法是“步函数”或“ SWF”。
lebryant

Answers:


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
我可能是错的,但我认为由于调用是同步的,因此第一个Lambda等待第二个Lambda终止,因此您将在两个Lambda运行时产生费用。使用SNS,第一个lambda应该终止,并允许第二个lambda独立执行。
dev

81
我可以通过InvocationType: 'Event'参数使它工作(在FunctionName和之后添加Payload)。从文档中:“您可以选择通过将Event指定为InvocationType来请求异步执行。” 使用异步执行,将可靠地调用回调函数,而不必等待调用的lambda完成执行。
亚历山德罗

25
请注意,调用lambda函数的角色需要包括IAM policy AWSLambdaRole。或者,您可以将以下语句对象添加到角色的现有策略中:'{“ Effect”:“ Allow”,“ Action”:[“ lambda:InvokeFunction”],“ Resource”:[“ *”]}`
Bob Arlof

4
实际上,AWS发布了StepFunctions,该功能使您可以调用多个Lambda,而不必从另一个Lambda调用Lambda,因此。第一个不“等待”第二个完成
塞巴斯蒂安·

116

您应该将您的Lambda functionsvia链接起来SNS。这种方法以最小的工作量提供了良好的性能,延迟和可伸缩性。

您的第一个Lambda向您发布消息,SNS Topic第二个Lambda已订阅该主题。一旦消息到达主题,就将Lambda消息作为输入参数执行秒。

请参阅使用Amazon SNS通知调用Lambda函数

您还可以使用此方法通过SNS调用跨帐户Lambda函数


2
Kinesis可能要复杂一些,但是如果您正在寻找更强大的解决方案,那么它可能是一个不错的选择。而且,SNS不会存储传入的事件,Kinesis会存储。
kixorz

7
“您应该通过SNS链接Lambda函数” –您可以通过证据/文档链接来支持此功能吗?我知道这两种方法如何工作,我很想看到一些意见/明确的陈述,哪一种是首选?
Claude

30
如果您需要异步的话,这是一个好主意。但是,如果您的第一个lambda函数需要第二个lambda的返回值,则必须链接lambda,并使第一个lambda函数直接调用第二个lambda函数。
Noel Llevares '16

3
我不建议使用SNS。您可以仅将异步调用API用于lambda函数,除非您想通知多个订阅者而不仅仅是触发另一个lambda函数,否则无需使用SNS。

6
请记住,SNS没有传递保证,因此您可能会触发该消息,但可能不会到达。
Bart Van Remortele

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)

顺便说一句,您还需要在lambda角色中添加这样的策略

   {
        "Sid": "Stmt1234567890",
        "Effect": "Allow",
        "Action": [
            "lambda:InvokeFunction"
        ],
        "Resource": "*"
    }

该文档似乎建议有效负载必须为JSON。是否可以发送二进制数据?
mbatchkarov

2
我也喜欢这种方法,但是有一个小故障。您需要将转换datetime.now()为字符串(或以某种方式处理)。否则,您会得到错误datetime.datetime(2017, 9, 11, 14, 40, 53, 23834) is not JSON serializable
John C

在第一个lambda的角色中是否可能更具限制性?即,将其绑定到调用特定功能,而不是所有功能?
Phil

@Phil也许可以将“ Resource”字段设置为仅允许特定的一组功能,但是我不确定是否完全如此
blueskin '18

2
InvocationType应该是:RequestResponse。从您尝试调用的lambda获得响应。
ambigus9

31

自从提出此问题以来,Amazon已发布了Step Functions(https://aws.amazon.com/step-functions/)。

AWS Lambda背后的核心原则之一是,您可以将更多精力放在业务逻辑上,而将精力放在将它们联系在一起的应用程序逻辑上。逐步函数使您能够协调函数之间的复杂交互,而无需编写代码即可完成。


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-验证参数值并验证用户或角色是否有权调用该函数。
Trilok Nagvenkar

11

我一直在考虑淘汰SNS,直到在Lambda客户端文档(Java版本)中看到了:

用于访问AWS Lambda的客户端。使用此客户端进行的所有服务调用均处于阻塞状态,直到该服务调用完成才返回。

因此SNS具有明显的优势:它是异步的。您的lambda不会等待后续的lambda完成。


17
InvocationType ='Event'使它异步。docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/…–
Ankit

3
@Ankit应该是选择的答案,我被误认为使用SNS是执行异步调用的唯一方法,因为没有人回答此信息。

@Ankit您是否知道使用InvocationType ='Event'的示例,但是使用Java而不是JavaScript的示例?有大量的Java文档,但没有JavaScript的示例那么多
Talador12 '18

SNS仍会增加其使用成本
Sebastien H.

1
@SebastienH。SNS调用Lambda无需花费任何费用。aws.amazon.com/sns/pricing
fabdouglas

8

亚马逊于2016年在AWS lambda中引入了步骤功能。我认为,现在使用步骤功能更加方便,因为它非常容易使用。您可以使用以下两个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函数使编写多个Lambda函数并依次或并行运行变得非常容易。您可以在此处获取有关lambda步骤功能的更多信息: 步骤功能


5

我正在使用blueskin提供的答案,但由于InvocationType ='Event'async,所以无法读取有效负载响应,因此我将其更改为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对象传递给另一个lambda,以防您需要将某些信息从调用lambda传递给被调用的lambda。



2

您可以AWSLambdaClient按照AWS博客文章中的描述直接(至少通过Java)调用lambda函数。


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/


1

一种回旋解决方案,但是当我需要链接它们时,我只是为我的lambda函数调用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的经验却不多
Brandon

您可以共享从lambda内调用API端点所需的代码吗?
格伦

@Glenn只是一个ajax请求。标记您需要作为查询参数的参数。参见:docs.aws.amazon.com/apigateway/api-reference/…docs.aws.amazon.com/lambda/latest/dg/…–
Anselm

4
另一个问题是,与调用另一个Lambda函数相比,通过API Gateway相对昂贵。运行100毫秒(最低)的128MB函数的费用为每100万次调用0.21美元,而API网关的费用为每100万次3.5美元。显然,如果您要运行更长的时间或使用更多的内存,则必须乘以21美分,但是,每百万$ 3.50确实很昂贵。(这些价格自2017
Patrick Chu

1

其他人指出要使用SQS和步进功能。但是这两种解决方案都增加了额外的成本。据说步功能状态转换非常昂贵。

AWS lambda提供了一些重试逻辑。尝试3次的地方。我不确定使用API​​触发它是否仍然有效。


0

这是调用另一个lambda函数并获取其响应的python示例。有两种调用类型'RequestResponse''Event'。如果要获取lambda函数的响应,请使用“ RequestResponse”,并使用“事件”异步调用lambda函数。因此,异步和同步都可用。

    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();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.