Лямбды перестают вызываться через некоторое время

Вот моя установка:

Лямбда-функция Python 3.6, который я хочу предварительно подогреть на определенном уровне параллелизма (скажем, 10). Инициализация лямбды достаточно болезненна, поэтому я не хочу навязывать эту стоимость посетителям наугад. Я называю эти лямбды "рабочими"

Узловая лямбда-функция, который запускается каждые 5 минут, чтобы попытаться предварительно разогреть 10 экземпляров. Он использует тип вызова Event для 9 из них и RequestResponse для 1. В любой момент времени выполняется только одна или ноль из этой лямбды. Я называю это «теплее».

Я следовал рекомендациям [https://www.jeremydaly.com/lambda-warmer-optimize-aws-lambda-function-cold-starts/]], а именно:

  • Не пингуйте чаще, чем каждые 5 минут
  • Вызов функции напрямую (т. Е. Не используйте API Gateway для ее вызова)
  • Передайте тестовую полезную нагрузку, которую можно идентифицировать как таковую.
  • Создайте логику обработчика, которая отвечает соответствующим образом, не запуская всю функцию

Вот проблема: это отлично работает в течение нескольких минут. Затем, просматривая журналы, я начинаю получать тайм-ауты от лямбда-вызовов моих рабочих. Таймауты быстро принимают на себя все вызовы, которые пытается запустить обогреватель.

Теперь рабочие лямбды больше не прогреваются. Но грелка продолжает попытки в расписании cron событий Cloudwatch, страдая 100% тайм-аутом. Наконец, 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.info("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.info('results', results))
        .catch(e => {
          console.info(e);
          return e;
        }
        ))
    } catch (e) {
      console.info(\`Warm Up Invoke Error: \${functionName}\`, e);
      return false;
    }
  }));

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

}

А вот и рабочая лямбда (Python):

    source = event.get('source')
    if source == 'serverless-plugin-warmup':
        time.sleep(0.05)
        print(event)
        return lambda_gateway_response(200, {"status": "lambda warmup"})
«Я начинаю получать тайм-ауты из-за лямбда-вызовов моего рабочего» ... это необходимо определить. У них таймауты "от" ... где наблюдали? Как это выглядит?
Michael - sqlbot 27.10.2018 19:24

В журналах Cloudwatch грелки похоже: "{TimeoutError: Время ожидания соединения истекло через 300000 мсек в ClientRequest. <anonymous> (/var/runtime/node_modules/aws-sdk/lib/http/node.js:83:34)"). Это продолжается до тех пор, пока я повторно не разверну функцию. Потом снова заработает около часа.

Fizz Orange 28.10.2018 16:47

Итак, тайм-аут связи с API службы Lambda. Первоначальное впечатление: вы используете функцию Lambda внутри VPC, но две подсети не идентичны ... одна из подсетей, связанных с функцией Lambda, неправильно настроена для использования шлюза NAT в качестве маршрута по умолчанию.

Michael - sqlbot 28.10.2018 19:02

Хорошая догадка, но мы не используем VPC :-) Кроме того, таймауты полностью отсутствуют около часа, затем они начинают возникать. После этого это похоже на болезнь голландского вяза, я должен рассматривать рабочую лямбду как мертвую и повторно развертывать.

Fizz Orange 28.10.2018 21:38

Разобрался, спасибо @ Michael-sqlbot!

Fizz Orange 29.10.2018 16:41
Доступ AWS Java Lambda к экземпляру AWS RDS MySQL с помощью CDK
Доступ AWS Java Lambda к экземпляру AWS RDS MySQL с помощью CDK
В этой статье мы рассмотрим, как включить доступ Java Lambda к экземпляру AWS RDS MySQL.
3
5
441
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это была более теплая (Node) лямбда, выходящая из строя, хотя все журналы указывали на рабочие (Python) лямбды. После установки context.callbackWaitsForEmptyEventLoop = false проблема исчезла.

Другие вопросы по теме