3

我们正在使用适用于 .NET 的 AWS 开发工具包,我正试图找出我们似乎与消费者应用程序存在同步问题的地方。基本上,我们有一个推送服务,它生成上传到 S3 的变更集文件,我们的消费者应用程序应该下载这些文件并应用它们,以便同步到正确的状态,而这并没有发生。

关于正确的日期戳的代表内容/位置存在一些相互矛盾的观点。我们的消费者被写入查看 s3 文件的“LastModified”字段以对下载的文件进行排序以进行处理,我不再知道该字段代表什么。起初我以为它代表了我们上传的文件的修改/创建日期,然后(如此处所示它实际上代表了文件上传时间的新日期戳,同样在同一个链接中,它似乎暗示当文件已下载,它会恢复为旧的日期戳(但我无法确认)。

我们正在使用这段代码来提取文件

// Get a list of the latest changesets since the last successful full update.
Amazon.S3.AmazonS3Client client = ...;

List<Amazon.S3.Model.S3Object> listObjects = client.GetFullObjectList(
    this.Settings.GetS3ListObjectsRequest(this.Settings.S3ChangesetSubBucket), 
    Amazon.S3.AmazonS3Client.DateComparisonType.GreaterThan, 
    lastModifiedDate, 
    Amazon.S3.AmazonS3Client.StringTokenComparisonType.MustContainAll, 
    this.Settings.RequiredChangesetPathTokens);

然后按 S3Object 的 LastModified 排序(我认为这是我们的假设错误的地方)

foreach (Amazon.S3.Model.S3Object obj in listObjects)
{
    if (DateTime.Parse(obj.LastModified) > lastModifiedDate)
    {
        //it's a new file, so we use insertion sort to put this file in an ordered list
        //based on LastModified
    }
}

我是否正确假设我们应该做更多的事情来保留我们自己需要的日期戳,例如使用自定义标头/元数据对象将正确的日期戳放在我们需要的文件上,甚至将它放在文件名本身中?

编辑

也许这个问题可以回答我的问题:如果我的服务有 2 个文件要上传到 S3 并经历了这样做的过程,我是否保证这些文件按照上传的顺序(通过 LastModified)或 S3显示在 S3 中做一些可能导致我的文件出现在 S3 对象列表中的异步处理乱序吗?我担心这样一种情况,例如,我的服务上传文件 A 然后 B,B 首先出现在 S3 中,我的消费者得到 + 进程 B,然后 A 出现,然后我的消费者可能会或可能不会得到 A 和错误地处理它认为它不是更新的?

编辑 2

正如我和下面的人所怀疑的那样,我们有一些赛车条件试图按顺序应用变更集,同时盲目地依赖 S3 的日期戳。作为附录,我们最终进行了 2 个修复来尝试解决该问题,这可能对其他人也有用:

首先,为了解决上传完成时间和 S3 报告的修改日期之间的竞争条件,我们决定让我们的所有查询从我们从 S3 中的拉取文件中读取的最后修改日期起 1 秒内查看过去。在检查此修复程序时,我们在 S3 中发现了另一个以前不明显的问题,即S3 不保留时间戳的毫秒数,而是将其所有时间戳向上舍入到下一秒。回溯 1 秒的时间就绕过了这一点。

其次,由于我们及时回顾,如果没有任何新的变更集文件要下载,我们会遇到多次下载同一个文件的问题,所以我们为我们在上次请求中看到的文件添加了一个文件名缓冲区,跳过了任何我们已经看到的文件,并在我们看到新文件时刷新缓冲区。

希望这可以帮助。

4

1 回答 1

5

在 S3 存储桶中列出对象时,从 S3 收到的 API 响应将始终按字母顺序返回它们。

S3 API 不允许您根据 LastModified 值过滤或排序对象。任何此类过滤或排序都仅在您用于连接到 S3 的客户端库中完成。

http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html

至于 LastModified 值的准确性,并且可以根据上传时间对对象列表进行排序,据我所知,LastModified 值设置为上传完成的时间(当服务器返回 200 OK 响应时) ) 而不是开始上传的时间。

这意味着,如果您开始上传大小为 100MB 的 A,然后一秒钟后您开始上传大小仅为 1K 的 B,那么最后,A 的最后修改时间戳将在 B 的最后修改时间戳之后。

如果您需要保留开始上传的时间,最好在原始 PUT 请求中使用自定义元数据标头。

于 2013-08-01T10:03:14.803 回答