amazon-web-services - 为什么 AWS Lambda 函数会为单个事件多次调用?

标签 amazon-web-services amazon-s3 amazon-ec2 aws-sdk aws-lambda

我正在尝试创建执行以下过程的 AWS Lambda 函数。

  • 接收 S3“放置”事件
  • 从 S3 获取文件 A
  • 从调用 lambda 的 S3 获取 fileB
  • 仅启动一个 EC2 实例
  • 为新的 EC2 实例创建标签

  • 问题:多个 (5) 实例意外启动。

    成功创建了一个实例,但同时启动了 4 个其他实例。总共启动了 5 个实例。

    日志

    在此函数的日志流中,我找到了 4 个用于此调用的流。每个 Stream 都没有显示任何错误或异常,但似乎该函数是重复执行的。

    试用

    我猜是函数超时了,然后重新运行。

    然后,我改了Timeout从 5s 到 60s 并将文件放在 S3 上。
    它以某种方式起作用。只出现了2个Log Streams,第一个显示函数只执行了一次,第二个显示函数执行了两次。已启动实例数为 3。

    但是,我不知道为什么会启动多个(3)个实例。

    欢迎任何意见!
    先感谢您 :-)

    我的 Lambda 函数

    我的 Lambda 函数如下。 (简化了隐藏凭证信息,但不会丢失其基本结构)
    var AWS = require('aws-sdk');
    
    function composeParams(data, config){
      var block_device_name = "/dev/xvdb";
      var security_groups = [
        "MyGroupName"
      ];
      var key_name = 'mykey';
      var security_group_ids = [
        "sg-xxxxxxx"
      ];
      var subnet_id = "subnet-xxxxxxx";
    
      // Configurations for a new EC2 instance
      var params = {
        ImageId: 'ami-22d27b22',      /* required */
        MaxCount: 1,                  /* required */
        MinCount: 1,                  /* required */
        KeyName: key_name,
        SecurityGroupIds: security_group_ids,
        InstanceType: data.instance_type,
        BlockDeviceMappings: [
          {
            DeviceName: block_device_name,
            Ebs: {
              DeleteOnTermination: true,
              Encrypted: true,
              VolumeSize: data.volume_size,
              VolumeType: 'gp2'
            }
          }
        ],
        Monitoring: {
          Enabled: false              /* required */
        },
        SubnetId: subnet_id,
        UserData: new Buffer(config).toString('base64'),
        DisableApiTermination: false,
        InstanceInitiatedShutdownBehavior: 'stop',
        DryRun: data.dry_run,
        EbsOptimized: false
      };
    
      return params;
    }
    
    exports.handler = function(event, context) {
      // Get the object from the event
      var s3 = new AWS.S3({ apiVersion: '2006-03-01' });
      var bucket = event.Records[0].s3.bucket.name;
      var key = event.Records[0].s3.object.key;
    
      // Get fileA
      var paramsA = {
        Bucket: bucket,
        Key: key
      };
      s3.getObject(paramsA, function(err, data) {
        if (err) {
          console.log(err);
        } else {
          var dataA = JSON.parse(String(data.Body));
    
          // Get fileB
          var paramsB = {
            Bucket: bucket,
            Key: 'config/config.yml'
          };
          s3.getObject(paramsB, function(err, data) {
            if (err) {
              console.log(err, err.stack);
            } else {
              var config = data.Body;
              /* Some process */
    
              // Launch EC2 Instance
              var ec2 = new AWS.EC2({ region: REGION, apiVersion: '2015-04-15' });
              var params = composeParams(dataA, config);
              ec2.runInstances(params, function(err, data) {
                if (err) {
                  console.log(err, err.stack);
                } else {
                  console.log(data);
    
                  // Create tags for instance
                  for (var i=0; i<data.Instances.length; i++){
                    var instance = data.Instances[i];
                    var params = {
                      Resources: [                /* required */
                        instance.InstanceId
                      ],
                      Tags: [                     /* required */
                        {
                          Key: 'Name',
                          Value: instance_id
                        },
                        {
                          Key: 'userID',
                          Value: dataA.user_id
                        }
                      ],
                      DryRun: dataA.dry_run
                    };
                    ec2.createTags(params, function(err, data) {
                      if (err) {
                        console.log(err, err.stack);
                      } else {
                        console.log("Tags created.");
                        console.log(data);
                      }
                    });
                  }
                }
              });
            }
          });
        }
      });
    };
    

    最佳答案

    解决了。

    添加 context.succeed(message);嵌套回调的最后一部分防止函数的重复执行。

                ec2.createTags(params, function(err, data) {
                  if (err) {
                    console.log(err, err.stack);
                    context.fail('Failed');
                  } else {
                    console.log("Tags created.");
                    console.log(data);
                    context.succeed('Completed');
                  }
                });
    

    关于amazon-web-services - 为什么 AWS Lambda 函数会为单个事件多次调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31982704/

    相关文章:

    amazon-web-services - 如何将本地主机设置为主题订阅的端点 - Amazon sns 服务

    python - 通过AWS Gateway Api通过Lambda将文件上传到S3

    opencv - 安装opencv AWS实例

    macos - 在 Mac 上通过终端连接到 EC2 实例

    ruby 脚本 'Killed'

    amazon-web-services - 在 AWS DNS/Route 53 记录中使用比较逻辑

    macos - 使用 scp 将文件从 Mac OS 复制到 Amazon EC2 实例时出现权限被拒绝错误

    amazon-web-services - 保护 Amazon Gateway API 仅可从 S3 存储桶中的内容访问

    Java.net.SocketException : Connection reset when reading file from S3

    java - 从 JAVA API 获取 Amazon EC2 实例的公共(public) DNS