问题描述
从AWS Lambda创建Cloudfront失效时,我遇到了问题。
我的情况很简单:我设置了一个Lambda处理程序,由特定的S3对象创建和删除操作触发,以使Cloudfront发行版上的缓存版本无效。这是使用nodejs编写的功能代码:
const AWS = require('aws-sdk');
exports.handler = async function (event,context) {
const cloudFront = new AWS.CloudFront();
const invalidationParams = {
distributionId: "XXXX",InvalidationBatch: {
CallerReference: Date.Now().toString(),Paths: {
Quantity: 2,Items: [
"/index.html","/service-worker.js"
]
}
}
};
cloudFront.createInvalidation(invalidationParams,(error,data) => {
if (error) {
console.log(error,error.stack);
} else {
console.log("Invalidation results",data);
}
});
};
如您所见,没有什么太复杂的。 现在,在大多数情况下,处理程序在执行任何操作时都没有做任何事情,我正在观察日志,除了请求ID和开始和结束时间戳记之外,什么都没有打印,甚至没有Cloudfront错误,这让我想知道发生了什么。 在连续执行四到五次手动测试之后,会正确创建一个失效,但是日志不会报告该失效。再点火一次,然后打印上次运行的无效结果。我觉得这很奇怪和令人困惑。
从上下文和Lambda代码来看,我可能会缺少一些东西吗?
谢谢。
解决方法
这是因为有Lambda运行时模型。当您使用异步函数作为处理程序时,Lambda执行在返回时被视为“完成”(返回的Promise已结算)。在您的代码中,创建了一个失效,但是处理程序函数在失效完成之前返回。
。当Lambda被视为“完成”时,它冻结了该函数,并且它不会等待createInvalidation
完成。有时起作用但有时不起作用的原因是,在Lambda冻结功能和失效请求之间存在竞争条件。我写了article with a more in-depth exlanation
解决方案很简单:在完成处理程序之前,等待createInvalidation完成:
const AWS = require('aws-sdk');
exports.handler = async function (event,context) {
const cloudFront = new AWS.CloudFront();
const invalidationParams = {
DistributionId: "XXXX",InvalidationBatch: {
CallerReference: Date.now().toString(),Paths: {
Quantity: 2,Items: [
"/index.html","/service-worker.js"
]
}
}
};
await cloudFront.createInvalidation(invalidationParams).promise();
// by the time the handler reaches this point the invalidation made it through
};