ChatGPT解决这个技术问题 Extra ChatGPT

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

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

我已经看过我能想到的所有地方 - 但看不到我将如何链接或调用函数......当然这存在!

我到了这里,但您为什么不能在第一个 Lambda 函数中依赖 AWS JavaScript 开发工具包,创建一个 AWS.Lambda 客户端和 invoke 第二个函数?
这是我要尝试的——但我不完全确定如何去做,因为没有任何例子可以从另一个 Lambda 函数中做到这一点。
显然您也可以通过 HTTP 调用 Lambda 函数。
还有一个想法,您可以chain them through SNS,这可能是我作为一种更具可扩展性的策略所采用的方式
此处未提及的另一个常见替代方法是 Step Functions 或 SWF。

N
Nicolas Grenié

我找到了一种使用 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


使用 SNS 可能是更好的方法,但这是正确的答案。
我可能是错的,但我认为因为调用是同步的,所以第一个 lambda 等待第二个 lambda 终止,因此在两个 lambda 运行时您将产生费用。使用 SNS,第一个 lambda 应该终止并允许第二个 lambda 独立执行。
多亏了 InvocationType: 'Event' 参数(在 FunctionNamePayload 之后添加它),我才能让它工作。来自文档:“您可以选择通过将 Event 指定为 InvocationType 来请求异步执行。” 使用异步执行,回调函数将被可靠地调用,但无需等待调用的 lambda 完成执行.
请注意,调用 lambda 函数的角色需要包含 IAM 策略 AWSLambdaRole。或者,您可以将以下语句对象添加到您角色的现有策略中:'{ "Effect": "Allow", "Action": [ "lambda:InvokeFunction" ], "Resource": ["*"] }`
a
adamkonrad

您应该通过 SNS 链接您的 Lambda functions。这种方法以最小的努力提供了良好的性能、延迟和可扩展性。

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

请参阅Invoking Lambda functions using Amazon SNS notifications

您也可以将此方法用于Invoke cross-account Lambda functions via SNS


Kinesis 可能有点复杂,但如果您正在寻找更强大的解决方案,那么它可能是您的一个不错的选择。此外,SNS 不存储传入事件,Kinesis 会。
“你应该通过 SNS 链接你的 Lambda 函数”——你能用证据/文档链接来支持这一点吗?我知道这两种方法是如何工作的,我有兴趣看到一些关于哪种方法是首选方法的意见/明确陈述
如果您需要它是异步的,这是一个好主意。但是,如果您的第一个 lambda 函数需要第二个 lambda 的返回值,则必须链接 lambda 并让第一个 lambda 函数直接调用第二个 lambda 函数。
我不建议使用 SNS。您可以将异步调用 API 用于 lambda 函数 - 没有理由使用 SNS,除非您想通知多个订阅者而不仅仅是触发另一个 lambda 函数。
请记住,SNS 没有传递保证,因此您可能会触发消息但它可能不会到达。
C
Chenna V

这是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。是否可以发送二进制数据?
我也更喜欢这种方法,但它有一个小故障。您需要将 datetime.now() 转换为字符串(或以某种方式处理它)。否则,您会收到错误 datetime.datetime(2017, 9, 11, 14, 40, 53, 23834) is not JSON serializable
是否可以对第一个 lambda 的角色进行更多限制?即,将其绑定到调用特定功能,而不是任何和所有?
@Phil也许可以将“资源”字段设置为仅允许一组特定的功能,但我不完全确定
InvocationType 应该是:RequestResponse。从您尝试调用的 lambda 获取响应。
d
dustinnoe

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

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


l
luk2302

此解决方案是使用 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

InvocationType 从以下选项中选择。 RequestResponse(默认)- 同步调用函数。保持连接打开,直到函数返回响应或超时。事件 - 异步调用函数。将多次失败的事件发送到函数的死信队列(如果已配置)。 DryRun - 验证参数值并验证用户或角色是否有权调用该函数。
B
Ben Iggulden

我一直在考虑删除 SNS,直到在 Lambda client docs (Java version) 中看到这个:

用于访问 AWS Lambda 的客户端。使用此客户端进行的所有服务调用都是阻塞的,并且在服务调用完成之前不会返回。

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


InvocationType='Event' 使其异步。 docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/…
@Ankit 应该是选择的答案,我被误导认为使用 SNS 是进行异步调用的唯一方法,因为没有人回答此信息。
@Ankit 您知道使用 InvocationType='Event' 但来自 Java 而不是 JavaScript 的示例吗?有大量的 Java 文档,但没有 JavaScript 那么多的示例
SNS 仍然会增加使用成本
@SebastienH。 SNS 调用 Lambda 是免费的。 aws.amazon.com/sns/pricing
S
Sunil Kapil

亚马逊于 2016 年在 AWS lambda 中引入了 steps 函数。我认为,现在使用 step 函数更方便,因为它真的很容易使用。您可以构建具有两个 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 步骤函数的更多信息:Steps Functions


S
Suyash

在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。


如何传递目标 lambda 所需的路径参数?
B
Black

有很多答案,但没有人强调调用另一个 lambda 函数不是同步调用的推荐解决方案,而您应该使用的实际上是 Step Functions

不推荐解决方案的原因:

当它们相互等待时,您为这两个功能付费

您的代码负责重试

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


a
antonio

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


M
Mike

您也许可以使用 Async.js 瀑布功能 - 请参阅本文档第 3 步中大代码块的底部以获取示例:

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


n
nnrales

其他人指出使用 SQS 和 Step Functions。但是这两种解决方案都会增加额外的成本。 Step Function 状态转换据说非常昂贵。

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


l
lalit gangwar

这是调用另一个 lambda 函数并获取其响应的 python 示例。有两种调用类型“RequestResponse”和“Event”。如果要获取 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)

N
Neil

您可以使用 AWS 博客 post 中所述的 AWSLambdaClient 直接调用 lambda 函数(至少通过 Java)。


L
Lewen

我遇到了同样的问题,但我实现的 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/


A
Anselm

一种迂回的解决方案,但是当我需要链接它们时,我只是为我的 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 少很多迂回,但我没有太多使用 SNS 的经验
您可以分享从 lambda 中调用 API 端点所需的代码吗?
@Glenn 这只是一个 ajax 请求。标记您需要作为查询参数的参数。请参阅:docs.aws.amazon.com/apigateway/api-reference/…docs.aws.amazon.com/lambda/latest/dg/…
另一个问题是,与调用另一个 Lambda 函数相比,通过 API Gateway 相对昂贵。运行 100 毫秒(最小值)的 128MB 函数每 100 万次调用需要 0.21 美元,而 API 网关每 100 万次调用需要 3.50 美元。显然,如果您运行更多时间或使用更多内存,则必须乘以 21 美分,但每百万美元 3.50 美元仍然非常昂贵。 (这些价格自 2017 年 8 月起生效)
S
Shaun Taylor

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

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


h
hojin

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