【问题标题】:AWS Lambda timeout when another (long) Lambda is invoked调用另一个(长)Lambda 时 AWS Lambda 超时
【发布时间】:2019-05-22 18:12:47
【问题描述】:

我正在使用将多个 Lambda 链接在一起的 Step Functions。在其中一个 lambda 中,我调用了另一个 lambda。两个 lambda 都有 15 分钟的超时时间。但是,几分钟后,调用辅助 lambda 的主 lambda 超时(辅助 lambda 愉快地继续工作)。

Error

com.amazonaws.SdkClientException
Cause

{"errorMessage": "Unable to execute HTTP request: Read timed out",
  "errorType": "com.amazonaws.SdkClientException",
  "stackTrace": [
    cause": {
      "errorMessage": "Read timed out",
   "errorType": "java.net.SocketTimeoutException",
   "stackTrace": [
  "java.net.SocketInputStream.socketRead0(Native Method)",
  "java.net.SocketInputStream.socketRead(SocketInputStream.java:116)",
  "java.net.SocketInputStream.read(SocketInputStream.java:171)",
  "java.net.SocketInputStream.read(SocketInputStream.java:141)",
  "sun.security.ssl.InputRecord.readFully(InputRecord.java:465)",
  "sun.security.ssl.InputRecord.read(InputRecord.java:503)",
  "sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:983)",
  "sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:940)",
  "sun.security.ssl.AppInputStream.read(AppInputStream.java:105)",

这是代码,如您所见,我尝试使用 4 个不同的命令来提高超时时间。

  // (2) Instantiate AWSLambdaClientBuilder to build the Lambda client
        AWSLambdaClientBuilder builder = 
 AWSLambdaClientBuilder.standard().withRegion(region);
        // (3) Build the client, which will ultimately invoke 
   the function
        AWSLambda client = builder.build();

        // (4) Create an InvokeRequest with required parameters
        InvokeRequest req = new 
   InvokeRequest().withFunctionName(random_arn).withPayload(jsonString); 

        // (5) Invoke the function and capture response
        int timeout = (15*60*1000);
        req.setSdkClientExecutionTimeout(timeout);
        req.setSdkRequestTimeout(timeout);
        req.withSdkClientExecutionTimeout(timeout);
        req.withSdkRequestTimeout(timeout);

        InvokeResult result = client.invoke(req);

知道如何解决这个超时问题吗?

【问题讨论】:

    标签: amazon-web-services aws-lambda aws-sdk


    【解决方案1】:

    在使用 AWS Lambda 时,您可能会感兴趣的超时不止一种。您指的是函数执行超时——人们在谈论 Lambda 时通常指的超时。但是,您还需要配置其他超时。查看 AWS CLI 文档:

    https://docs.aws.amazon.com/cli/latest/reference/index.html

    这里有--cli-read-timeout--cli-connect-timeout。如果我要创建一个函数执行超时为 5 分钟的 Lambda 函数,并使用 AWS CLI 使用 RequestResponse(同步)调用类型调用它,如果发生这种情况,则执行时间超过 1 分钟(--cli-read-timeout 的默认值), AWS Lambda 将失败此执行并触发自动重试,最多重试次数。从你所描述的情况来看,我相信你正面临着这样的麻烦。设置所有超时,然后重试。

    更多链接可能对您有所帮助:

    AWS Lambda using Java - setting the configuration connection/socket timeouts

    https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/section-client-configuration.html

    https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/ClientConfiguration.html#setSocketTimeout-int-

    【讨论】:

    • 是的,你是对的。经过一番谷歌搜索后,我可以找到相应的代码: ClientConfiguration clientConfiguration = new ClientConfiguration(); clientConfiguration.setSocketTimeout(0); AWSLambdaClientBuilder 构建器 = AWSLambdaClientBuilder.standard() .withClientConfiguration(clientConfiguration) .withRegion(region); // (3) 构建客户端,最终会调用函数AWSLambda client = builder.build();
    【解决方案2】:

    由于您没有明确指定调用类型,因此您会从您的第一个 AWS Lambda 同步调用您的第二个 AWS Lambda 函数。因此,当您的第二个 AWS Lambda 函数正在运行时,第一个函数也会继续运行,等待第二个函数的响应。这就是为什么如果第一个和第二个 AWS Lambda 函数的运行时间总和高于第一个 AWS Lambda 函数的配置最大超时(在您的情况下为 15 分钟),您的第一个 AWS Lambda 函数将超时。

    从另一个 AWS Lambda 函数同步调用 AWS Lambda 函数是一种不好的做法,因为您可能会遇到当前遇到的超时问题,并在第二个 AWS Lambda 函数运行时花钱运行第一个 AWS Lambda 函数。

    您可以做的是异步调用第二个 AWS Lambda 函数,通过 setting the proper invocation type 为您的 InvokeRequest

    InvokeRequest req = new InvokeRequest().withFunctionName(random_arn)
                                           .withPayload(jsonString)
                                           .withInvocationType(InvocationType.Event); 
    

    这当然只有在您不依赖第二个 AWS Lambda 函数的输出来完成您的第一个函数时才有效。

    由于您已经在使用 AWS Step 函数,可能更好的选择是使用 Step Functions 状态机来编排第二个 AWS Lambda 函数的调用,如以下教程中所述:https://aws.amazon.com/de/getting-started/tutorials/create-a-serverless-workflow-step-functions-lambda/

    根据您的 AWS Lambda 运行方式,将第一个 AWS Lambda 函数(当前调用第二个 AWS Lambda 函数)拆分为在调用的 Lambda 函数之前和之后运行的两部分可能是有意义的。

    【讨论】:

    • 您好,感谢您的详细回复。我知道同步运行这 2 个 lambdas 的缺点。我应该提到我正在另一个区域调用第二个 lambda,这是在要求所有 lambda 都在同一区域运行的阶梯函数管道中无法完成的(如果我错了,请纠正我,我很想调用不同区域的 lambdas!来自阶跃函数)。是的,第一个 lambda 应该耐心等待第二个 lambda 完成。幸运的是,我可以用相当少的内存运行第一个 lambda
    • 而第二个 lambda 执行繁重的工作(并使用更多内存)。所以我有一些开销,但不是很大。所以我认为我仍然需要等待我的第二个 lambda 完成并继续运行该运行的 json 结果。我错过了什么吗?我希望有一些我想念的东西:-)
    • 我仍然建议将调用 Lambda 函数分成两部分。一部分直到您触发第二个 Lambda 函数,另一部分用于处理结果。由于您不能使用 Step Functions 进行编排,因此您可以使用其他东西,例如 SQS 来持久化结果。因此,您将异步调用该函数,并让 SQS 队列中的新消息触发处理结果的 Lambda 函数,这些消息由另一个区域中调用的 Lambda 函数写入。
    • 嗨 Dunedan,这也是一个非常有趣和优雅的解决方案。我正在考虑向 s3 发布一些内容,但使用 SQS 更好。但是,我发现了一个也可以使用的超时设置,这要容易得多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-31
    • 2018-06-09
    • 2019-04-03
    • 2021-06-08
    • 2021-01-30
    相关资源
    最近更新 更多