Проблемы при загрузке больших файлов в Amazon S3 - PullRequest
15 голосов
/ 15 января 2011

Я пытался использовать пример кода Amazon-SDK (Java) S3TransferProgressSample.java для загрузки больших файлов в хранилище Amazon-S3 ( также размещено здесь в документации AWS ).

Но когдаЯ пытаюсь загрузить файлы размером 11 ГБ, загрузка застревает в разных точках с сообщением об ошибке:

Unable to upload file to Amazon S3: Unable to upload part: Unable toexecute HTTP request: Unbuffered entity enclosing request can not be repeated " (attached screenshot). 

Похоже, что после возникновения IOException SDK не может повторить запрос (см. Ниже),

Кто-нибудь сталкивался с этим?Какова лучшая практика для решения этой проблемы?Любой код приветствуется.

 INFO: Received successful response: 200, AWS Request ID:
 2B66E7669E24DA75<br> Jan 15, 2011 6:44:46 AM
 com.amazonaws.http.HttpClient execute<br> INFO: Sending Request: PUT
 s3.amazonaws.com /test_file_upload/autogenerated.txt Parameters:
 (uploadId:
     m9MqxzD484Ys1nifnX._IzJBGbCFIoT_zBg0xdd6kkZ4TAtmcG0lXQOE.LeiSEuqn6NjcosIQLXJeKzSnKllmw--, partNumber: 1494, )<br> Jan 15, 2011 6:45:10 AM
     org.apache.commons.httpclient.HttpMethodDirector executeWithRetry<br>
     **INFO: I/O exception (java.net.SocketException) caught when processing request: Connection reset by peer: socket write error**<br>
     Jan 15, 2011 6:45:10 AM
     org.apache.commons.httpclient.HttpMethodDirector executeWithRetry<br>
     INFO: Retrying request<br> Jan 15, 2011 6:45:12 AM
     com.amazonaws.http.HttpClient execute<br> WARNING: Unable to execute
     HTTP request: Unbuffered entity enclosing request can not be
     repeated.<br> Jan 15, 2011 6:45:12 AM
     org.apache.commons.httpclient.HttpMethodDirector executeWithRetry<br>
     **INFO: I/O exception (java.net.SocketException) caught when processing request: Connection reset by peer: socket write error**<br>
     Jan 15, 2011 6:45:12 AM
     org.apache.commons.httpclient.HttpMethodDirector executeWithRetry<br>
     INFO: Retrying request<br> Jan 15, 2011 6:45:13 AM
     org.apache.commons.httpclient.HttpMethodDirector executeWithRetry<br>
     **INFO: I/O exception (java.net.SocketException) caught when processing request: Connection reset by peer: socket write error**<br>
     Jan 15, 2011 6:45:13 AM
     org.apache.commons.httpclient.HttpMethodDirector executeWithRetry<br>
     INFO: Retrying request<br> Jan 15, 2011 6:45:13 AM
     com.amazonaws.http.HttpClient execute<br>
     **WARNING: Unable to execute HTTP request: Unbuffered entity enclosing request can not be repeated.**<br> Jan 15, 2011 6:45:14 AM
     com.amazonaws.http.HttpClient execute<br> WARNING: Unable to execute
     HTTP request: Unbuffered entity enclosing request can not be
     repeated.<br> Jan 15, 2011 6:45:14 AM com.amazonaws.http.HttpClient
     execute<br> WARNING: Unable to execute HTTP request: Unbuffered entity
     enclosing request can not be repeated.<br> Jan 15, 2011 6:45:14 AM
     com.amazonaws.http.HttpClient execute<br> WARNING: Unable to execute
     HTTP request: Unbuffered entity enclosing request can not be
     repeated.<br> Jan 15, 2011 6:45:15 AM com.amazonaws.http.HttpClient
     execute<br> WARNING: Unable to execute HTTP request: Unbuffered entity
     enclosing request can not be repeated.<br> Jan 15, 2011 6:45:16 AM
     com.amazonaws.http.HttpClient execute<br> WARNING: Unable to execute
     HTTP request: Unbuffered entity enclosing request can not be
     repeated.<br> Jan 15, 2011 6:45:16 AM

 com.amazonaws.http.HttpClient
     execute<br> WARNING: Unable to execute HTTP request: Unbuffered entity
     enclosing request can not be repeated.<br> Jan 15, 2011 6:45:17 AM
     com.amazonaws.http.HttpClient execute<br> WARNING: Unable to execute
     HTTP request: Unbuffered entity enclosing request can not be
     repeated.<br> Jan 15, 2011 6:45:19 AM com.amazonaws.http.HttpClient
     execute<br> WARNING: Unable to execute HTTP request: Unbuffered entity
     enclosing request can not be repeated.<br> Jan 15, 2011 6:45:19 AM
     com.amazonaws.http.HttpClient execute<br> ....<br> Jan 15, 2011
     6:45:21 AM com.amazonaws.http.HttpClient handleResponse<br>
     **INFO: Received successful response: 204, AWS Request ID: E794B8FCA4C3D007**<br> Jan 15, 2011 6:45:21 AM
     com.amazonaws.http.HttpClient execute<br> ...<br> Jan 15, 2011 6:45:19
     AM com.amazonaws.http.HttpClient execute<br> INFO: Sending Request:
     DELETE s3.amazonaws.com /test_file_upload/autogenerated.txt
     Parameters:<br> ...<br> Jan 15, 2011 6:47:01 AM
     com.amazonaws.http.HttpClient handleErrorResponse<br> INFO: Received
     error response: Status Code: 404, AWS Request ID: 0CE25DFE767CC595,
     AWS Error Code: NoSuchUpload, AWS Error Message: The specified upload
     does not exist. The upload ID may be invalid, or the upload may have
     been aborted or completed.<br>

Ответы [ 5 ]

18 голосов
/ 15 января 2011

Попробуйте использовать API низкого уровня .

Это даст вам гораздо больше контроля, когда что-то пойдет не так, как это может случиться с файлом объемом 11 ГБ.

Запросы к и от S3 время от времени терпят неудачу. С помощью низкоуровневого API вы сможете повторить часть загрузки, если она не удалась.

Немного переформулируем пример в документации Amazon:

// Step 2: Upload parts.
long filePosition = 0;
for (int i = 1; filePosition < contentLength; i++) {
    // Last part can be less than 5 MB. Adjust part size.
    partSize = Math.min(partSize, (contentLength - filePosition));

    // Create request to upload a part.
    UploadPartRequest uploadRequest = new UploadPartRequest()
                .withBucketName(existingBucketName).withKey(keyName)
                .withUploadId(initResponse.getUploadId()).withPartNumber(i)
                .withFileOffset(filePosition)
                .withFile(file)
                .withPartSize(partSize);

    // repeat the upload until it succeeds.
    boolean anotherPass;  
        do {
              anotherPass = false;  // assume everythings ok
              try {
                  // Upload part and add response to our list.
                  partETags.add(s3Client.uploadPart(uploadRequest).getPartETag());
              } catch (Exception e) {
                    anotherPass = true; // repeat
              }
        } while (anotherPass);

     filePosition += partSize;
}

   // Step 3: complete.
   CompleteMultipartUploadRequest compRequest = new 
                     CompleteMultipartUploadRequest(
                                existingBucketName, 
                                keyName, 
                                initResponse.getUploadId(), 
                                partETags);

   s3Client.completeMultipartUpload(compRequest);

Примечание. Я не являюсь Java-разработчиком, поэтому мог бы синтаксически все испортить, но, надеюсь, это приведет вас в правильном направлении. Кроме того, вы захотите добавить «счетчик повторов», чтобы предотвратить бесконечный цикл, если повторная загрузка не удалась.

4 голосов
/ 23 февраля 2013

Я думаю, вам стоит попробовать Multipart API, поддерживаемый AWS.

Проверьте это: http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/TransferManager.html

3 голосов
/ 30 октября 2012

В качестве примечания можно указать 404 ошибки, если попытаться выполнить многоэлементную загрузку на ключ, который уже находится в многочастной загрузке.

1 голос
/ 25 апреля 2014

Я хотел добавить комментарий к ответу Джеффа Эпплфорда, но ТАК не позволил бы мне.В целом, его ответ на использование низкоуровневого API работает хорошо, но даже если у нас теперь есть цикл do-while, для цикла разработан встроенный алгоритм повторения.В его фрагменте кода позиция файла увеличивается только в случае успеха, в противном случае вы снова загружаете ту же часть.

1 голос
/ 06 февраля 2011

Ответ Джеффа Эпплфорда работает на меня. Однако я бы добавил && retryCount

Aviad

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...