Android端使用AWS SDK v2下载S3同一对象时间歇性触发NoSuchKey(404)问题的排查及客户端优化咨询
Android端使用AWS SDK v2下载S3同一对象时间歇性触发NoSuchKey(404)问题的排查及客户端优化咨询
问题背景
我在Android项目中使用AWS SDK for Java v2从S3桶下载.aac音频文件时,遇到了一个非常诡异的间歇性问题:同一个对象Key,有时候下载会报NoSuchKey(404)错误,但重启APP或者过一会儿再用完全相同的Key重试,又能成功下载,期间没有做任何后端配置变更。想请教这种情况的可能原因,以及如何优化客户端的下载逻辑来提升稳定性。
环境信息
- Android版本:15(SDK 35),且其他测试机型也出现相同问题
- AWS SDK for Java v2(S3模块)版本:2.x.x
- S3桶区域:eu-west-1(客户端已配置为相同区域)
- IAM权限:已配置对音频文件前缀的只读访问权限
错误示例
software.amazon.awssdk.services.s3.model.NoSuchKeyException: The specified key does not exist. Service: S3, Status Code: 404, Request ID: MCZP4XMJHPPPQHFT, Extended Request ID: ygGBV...
核心代码片段
S3下载方法
fun getObjectBytes(bucketName: String, keyName: String, folder: String): Boolean { try { val aws = AWSConnection() val objectRequest = GetObjectRequest .builder() .key("$folder/$keyName") .bucket(bucketName) .build() val objectBytes = aws.s3Client.getObjectAsBytes(objectRequest) val data = objectBytes.asByteArray() writeToLocal(data, keyName) return true } catch (e: IOException) { e.logException() return false } catch (e: S3Exception) { e.logException() return false } catch (e: Exception) { e.logException() return false } }
调用逻辑
private fun downloadAudio(uri: Uri, audioFilename: String, s3Folder: String){ if (!Http.isOnline){ confirmInternetConnection(uri, audioFilename, s3Folder) }else{ val taskRunner = TaskRunner() taskRunner.executeAsync(DownloadAudioTask(s3Service, audioFilename, s3Folder)) { fileGet: Boolean -> if (!fileGet){ alertCannotGetFile() }else{ playAudio(uri) } } } } class DownloadAudioTask( private val s3Service: IS3StorageService, private val filename: String, private val s3Folder: String) : Callable<Boolean> { override fun call(): Boolean { return s3Service.getObjectBytes(props.aws.s3.audioBucketName, filename, s3Folder) } }
已尝试的优化方案
- 实现带指数退避+抖动的重试逻辑(最多5次):但失败时连续重试都会失败,无法立刻恢复
- 提前调用
headObject校验:有时候HEAD请求成功,但后续GET请求依然报404 - Key规范化处理:避免出现
//、去除首尾空格、统一使用NFC Unicode编码 - 复用S3Client实例+固定区域:没有每次请求都创建新客户端,区域配置与桶一致
- 验证请求Key:确认每次GET请求使用的都是
$folder/$fileName格式的正确Key
我想了解的内容
- 间歇性NoSuchKey的可能原因:比如桶版本化导致最新版本是删除标记、IAM前缀限制伪装成404、区域隐性不匹配等,希望能列举所有可能的场景
- 基于Request ID的诊断方法:有没有AWS CLI命令或者控制台操作,可以通过错误中的Request ID和Extended Request ID排查具体请求失败的原因
- 客户端侧的稳健优化方案:在不修改后端配置的前提下,如何优化Android端的AWS SDK v2使用逻辑,避免这种间歇性失败的情况




