如何在 AWS Lambda 中使用 Node.js 列出我的所有 Amazon EC2 实例?

Posted

技术标签:

【中文标题】如何在 AWS Lambda 中使用 Node.js 列出我的所有 Amazon EC2 实例?【英文标题】:How can I list all my Amazon EC2 instances using Node.js in AWS Lambda? 【发布时间】:2015-02-25 17:00:53 【问题描述】:

我在 AWS 上并使用 AWS SDK for javascript in Node.js。我正在尝试构建一个 AWS Lambda 函数,在里面我想获取我所有的 Amazon EC2 实例的列表,但我似乎无法让它工作。谁能发现我做错了什么?

这是我的 Lambda 函数代码:

var AWS = require('aws-sdk');
AWS.config.region = 'us-west-1';

exports.handler = function(event, context) 
    console.log("\n\nLoading handler\n\n");
    var ec2 = new AWS.EC2();
    ec2.describeInstances( function(err, data) 
        console.log("\nIn describe instances:\n");
      if (err) console.log(err, err.stack); // an error occurred
      else     console.log("\n\n" + data + "\n\n"); // successful response
    );
    context.done(null, 'Function Finished!');  
;

这是我的政策(我认为这是正确的?)


  "Version": "2012-10-17",
  "Statement": [
    
      "Effect": "Allow",
      "Action": [
        "logs:*"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    ,
    
    "Effect": "Allow",
    "Action": [
      "ec2:*"
    ],
    "Resource": "arn:aws:ec2:*"
  ,
    
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::*"
      ]
    
  ]

如果我在 'ec2' 上执行 console.log,我会得到:

 config: 
    credentials: 
       expired: false,
        expireTime: null,
        accessKeyId: 'XXXXXXXXXXXXXXXXXX',
        sessionToken: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
        envPrefix: 'AWS' ,
     credentialProvider:  providers: [Object] ,
     region: 'us-west-1',
     logger: null,
     apiVersions: ,
     apiVersion: null,
     endpoint: 'ec2.us-west-1.amazonaws.com',
     httpOptions:  timeout: 120000 ,
     maxRetries: undefined,
     maxRedirects: 10,
     paramValidation: true,
     sslEnabled: true,
     s3ForcePathStyle: false,
     s3BucketEndpoint: false,
     computeChecksums: true,
     convertResponseTypes: true,
     dynamoDbCrc32: true,
     systemClockOffset: 0,
     signatureVersion: 'v4' ,
  isGlobalEndpoint: false,
  endpoint: 
    protocol: 'https:',
     host: 'ec2.us-west-1.amazonaws.com',
     port: 443,
     hostname: 'ec2.us-west-1.amazonaws.com',
     pathname: '/',
     path: '/',
     href: 'https://ec2.us-west-1.amazonaws.com/'  

【问题讨论】:

【参考方案1】:

最可能的原因是您在 Lambda 函数完成对 EC2 DescribeInstances API 的调用之前明确终止了它。

原因是 Lambda 假定您的代码在您调用 context.done(...) 后立即执行完毕。这发生在console.log(... data ...) 调用之前。

由于 NodeJS 的工作方式以及适用于 JavaScript 的 AWS 开发工具包的工作方式,会发生这种奇怪的排序。在 NodeJS 中,你永远不应该 block 执行。对 Web 服务(例如 EC2)的调用会阻止执行。因此,适用于 JavaScript 的 AWS 开发工具包(以及大多数 NodeJS 库)通过 异步 调用来工作。

大多数情况下,当您进行 异步 调用时,您会将 callback 函数传递给该调用。当结果准备好后,NodeJS 会执行 callback 函数。

在您的代码中,function(err, data) ...回调 函数。这不会立即执行,而是会在 NodeJS 看到 ec2.describeInstances 调用已收到其结果时安排执行。

一旦您安排回叫的执行,您就会调用context.done(...),它告诉 Lambda:我已经完成了,你可以杀了我。在 EC2 DescribeInstances 调用接收其数据并将其传递给您的 callback 函数之前,它很乐意服从并中断您的函数。

如何解决问题?

现在答案应该很清楚了:只需将您的 context.done(...) 调用移到您的 callback 函数内部,就在包含 console.log(...data...) 调用的 if/else 块之后:

ec2.describeInstances( function(err, data) 
  console.log("\nIn describe instances:\n");
  if (err) console.log(err, err.stack); // an error occurred
  else     console.log("\n\n" + data + "\n\n"); // successful response
  context.done(null, 'Function Finished!');  
);

【讨论】:

谢谢@Bruno。您如何建议在循环中完成相同的任务 - 比如创建 10 个 SQS 队列,插入 20 条消息 [ 批处理 api 存在,除此之外],如果我将 context.done() 放入循环中,这是否意味着迭代会单次执行后停止(1,然后是部分执行)【参考方案2】:

截至 2019 年(10 月),给定的答案没有帮助,经过挖掘,我现在发现它是基于承诺的

exports.handler = async function(event) 
  const promise = new Promise(function(resolve, reject) 
      //your logic, goes here at the end just call resolve 
      resolve("data you want to return"); // here lamda exits 
    )
  return promise;// lamda does not  exits here, it waits for to resolve

【讨论】:

以上是关于如何在 AWS Lambda 中使用 Node.js 列出我的所有 Amazon EC2 实例?的主要内容,如果未能解决你的问题,请参考以下文章

AWS Lambda、API 网关和 Cognito:如何在 lambda 函数中获取身份对象?

如何使用 IAM 在 AWS Lambda 中调用 AppSync?

如何在 AWS Lambda 中使用 cURL 和邮件

如何使用 NodeJS 在本地测试 AWS Lambda 处理程序?

如何通过在 AWS CLI 中使用其 ARN 来获取 lambda 函数?

如何在 AWS Lambda 上的无服务器应用程序中存储和使用 HTML 模板(使用 AWS SAM)?