Google 云存储 - 将大对象重写到 "nearline" 存储桶时出现 SocketTimeoutException
Google Cloud Storage - SocketTimeoutException when rewriting a big object to "nearline" bucket
环境:
Java 客户端 ("google-api-services-storage", "v1-rev33-1.20.0") 使用 JSON API (com.google.api.services.storage.Storage class).
目标:
使用 Java 客户端将大对象从 "standard" 移动到 "nearline" 存储桶(文件大小为 512 MB)。
步骤:
使用 "rewrite" API 方法。
问题:
我在 20 秒内收到 SocketTimeoutException。
调查:
当我使用从 "standard" 桶重写到同一对象的另一个 "standard" 桶时,相同的代码工作正常。
我还尝试了 APIs Explorer 并创建了一个将对象从 "standard" 重写到 "nearline" 存储桶的请求。服务器在大约 27 秒内响应,响应中的 "totalBytesRewritten" 属性 大约是文件大小的一半。如何获取和处理这样的响应?
文档说:
"If the source and destination are different locations and/or storage classes, the rewrite method might require multiple calls."
我的代码(Java):
final Storage.Objects.Rewrite rewriteRequest = storage.objects().rewrite(
STANDARD_BUCKET_NAME,
SOURCE_OBJECT_PATH,
NEARLINE_BUCKET_NAME,
TARGET_OBJECT_PATH,
null // no metadata overriding
);
rewriteRequest.execute();
请帮忙
根据 documentation,如果文件被分割成块,您应该再次调用 rewrite,使用 rewrite 的第一个响应中返回的 'rewriteToken'。操作将恢复,再处理一大块数据。这应该重复直到响应有 getDone() == true。
我对 java api 的实现:
private void rewriteUntilDone(final String sourceBucket, final String sourceKey,
final String destBucket, final String destKey) throws IOException {
rewriteUntilDone(sourceBucket, sourceKey, destBucket, destKey, null);
}
private void rewriteUntilDone(final String sourceBucket, final String sourceKey,
final String destBucket, final String destKey,
@Nullable final String rewriteToken)
throws IOException {
Storage.Objects.Rewrite rewrite = googleStorage.objects().rewrite(sourceBucket, sourceKey, destBucket, destKey, null);
if (rewriteToken != null) {
rewrite.setRewriteToken(rewriteToken);
}
RewriteResponse rewriteResponse = rewrite.execute();
if (!rewriteResponse.getDone()) {
String rewriteToken2 = rewriteResponse.getRewriteToken();
BigInteger totalBytesRewritten = rewriteResponse.getTotalBytesRewritten();
log.debug("Rewriting not finished, bytes completed: {}. Calling rewrite again with token {}", totalBytesRewritten, rewriteToken2);
rewriteUntilDone(sourceBucket, sourceKey, destBucket, destKey, rewriteToken2);
}
}
编辑:
此外,您可能必须增加读取超时。似乎重写在 27 秒后响应,但默认超时为 20 秒。 Wrap your GoogleCredentials to set the read timeout
环境:
Java 客户端 ("google-api-services-storage", "v1-rev33-1.20.0") 使用 JSON API (com.google.api.services.storage.Storage class).
目标:
使用 Java 客户端将大对象从 "standard" 移动到 "nearline" 存储桶(文件大小为 512 MB)。
步骤:
使用 "rewrite" API 方法。
问题:
我在 20 秒内收到 SocketTimeoutException。
调查:
当我使用从 "standard" 桶重写到同一对象的另一个 "standard" 桶时,相同的代码工作正常。
我还尝试了 APIs Explorer 并创建了一个将对象从 "standard" 重写到 "nearline" 存储桶的请求。服务器在大约 27 秒内响应,响应中的 "totalBytesRewritten" 属性 大约是文件大小的一半。如何获取和处理这样的响应?
文档说:
"If the source and destination are different locations and/or storage classes, the rewrite method might require multiple calls."
我的代码(Java):
final Storage.Objects.Rewrite rewriteRequest = storage.objects().rewrite(
STANDARD_BUCKET_NAME,
SOURCE_OBJECT_PATH,
NEARLINE_BUCKET_NAME,
TARGET_OBJECT_PATH,
null // no metadata overriding
);
rewriteRequest.execute();
请帮忙
根据 documentation,如果文件被分割成块,您应该再次调用 rewrite,使用 rewrite 的第一个响应中返回的 'rewriteToken'。操作将恢复,再处理一大块数据。这应该重复直到响应有 getDone() == true。
我对 java api 的实现:
private void rewriteUntilDone(final String sourceBucket, final String sourceKey,
final String destBucket, final String destKey) throws IOException {
rewriteUntilDone(sourceBucket, sourceKey, destBucket, destKey, null);
}
private void rewriteUntilDone(final String sourceBucket, final String sourceKey,
final String destBucket, final String destKey,
@Nullable final String rewriteToken)
throws IOException {
Storage.Objects.Rewrite rewrite = googleStorage.objects().rewrite(sourceBucket, sourceKey, destBucket, destKey, null);
if (rewriteToken != null) {
rewrite.setRewriteToken(rewriteToken);
}
RewriteResponse rewriteResponse = rewrite.execute();
if (!rewriteResponse.getDone()) {
String rewriteToken2 = rewriteResponse.getRewriteToken();
BigInteger totalBytesRewritten = rewriteResponse.getTotalBytesRewritten();
log.debug("Rewriting not finished, bytes completed: {}. Calling rewrite again with token {}", totalBytesRewritten, rewriteToken2);
rewriteUntilDone(sourceBucket, sourceKey, destBucket, destKey, rewriteToken2);
}
}
编辑: 此外,您可能必须增加读取超时。似乎重写在 27 秒后响应,但默认超时为 20 秒。 Wrap your GoogleCredentials to set the read timeout