【问题标题】:Lambdas stop invoking after a period of timeLambda 在一段时间后停止调用
【发布时间】:2019-03-31 17:42:43
【问题描述】:

这是我的设置:

一个 Python 3.6 lambda 函数,我想在某个并发级别(比如 10)保持预热。 lambda 的初始化非常痛苦,我不想随意给访问者带来这个成本。我称这些 lambda 为“工人”

一个 Node lambda 函数,它每 5 分钟运行一次以尝试预热 10 个实例。它对其中的 9 个使用 Event 调用类型,对 1 个使用 RequestResponse。这个 lambda 在任何时候都只有一个或零个运行。我称之为“温暖”。

我遵循 [https://www.jeremydaly.com/lambda-warmer-optimize-aws-lambda-function-cold-starts/] 的指导方针,即:

  • ping 频率不要超过每 5 分钟一次
  • 直接调用函数(即不要使用 API Gateway 调用它)
  • 传入一个可以被识别的测试载荷
  • 创建处理程序逻辑,在不运行整个函数的情况下做出相应的响应

这里有一个问题:这可以持续几分钟。然后,当我查看日志时,我开始从我的 worker lambda 调用中获得超时。超时很快接管了 warmer 试图启动的所有调用。

现在,不再对 worker lambda 进行预热。但温暖的人继续尝试,在 Cloudwatch 事件 cron 计划中,遭受 100% 的超时。最后,Lambda 完全停止尝试启动我的 worker lambdas。感觉就像 Lambda 的某个方面让其状态变得混乱。恢复的唯一方法是重新部署 lambda。这让我在预热的 lambdas 工作的情况下再花一个小时。

问题:

  • 如何了解为什么我的工作 lambda 开始超时,然后变得完全没有响应?
  • “并发执行”的定义是什么?在主要的 Lambda 仪表板上,它向我展示了它们的图表。然而,它的并发执行数似乎是我请求的两倍多。

这是预热 lambda 代码(节点):

// warmer
"use strict";

/** Generated by Serverless WarmUP Plugin at ${new Date().toISOString()} */
const aws = require("aws-sdk");
aws.config.region = "${this.options.region}";
const lambda = new aws.Lambda({httpOptions: {timeout: 60000}});
const functionNames = ${JSON.stringify(functionNames)};
const delay = ms => new Promise(res => setTimeout(res, ms))
const concurrency = 10;
module.exports.warmUp = async (event, context, callback) => {
  console.log("Warm Up Start");
  const invokes = await Promise.all(functionNames.map(async (functionName) => {

    let invocations = [];

    try {
      for(let i=1;i <= concurrency;i++){
          let params = {
            FunctionName: functionName,
            InvocationType: (i===concurrency)?'RequestResponse': 'Event',
            LogType: 'None',
            Qualifier: process.env.SERVERLESS_ALIAS || "$LATEST",
            Payload: JSON.stringify({
              source: 'serverless-plugin-warmup',
              '__WARMER_INVOCATION__': i,
              '__WARMER_CONCURRENCY__': concurrency,
              '__WARMER_REQUESTED__': new Date().toISOString(),
            })
          };

          invocations.push(lambda.invoke(params).promise())
      }
      return await delay(75).then(Promise.all(invocations.map(p => p.catch(e => e)))
        .then(results => console.log('results', results))
        .catch(e => {
          console.log(e);
          return e;
        }
        ))
    } catch (e) {
      console.log(\`Warm Up Invoke Error: \${functionName}\`, e);
      return false;
    }
  }));

  console.log(\`Warm Up Finished\`);

}

这里是 worker lambda (Python):

    source = event.get('source')
    if source == 'serverless-plugin-warmup':
        time.sleep(0.05)
        print(event)
        return lambda_gateway_response(200, {"status": "lambda warmup"})

【问题讨论】:

  • “我开始从我的工作 lambda 调用中获得超时” ...这需要定义。你从他们那里得到超时......在哪里观察到?这看起来像什么?
  • 看起来像“ { TimeoutError: Connection timed out after 300000ms at ClientRequest. (/var/runtime/node_modules/aws-sdk/lib/http/node.js:83:34) ",在取暖器的 Cloudwatch 日志中。这种情况一直在发生,直到我重新部署该功能。然后它会再次工作,大约一个小时。
  • 所以联系 Lambda 服务 API 超时。初步印象:您在 VPC 中运行 Lambda 函数,但两个子网不相同...与 Lambda 函数关联的子网之一未正确配置为使用 NAT 网关作为其默认路由。
  • 猜得好,但我们没有使用 VPC :-) 此外,超时完全不存在大约一个小时,然后它们开始发生。之后,有点像荷兰榆树病,我必须将工人 lambda 视为死亡并重新部署。
  • 想通了,谢谢@Michael-sqlbot!

标签: aws-lambda serverless-framework


【解决方案1】:

即使所有日志都指向工作 (Python) lambda,但更温暖的 (Node) lambda 会出现问题。设置context.callbackWaitsForEmptyEventLoop = false后,问题就消失了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多