如何在 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?
如何使用 NodeJS 在本地测试 AWS Lambda 处理程序?