新加坡区域S3桶调用GetBucketACL()抛出指定端点访问301异常
异常原因
- 该301错误的核心是S3请求的端点与桶实际所属区域不匹配。你向新加坡区域的S3端点发起请求,但目标桶实际不在该区域,S3返回重定向要求你将请求发送到桶所属区域的正确端点,而AWS SDK v2默认不会自动处理该类S3重定向,因此抛出异常。
- 对应到你的代码,具体触发原因是:创建桶时未显式指定桶的区域配置,即使初始化S3客户端时传入了新加坡区域参数,未配置
CreateBucketConfiguration的CreateBucketRequest会默认将桶创建到美东1区(us-east-1),后续用新加坡区域的客户端请求美东的桶就会触发该错误。
解决方案
方案1(推荐):创建桶时显式指定区域配置,保证桶与客户端同区域
修改createAWSBucket方法的CreateBucketRequest构造逻辑,显式传入桶的区域配置:
// 先调整方法入参,传入客户端对应的region,或者从s3Client配置中提取region public String createAWSBucket(S3Client s3Client, String bucketName, Region region) { try { S3Waiter s3Waiter = s3Client.waiter(); CreateBucketRequest bucketRequest = CreateBucketRequest.builder() .bucket(bucketName) // 新增桶区域配置 .createBucketConfiguration(CreateBucketConfiguration.builder() .locationConstraint(region.id()) .build()) .build(); CreateBucketResponse few = s3Client.createBucket(bucketRequest); HeadBucketRequest bucketRequestWait = HeadBucketRequest.builder() .bucket(bucketName) .build(); // 建议等待桶创建完成再返回,避免后续立即访问时出现一致性问题 WaiterResponse<HeadBucketResponse> waiterResponse = s3Waiter.waitUntilBucketExists(bucketRequestWait); waiterResponse.matched().response().ifPresent(System.out::println); return bucketRequestWait.bucket(); } catch (S3Exception e) { if(e.awsErrorDetails().errorCode().equalsIgnoreCase("BucketAlreadyOwnedByYou")){ return bucketName; } throw e; } }
调用该方法时,直接传入你初始化客户端时用的新加坡区域Region.AP_SOUTHEAST_1即可。
方案2:开启S3客户端跨区域重定向自动跟随
如果你的业务确实需要跨区域访问S3桶,可以在初始化S3Client时开启自动重定向处理,修改createCredentialsWithAWSJdk方法的客户端构造逻辑:
public S3Client createCredentialsWithAWSJdk(String regionString) { try { AwsBasicCredentials awsCreds = AwsBasicCredentials.create( ACCESS_KEY, SECRET_KEY); S3ClientBuilder s3ClientBuilder = S3Client.builder().credentialsProvider(StaticCredentialsProvider.create(awsCreds)); if (regionString != null && !regionString.isEmpty()) { Region region = Region.of(regionString); s3ClientBuilder.region(region); } // 新增跨区域访问配置 s3ClientBuilder.serviceConfiguration(config -> config.crossRegionAccessEnabled(true)); S3Client s3Client = s3ClientBuilder.build(); return s3Client; } catch (S3Exception ex) { throw ex; } }
补充注意事项
- 确认你传入的
sLocationConstaints参数值正确,新加坡区域的正确标识为ap-southeast-1,注意不要出现拼写错误。 - 你可以通过
HeadBucketResponse的headBucketResult().bucketRegion()方法获取桶的实际所属区域,排查区域不匹配问题。
内容的提问来源于stack exchange,提问作者parita porwal
相关产品推荐
相关产品推荐

