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

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

我已经看遍了我能想到的所有地方——但不知道我该如何链接或调用函数……这当然存在!

265810 次浏览

你应该通过SNS链接你的Lambda functions。这种方法以最小的工作量提供了良好的性能、延迟和可伸缩性。

你的第一个Lambda向你的SNS Topic发布消息,第二个Lambda订阅了这个主题。一旦消息到达主题,第二个Lambda将被作为消息的输入参数执行。

看到使用Amazon SNS通知调用Lambda函数

你也可以使用这个方法来通过SNS调用跨帐户Lambda函数

我发现了一种方法使用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

你可能会使用Async.js的瀑布特性——参见本文档第3步大代码块底部的示例:

https://aws.amazon.com/blogs/compute/better-together-amazon-ecs-and-aws-lambda/

下面是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": "*"
}

你可以直接调用lambda函数(至少通过Java),方法是使用AWS博客帖子中描述的AWSLambdaClient

我正在使用blueskin提供的答案,但我无法读取有效负载响应,因为InvocationType = '事件'异步,所以我更改为InvocationType='RequestResponse',现在一切正常。

我也有同样的问题,但我实现的Lambda函数将在DynamoDB中插入一个条目,所以我的解决方案使用DynamoDB触发器。

我让DB对表中的每一次插入/更新都调用一个Lambda函数,这样就分离了两个Lambda函数的实现。

文件如下: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.Lambda.html < / p >

以下是一个有指导的演练: https://aws.amazon.com/blogs/aws/dynamodb-update-triggers-streams-lambda-cross-region-replication-app/ < / p >

这是一种迂回的解决方案,但当我需要链接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

我一直在寻找切断SNS,直到我在Lambda客户端文档(Java版本)中看到这个:

访问AWS Lambda的客户端。使用此客户端进行的所有服务调用都是阻塞的,直到服务调用完成才返回。

所以SNS有一个明显的优势:它是异步的。你的lambda不会等待后续的lambda完成。

在java中,我们可以这样做:

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


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


InvokeResult invokeResult = awsLambdaAsync.invoke(invokeRequest);

这里,payload是你的stringified java对象,它需要作为Json对象传递给另一个lambda,以防你需要从调用lambda传递一些信息给被调用lambda。

您可以设置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();

自从这个问题被提出后,Amazon发布了Step Functions (https://aws.amazon.com/step-functions/)。

AWS Lambda背后的核心原则之一是,您可以更多地关注业务逻辑,而不是将它们联系在一起的应用程序逻辑。步骤函数允许您编排函数之间的复杂交互,而无需编写代码。

亚马逊于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 functions使得编写多个lambda函数并按顺序或并行运行非常容易。 你可以在这里获得更多关于lambda steps函数的信息: 步骤的功能 < / p >

这个解决方案是使用boto3和Python完成的:

import boto3
import json


lambda_client = boto3.client('lambda', region_name='eu-west-1')


def lambda_handler(event, context):
lambda_client.invoke(FunctionName = 'function_name', InvocationType = 'RequestResponse', Payload = json.dumps(event))
    

return True

其他人指出使用SQS和步骤函数。但这两种解决方案都增加了额外的成本。阶跃函数的状态转换应该是非常昂贵的。

AWS lambda提供了一些重试逻辑。它尝试某件事3次。我不确定当你使用API触发它时,它是否仍然有效。

下面是调用另一个lambda函数并获得其响应的python示例。有两种调用类型“RequestResponse”“事件”。如果你想获得lambda函数的响应,请使用'RequestResponse',并使用'Event'来异步调用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)

您可以以异步方式直接从其他Lambda函数直接触发Lambda函数。

https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html#invocation-async-destinations

有很多答案,但没有一个是强调调用另一个lambda函数不是同步调用的推荐解决方案,你应该使用的是步功能

不建议解决的原因:

  • 当两个函数相互等待时,你为它们支付了费用
  • 你的代码负责重试

您还可以将它用于相当复杂的逻辑,例如并行步骤和捕获失败。每次执行都被注销,这使得调试更加简单。

以下是如何在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;