我有一个lambda函数,它使用S3.listObjects返回目录列表。该列表有时(并非总是!)过时 - 它不包含最近上传的对象,并且具有旧的修改日期。
当我在本地运行相同的代码时,它总能正常工作。
显然是某种缓存,但我不明白...
以下是相关代码:
function listFiles() {
return new Promise(function (resolve, reject) {
const params = {
Bucket: "XXXXX",
Prefix: "YYYYY"
};
s3.listObjects(params, function (err, data) {
if (err) reject(err);
else resolve(data.Contents);
});
})
}
答案 0 :(得分:0)
这是由于Amazon S3 Data Consistency Model。 S3为PUT提供了写后读一致性,但是其他请求 - 包括listObjects最终是一致的,这意味着传播可能会有延迟。
答案 1 :(得分:0)
实际上,写后读的一致性仅需几秒钟即可解决。但是,这不是保证。几分钟后,亚马逊返回陈旧数据的可能性不大,但并非并非不可能,尤其是跨区域时。但是,您的客户端更有可能为该URL缓存先前的响应。
您可能会遇到lambda容器被重用的副作用。在较高级别的here中对此进行了说明。容器重用的结果之一是,重新调用lambda时,后台进程,临时文件和全局变量修改仍然存在。另一个article talking about how to guard。
如果要将日志发送到cloudwatch日志,则可以将lambda的日志似乎附加到以前的日志流的末尾,而不是创建新的日志流,以确认容器正在被重用。 / p>
当您的lambda容器被重用时,处理程序函数外部的全局变量将被重用。例如,如果您在处理程序的末尾将日志调用的日志级别更改为DEBUG,则如果您的容器被重用,它将在同一日志级别处从处理程序的顶部开始。
如果您正在使用默认的s3客户端会话(看起来像是在使用),则此连接将保留在全局连接(单个)中。如果您的s3客户端连接被重用,则它可能会事先提取调用的缓存结果,我希望该连接在以后的调用中被重用。
避免这种情况的一种方法是指定If-None-Match请求标头。如果您要访问的对象的ETag在远端不匹配,您将获得新数据。您可以将其设置为您获得的最后一个Etag(将其存储在全局变量中),或者可以尝试设置一个完全随机的值-该值应充当缓存破坏者。但是,list_objects()
似乎不接受If-None-Match标头。您可以尝试仅针对当前调用创建一个新的客户端会话。
此article on recursive lambdas讨论了这个问题。