Java 429使用aws sdk为s3对象生成预签名URL时请求过多
我有一个应用程序,这是一个数字资产管理系统。它显示缩略图。我已将这些缩略图设置为与AWS S3预签名URL一起使用:。这段代码正在工作,直到我更改通过请求处理的项目数量。应用程序有25、50、100、200个选项。如果选择100或200,进程将失败,并显示“错误:com.amazonaws.AmazonServiceException:请求太多(服务:null;状态代码:429;错误代码:null;请求ID:null)” 目前的过程如下: 执行搜索>通过返回该对象的预签名url的方法运行每个对象键 我们通过弹性容器服务运行该应用程序,该服务允许我们通过ContainerCredentialsProvider获取凭据 有关覆核守则:Java 429使用aws sdk为s3对象生成预签名URL时请求过多,java,amazon-web-services,amazon-s3,aws-sdk,http-status-code-429,Java,Amazon Web Services,Amazon S3,Aws Sdk,Http Status Code 429,我有一个应用程序,这是一个数字资产管理系统。它显示缩略图。我已将这些缩略图设置为与AWS S3预签名URL一起使用:。这段代码正在工作,直到我更改通过请求处理的项目数量。应用程序有25、50、100、200个选项。如果选择100或200,进程将失败,并显示“错误:com.amazonaws.AmazonServiceException:请求太多(服务:null;状态代码:429;错误代码:null;请求ID:null)” 目前的过程如下: 执行搜索>通过返回该对象的预签名url的方法运行每个对象
String s3SignedUrl(String objectKeyUrl) {
// Environment variables for S3 client.
String clientRegion = System.getenv("REGION");
String bucketName = System.getenv("S3_BUCKET");
try {
// S3 credentials get pulled in from AWS via ContainerCredentialsProvider.
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withRegion(clientRegion)
.withCredentials(new ContainerCredentialsProvider())
.build();
// Set the pre-signed URL to expire after one hour.
java.util.Date expiration = new java.util.Date();
long expTimeMillis = expiration.getTime();
expTimeMillis += 1000 * 60 * 60;
expiration.setTime(expTimeMillis);
// Generate the presigned URL.
GeneratePresignedUrlRequest generatePresignedUrlRequest =
new GeneratePresignedUrlRequest(bucketName, objectKeyUrl)
.withMethod(HttpMethod.GET)
.withExpiration(expiration);
return s3Client.generatePresignedUrl(generatePresignedUrlRequest).toString();
} catch (AmazonServiceException e) {
throw new AssetException(FAILED_TO_GET_METADATA, "The call was transmitted successfully, but Amazon " +
"S3 couldn't process it, so it returned an error response. Error: " + e);
} catch (SdkClientException e) {
throw new AssetException(FAILED_TO_GET_METADATA, "Amazon S3 couldn't be contacted for a response, or " +
"the client couldn't parse the response from Amazon S3. Error: " + e);
}
}
这是我们处理项目的部分:
// Overwrite the url, it's nested deeply in maps of maps.
for (Object anAssetList : assetList) {
String assetId = ((Map) anAssetList).get("asset_id").toString();
if (renditionAssetRecordMap.containsKey(assetId)) {
String s3ObjectKey = renditionAssetRecordMap.get(assetId).getThumbObjectLocation();
((Map) ((Map) ((Map) anAssetList)
.getOrDefault("rendition_content", new HashMap<>()))
.getOrDefault("thumbnail_content", new HashMap<>()))
.put("url", s3SignedUrl(s3ObjectKey));
}
}
//覆盖url,它深深嵌套在地图的地图中。
用于(对象集合列表:集合列表){
字符串assetId=((映射)anAssetList.get(“资产id”).toString();
if(格式副本AssetRecordMap.containsKey(assetId)){
字符串s3ObjectKey=renditionAssetRecordMap.get(assetId.getThumbObjectLocation();
((地图)((地图)((地图)设置列表)
.getOrDefault(“格式副本内容”,新的HashMap()))
.getOrDefault(“缩略图内容”,新的HashMap()))
.put(“url”,s3SignedUrl(s3ObjectKey));
}
}
任何指导都将不胜感激。希望有一个简单的解决方案,并且希望可以在AWS端进行配置。否则,现在我正在考虑为此添加一个进程,以批量生成URL。问题与生成预签名URL无关。这些都是在没有与服务交互的情况下完成的,因此不可能对其进行速率限制。预签名URL使用HMAC-SHA算法向服务证明拥有凭据的实体已授权特定请求。HMAC-SHA的单向(不可逆)特性允许完全在运行代码的机器上生成这些URL,而无需服务交互 但是,重复获取凭据似乎很可能是异常的实际原因,而您似乎在不必要地反复这样做 这是一项昂贵的操作:
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withRegion(clientRegion)
.withCredentials(new ContainerCredentialsProvider())
.build();
每次您再次调用它时,必须再次获取凭据。这实际上是你达到的极限
只构建一次s3client
,然后重构s3SignedUrl()
以期望传入该对象,以便重用它
除了解决
429
错误之外,您还应该看到显著的性能改进。该问题与生成预签名URL无关。这些都是在没有与服务交互的情况下完成的,因此不可能对其进行速率限制。但是,重复获取凭据似乎很可能是异常的实际原因,而您似乎在不必要地反复这样做。只构建s3client一次,然后重构s3SignedUrl()
,以期望传入该对象。你也应该看到一个显著的性能改进。谢谢你,迈克尔,就是这样。非常感谢。我希望我能把这句话作为答案。