Cloudwatch putMetricData hanging within Lambda



我正在尝试设置一个lambda来定期查询我们的队列服务,并将消息计数报告回Cloudwatch,以便我们可以监控队列大小。

当使用无服务器框架在本地调用时,所有代码都可以工作。然而,当Lambda本身触发时,对AWS Cloudwatch的请求从未完成,Lambda超时。

import {Callback, Context, Handler} from 'aws-lambda';
import {CloudWatch} from 'aws-sdk';
const queueReporter: Handler = async (event: any, context: Context, callback: Callback) => {
// TRUNCATED - GET Queue counts
const cloudwatch = new CloudWatch({region: 'eu-west-1'})
const date = new Date();
// convert queue data into cloudwatch metrics
const metricData: CloudWatch.Types.MetricData = queues.map((queue): CloudWatch.Types.MetricDatum => ({
MetricName: queue.name,
Timestamp: date,
Unit: 'Count',
Value: queue.messages,
}));
console.log('add metrics'); // This prints out
return await cloudwatch.putMetricData(
{
MetricData: metricData,
Namespace: 'Queue_Messages'
}).promise().then((response) => {
const result = JSON.stringify(response);
console.log(result); // this does not print out
callback(null, result);
return result;
}
);
};

我怀疑这是某种权限问题,因为当我没有在笔记本电脑上配置访问密钥时,我在本地看到了类似的问题
但政策中包括这一声明,我认为这应该足够

{
"Action": [
"cloudwatch:PutMetricData"
],
"Resource": "*",
"Effect": "Allow"
}

为了访问队列的api,此lambda已添加到VPC和安全组中。但是,此安全组没有传出限制,只有传入限制。

如有任何帮助,将不胜感激

我首先要考虑的是简化异步处理的不匹配。您正在等待调用lambda回调的promise,但lambda函数被定义为async,因此AWS希望返回promise。您应该将lambda定义为async并忽略回调,或者定义不带async的lambda并使用回调。

试试这个:

const queueReporter: Handler = async (event: any, context: Context) => {
// TRUNCATED - GET Queue counts
const cloudwatch = new CloudWatch({region: 'eu-west-1'})
const date = new Date();
// convert queue data into cloudwatch metrics
const metricData: CloudWatch.Types.MetricData = queues.map((queue): CloudWatch.Types.MetricDatum => ({
MetricName: queue.name,
Timestamp: date,
Unit: 'Count',
Value: queue.messages,
}));
const response = await cloudwatch.putMetricData({
MetricData: metricData,
Namespace: 'Queue_Messages'
}).promise();
const result = JSON.stringify(response);
console.log(result); 
return result;
};

您需要在监控服务中添加一个VPC端点,以避免超时并连接到CloudWatch。

VPC端点选择

然后,您可以在SDK配置中提及端点的私有DNS名称。

var cloudwatch = new AWS.CloudWatch({
apiVersion: '2010-08-01',
endpoint: `https://monitoring.${process.env.REGION}.amazonaws.com`,
region: process.env.REGION
});

最新更新