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

我在AWS上, 在Node.js中使用AWS SDK for JavaScript 。 我正在尝试构build一个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/' } } 

最可能的原因是在完成对EC2 DescribeInstances API的调用之前,您正在显式终止您的Lambda函数。

原因在于,只要调用context.done(...) ,Lambda就会假定您的代码已经完成执行。 这是 console.log(... data ...)调用之前发生的。

由于NodeJS的工作原理以及适用于JavaScript的AWS开发工具包的工作原理,这种奇怪的sorting方式是有的。 在NodeJS中,你不应该阻止执行。 对Web服务(如EC2)的调用会阻止执行。 因此,适用于JavaScript的AWS开发工具包(以及大多数NodeJS库)通过进行asynchronous调用来工作。

大多数时候,当你有一个asynchronous调用,你传递一个callback函数到那个调用。 当结果准备就绪时,NodeJS将执行callback函数。

在你的代码中, function(err, data) {...}callback函数。 这不会立即执行,而是在ec2.describeInstances发现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!'); });