AWS S3 Java SDK:以编程方式检测时间/时钟偏差?
Posted
技术标签:
【中文标题】AWS S3 Java SDK:以编程方式检测时间/时钟偏差?【英文标题】:AWS S3 Java SDK: detect time/clock skew programmatically? 【发布时间】:2013-02-08 14:17:14 【问题描述】:我的 android 应用使用 AWS Java SDK 将用户照片上传到 S3。
只要用户手机的时钟出现“偏差”,就会导致所有传输失败。这是 S3 的一个有据可查的方面:
http://aws.amazon.com/articles/1109?_encoding=UTF8&jiveRedirect=1#04
上游 S3 服务似乎很清楚地报告了这个错误:
HTTP 状态码:403 禁止
错误代码:RequestTimeToo-Skewed
说明:请求时间与服务器的时间差 时间过长。
但是,当使用 Java SDK 时,似乎信息丰富的 403 代码丢失了......而且我只有一个不透明的“TransferState.Failed”可以通过(顺便说一下,如果互联网连接丢失,也会出现同样的错误,如果超时等...)。
据我从文档中得知:
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/index.html http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/TransferProgress.html http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/Transfer.TransferState.html http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/Upload.html
无法获取有关传输失败的额外“RequestTimeToo-Skewed”元数据。
我错过了吗?当使用 Amazon 的 Java SDK 进行 S3 传输失败时,有什么方法可以获取额外的错误信息?
更新 #1: 一位评论者亲切地强调我应该澄清两点:
我实际上使用的是适用于 Android 的 AWS 开发工具包(它看起来与 Java 开发工具包非常相似,但又截然不同) 我正在使用 TransferManager 类来执行我的上传。显然,这是一个包装了较低级别 AmazonS3Client 的高级类......并且这个较低级别的类应该公开我需要的错误报告,但我仍在调查 TransferManager 和 AmazonS3Client 之间所涉及的确切权衡。据我所知,没有办法通过(同步)AmazonS3Client.putObjectRequest 获取进度信息,这对我来说是一个障碍......更新 #2: 衷心感谢 Jason(AWS 开发工具包团队的)前来帮助我。如果您使用某些方法,重要的信息确实可以作为 AmazonS3Exception 的属性使用。文档最初让我感到困惑,我认为需要手动 Thread.sleep() 循环来轮询状态(因此我无法利用 waitForCompletion 或 waitForException),但如果您在 PutObjectRequest 上使用 ProgressListener,您可以获得完整的进度回调和AmazonS3Exception 的错误保真度。
【问题讨论】:
您似乎使用的是TransferManager
,而不是低级别的AmazonS3Client
。你应该在你的问题中清楚地提到这一点。低级客户端抛出包含errorCode
和statusCode
的AmazonServiceException
。此外,您使用适用于 Java 的 AWS 开发工具包而不是适用于 Android 的 AWS 开发工具包有什么特别的原因吗?
嗨@YosukeMatsuda - 感谢您的回复。是的,我的错,我实际上使用的是适用于 Android 的 AWS (Java) SDK。让我快速浏览一下 AmazonS3Client...
@YosukeMatsuda 查看 AmazonS3Client,是否可以使用此 API 获取传输进度?我用它在上传过程中向我的用户显示一个进度对话框,这很关键,因为我的许多用户的无线连接很差,并且状态/进度/带宽的一些指示确实有帮助......在确切的权衡中是否有一个好的文档在 AmazonS3Client 和 TransferManager 之间?
您可以通过ProgressListener获取进度反馈。总的来说,TransferManager
比较好用,有利于高效上传大量大文件;它会自动对大文件使用分段上传。另一方面,AmazonS3Client
为您提供更多控制权,但您需要进行更多编码。另外,you can fetch the AWS server time using Amazon Route 53.
我们刚刚发布了一个new version of the AWS SDK for Android,它能够处理设备时钟偏差。当您确定设备时钟过于倾斜时,您可能需要使用此功能。
【参考方案1】:
这两种方法应该可以帮助你:
Transfer.waitForCompletion() Transfer.waitForException()如果您根据传输进度事件检测到您的传输失败,您可以简单地调用 Transfer.waitForException() 以返回发生的异常。在这种情况下,该异常将是 AmazonServiceException,其中包含您需要查看的所有信息,以了解真正的问题是时钟偏差问题。
或者,Transfer.waitForCompletion()
方法将从 ExecutionException 中解开原始异常并直接抛出原始异常,就好像它都发生在一个线程上一样。如果您想使用 catch 块干净、优雅地捕获不同类型的错误,这可能是一种更方便的方法。
我不同意“catch Exception”块“非常广泛”。该代码的重点是捕获发生的任何错误,将传输标记为失败并重新抛出错误,以便应用程序代码知道它。如果它不那么广泛,那么那就是异常可能潜入并且传输进度不会正确更新并且与现实不同步的情况。
给出这两种方法并拍摄,如果有帮助,请告诉我们!
【讨论】:
嗨,Jason - 感谢您抽出宝贵时间在这里回复,非常感谢。事实上,看起来 waitForException 是我的方案的最佳选择。最初我跳过了这些方法,因为它们是阻塞的,我无法判断是否/如何获得增量进度回调([1] 中的文档引导我使用循环的 Thread.sleep() 解决方案)。但是使用上面的指导和 Yosuke 在 PutObjectRequest 上提到的 ProgressListener,我认为这将提供 #1 增量进度和 #2 我需要的错误细节级别。 [1] - docs.aws.amazon.com/AWSAndroidSDK/latest/javadoc/com/amazonaws/… 只是一个想法:更新上面链接的 TransferManager 类文档以使用 ProgressListener 和 waitForException 而不是手动的 Thread.sleep() 方法可能是有意义的。 嘿迈克,我很高兴听到这对你有用!关于文档的好建议。今天我将更新它以使这些方法更加明显,您应该会在下一两个 SDK 版本中看到这些更改。如果您在 SDK 代码中遇到更多问题或有任何其他反馈,请告诉我们。我们喜欢听取客户的意见。【参考方案2】:好吧,我已经调试了亚马逊的 SDK,很抱歉,这些信息在内部被吞没了。也许我会尝试提交补丁。
详细信息:内部抛出了一个 AmazonS3Exception,它实际上准确地报告了这个确切的错误场景,但是一个粗暴的 try catch (Exception e) 消耗了它并冲走了特殊性。
这是有罪的try-catch:
https://github.com/aws/aws-sdk-java/blob/master/src/main/java/com/amazonaws/services/s3/transfer/internal/UploadMonitor.java#L145
这是一个屏幕截图,显示 AmazonS3Exception 使用正确的信息被正确抛出...
【讨论】:
以上是关于AWS S3 Java SDK:以编程方式检测时间/时钟偏差?的主要内容,如果未能解决你的问题,请参考以下文章
AWS CloudTrail Create API for Go SDK 引发错误消息“InsufficientS3BucketPolicyException:检测到存储桶的 S3 存储桶策略不正确: