AWS Lambda SDK - TooManyRequestsException

AWS Lambda SDK - TooManyRequestsException

我有大约 50 个 AWS Lambda 函数,我有一个 gulp 任务来部署它,脚本压缩函数并将其上传到 S3,然后使用 Lambda JS SDK 我将这个任务调用到 create/update 函数:

gulp.task('upload', function (callback) {
  var AWS = require('aws-sdk');
  var lambda = Promise.promisifyAll(new AWS.Lambda(), {
    filter: function (name) {
      return name.indexOf('Async') === -1;
    }
  });
  var promises = require('./lambda-config.js').lambda.map(function (lambdaConfig) {
    return lambda.getFunctionConfigurationAsync({
      FunctionName: lambdaConfig.FunctionName
    }).then(function () {
      return lambda.updateFunctionCodeAsync({
        FunctionName: lambdaConfig.FunctionName,
        S3Bucket: lambdaConfig.Code.S3Bucket,
        S3Key: lambdaConfig.Code.S3Key
      });
    }).catch(function () {
      return lambda.createFunctionAsync(lambdaConfig);
    });
  });
  Promise.all(promises).then(() => callback()).catch(callback);
});

我收到 TooManyRequestsException error,压缩包大小为 13MB,解压后版本为 50MB。我不认为大小是问题,而是对 SDK 的并发调用。

在哪里可以找到有关 AWS SDK 可以执行多少个并发调用的信息?你建议我如何解决 TooManyRequestsException error ?感谢代码示例。

zip 的大小似乎不是问题(参见 http://docs.aws.amazon.com/lambda/latest/dg/limits.html)。

当超过 AWS 授权该账户的 Lambda 进程数时,我收到了 TooManyRequestsException。以下是围绕这种限制需要考虑的一些事项:

  1. 您开始时的限制约为 100.See https://aws.amazon.com/lambda/faqs/ 以了解详细信息。据我了解,这意味着最好的情况,如果没有其他事情发生,您在任何给定时间最多只能有 100 个 Lambda 进程 运行ning。

  2. Lambda 进程结束的时间与结束的进程计入您的限制的时间之间存在延迟。我不确定是否有关于该时间有多长的明确指导;根据我的经验,它的范围从几秒钟到一分钟左右不等。因此,如果您有一个使用 50 个 lamda 的进程,并且每个 lambda 需要 60 秒才能达到 运行,那么最好的情况是,限制为 100,您可以 运行 该进程每分钟两次,但实际上它会可能比那更受限制。

  3. 如果您向亚马逊发送服务限制增加请求(支持 -> 创建案例 -> 服务限制增加),您的限制可以增加。您必须提供每秒请求数、请求持续时间等信息。

  4. 非常重要:Lambda 进程可能会自动重试——参见 https://aws.amazon.com/lambda/faqs/,尤其是 "What happens if my account exceeds the default throttle limit on concurrent executions?" 和 "What happens if my Lambda function fails during processing an event?"。这意味着如果您超出了您的限制并继续测试,您可能会积压仍在重试的进程(并用完您的限制)。

基于此,您可能需要执行以下操作:

  1. 自行管理重试,不要使用 Amazon 的内置重试机制,尤其是出于测试目的的任何交互式 and/or。例如在节点中:

    var lambda = new AWS.Lambda({
        region: REGION,
        maxRetries:0,
        ....
    });
    

    然后您可以使用类似的方式进行管理:

    lambda.invoke(lambda_params, function(err, obj){
        if(err){
            if(err.toString().match(/TooManyRequestsException/)) ...
    
  2. 如果您想确保停止任何可能仍然 运行 失控的 Lambda(无论是由于重试还是因为您的代码中可能存在错误) ,删除您的 lambda 函数。例如从控制台: aws lambda delete-function --function-name my_outofcontrol_func

  3. 在尝试扩展之前,请大量使用测试功能(AWS 仪表板 -> Lambda -> 选择您的功能 -> 测试)。日志也很有用——因此如果您调用 50 个 lambda 进行测试,您可以转到日志并查看这 50 个 lambda 发生了什么。

  4. 需要扩展时,提前向亚马逊申请。这将需要几天时间,对我和我听说的其他人来说,他们总是希望给你的比你要求的少。如果您有使用现有容量的历史,这会有所帮助。当心,一旦你达到大约 1000 个节点,在你突破免费层并开始必须为每次使用付费之前不需要进行大量测试(更多理由做很多#3)。

看来这里的并发有问题。我遇到了同样的问题,保存了许多承诺,然后用 Promise.all

执行它们

这是通过使用具有类似功能 Promise.map 的 Bluebird Promise 库解决的,该库还可以处理并发。

代码将符合以下内容:

const Promise = require('bluebird');

Promise.map(arrayWithLambdas, lambda => {

        //Deploy each lambda

    }, { concurrency: 5}) // Control concurrency
    .then(() => {

        // Handle successful deploy of lambdas
    })
    .catch(() => {

        // Handle unsuccessful deploy of lambdas
    })
};