You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

我想了解的内容

  1. 间歇性NoSuchKey的可能原因:比如桶版本化导致最新版本是删除标记、IAM前缀限制伪装成404、区域隐性不匹配等,希望能列举所有可能的场景
  2. 基于Request ID的诊断方法:有没有AWS CLI命令或者控制台操作,可以通过错误中的Request ID和Extended Request ID排查具体请求失败的原因
  3. 客户端侧的稳健优化方案:在不修改后端配置的前提下,如何优化Android端的AWS SDK v2使用逻辑,避免这种间歇性失败的情况

火山引擎 最新活动