6

nềnLàm thế nào để xác định rằng Mã trạng thái HTTP 304 (NotModified) không phải là một điều kiện lỗi bên trong API GetObject của Amazon S3?

Tôi cố gắng để tận dụng S3 như lớp bộ nhớ đệm lớn một 'vô cực' đối với một số 'khá' tài liệu XML tĩnh. Tôi muốn đảm bảo rằng ứng dụng máy khách (sẽ chạy trên hàng nghìn máy đồng thời và yêu cầu các tài liệu XML nhiều lần mỗi giờ) chỉ tải xuống các tài liệu XML này nếu nội dung của chúng đã thay đổi kể từ lần cuối cùng ứng dụng khách tải xuống chúng.

Cách tiếp cận

Trên Amazon S3, chúng ta có thể sử dụng HTTP ETag cho việc này. Theo mặc định, đối tượng Amazon S3 có ETAG của chúng được đặt thành mã băm MD5 của đối tượng.

Sau đó, chúng tôi có thể chỉ định mã băm MD5 của tài liệu XML bên trong thuộc tính GetObjectRequest.ETagToNotMatch. Điều này đảm bảo rằng khi chúng tôi thực hiện cuộc gọi AmazonS3.GetObject (hoặc trong trường hợp của tôi là phiên bản async AmazonS3.BeginGetObjectAmazonS3.EndGetObject), nếu tài liệu được yêu cầu có cùng mã băm MD5 như được chứa trong GetObjectRequest.ETagToNotMatch thì S3 sẽ tự động trả lại mã trạng thái HTTP 304 (NotModified) và nội dung thực tế của tài liệu XML là không phải là được tải xuống.

Vấn đề

Vấn đề tuy nhiên là khi gọi AmazonS3.GetObject (hoặc nó async tương đương) API Amazon Net thực sự nhìn thấy mã HTTP Status 304 (NotModified) như là một lỗi và nó lại yêu cầu get ba thời gian và sau đó cuối cùng ném một số Amazon.S3.AmazonS3Exception: Maximum number of retry attempts reached : 3. Rõ ràng là tôi có thể thay đổi việc triển khai này để sử dụng AmazonS3.GetObjectMetaData và sau đó so sánh ETAG và sử dụng AmazonS3.GetObject nếu chúng không khớp, nhưng sau đó có hai yêu cầu đến S3 thay vì một yêu cầu khi tệp bị cũ. Quay lại Đầu trang | Tôi muốn có một yêu cầu bất kể tài liệu XML có cần tải xuống hay không.

Bất kỳ ý tưởng nào? Đây có phải là một lỗi hoặc tôi thiếu một cái gì đó? Có một số cách tôi có thể giảm số lần thử lại thành một và 'xử lý' ngoại lệ (mặc dù tôi cảm thấy 'yuck' về tuyến đường này).

Thực hiện

Tôi đang sử dụng AWS SDK cho .NET (phiên bản 1.3.14).

Đây là thực hiện của tôi (giảm nhẹ để giữ cho nó ngắn hơn):

public Task<GetObjectResponse> DownloadString(string key, string etag = null) { 

    var request = new GetObjectRequest { Key = key, BucketName = Bucket }; 

    if (etag != null) { 
     request.ETagToNotMatch = etag; 
    } 

    var task = Task<GetObjectResponse>.Factory.FromAsync(_s3Client.BeginGetObject, _s3Client.EndGetObject, request, null); 

    return task; 
} 

sau đó tôi gọi đây như:

var dlTask   = s3Manager.DownloadString("new one", "d7db7bc318d6eb9222d728747879b52e"); 
var responseTasks = new[] 
    { 
     dlTask.ContinueWith(x => _log.Error("Error downloading string.", x.Exception), TaskContinuationOptions.OnlyOnFaulted), 
     dlTask.ContinueWith(x => _log.Warn("Downloading string was cancelled."), TaskContinuationOptions.OnlyOnCanceled), 
     dlTask.ContinueWith(x => _log.Info(string.Format("Done with download: {0}", x.Result.ETag)), TaskContinuationOptions.OnlyOnRanToCompletion) 
    }; 

try { 
    Task.WaitAny(responseTasks); 
} catch (AggregateException aex) { 
    _log.Error("Error while processing download string.", aex); 
} 

_log.Info("Exiting..."); 

này sau đó tạo file log sản lượng này:

2011-10-11 13:21:20,376 [11] INFO Amazon.S3.AmazonS3Client - Received response for GetObject (id 2ee99002-d148-4572-b19b-29259534f48f) with status code NotModified in 00:00:01.6140812. 
2011-10-11 13:21:20,385 [11] INFO Amazon.S3.AmazonS3Client - Request for GetObject is being redirect to https://s3.amazonaws.com/x/new%20one. 
2011-10-11 13:21:20,789 [11] INFO Amazon.S3.AmazonS3Client - Retry number 1 for request GetObject. 
2011-10-11 13:21:22,329 [11] INFO Amazon.S3.AmazonS3Client - Received response for GetObject (id 2ee99002-d148-4572-b19b-29259534f48f) with status code NotModified in 00:00:01.1400356. 
2011-10-11 13:21:22,329 [11] INFO Amazon.S3.AmazonS3Client - Request for GetObject is being redirect to https://s3.amazonaws.com/x/new%20one. 
2011-10-11 13:21:23,929 [11] INFO Amazon.S3.AmazonS3Client - Retry number 2 for request GetObject. 
2011-10-11 13:21:26,508 [11] INFO Amazon.S3.AmazonS3Client - Received response for GetObject (id 2ee99002-d148-4572-b19b-29259534f48f) with status code NotModified in 00:00:00.9790314. 
2011-10-11 13:21:26,508 [11] INFO Amazon.S3.AmazonS3Client - Request for GetObject is being redirect to https://s3.amazonaws.com/x/new%20one. 
2011-10-11 13:21:32,908 [11] INFO Amazon.S3.AmazonS3Client - Retry number 3 for request GetObject. 
2011-10-11 13:21:40,604 [11] INFO Amazon.S3.AmazonS3Client - Received response for GetObject (id 2ee99002-d148-4572-b19b-29259534f48f) with status code NotModified in 00:00:01.2950718. 
2011-10-11 13:21:40,605 [11] INFO Amazon.S3.AmazonS3Client - Request for GetObject is being redirect to https://s3.amazonaws.com/x/new%20one. 
2011-10-11 13:21:40,621 [11] ERROR Amazon.S3.AmazonS3Client - Error for GetResponse 
Amazon.S3.AmazonS3Exception: Maximum number of retry attempts reached : 3 
    at Amazon.S3.AmazonS3Client.pauseOnRetry(Int32 retries, Int32 maxRetries, HttpStatusCode status, String requestAddr, WebHeaderCollection headers, Exception cause) 
    at Amazon.S3.AmazonS3Client.handleHttpResponse[T](S3Request userRequest, HttpWebRequest request, HttpWebResponse httpResponse, Int32 retries, TimeSpan lengthOfRequest, T& response, Exception& cause, HttpStatusCode& statusCode) 
    at Amazon.S3.AmazonS3Client.getResponseCallback[T](IAsyncResult result) 
2011-10-11 13:21:40,635 [10] INFO Example.Program - Exiting... 
2011-10-11 13:21:40,638 [19] ERROR Example.Program - Error downloading string. 
System.AggregateException: One or more errors occurred. ---> Amazon.S3.AmazonS3Exception: Maximum number of retry attempts reached : 3 
    at Amazon.S3.AmazonS3Client.pauseOnRetry(Int32 retries, Int32 maxRetries, HttpStatusCode status, String requestAddr, WebHeaderCollection headers, Exception cause) 
    at Amazon.S3.AmazonS3Client.handleHttpResponse[T](S3Request userRequest, HttpWebRequest request, HttpWebResponse httpResponse, Int32 retries, TimeSpan lengthOfRequest, T& response, Exception& cause, HttpStatusCode& statusCode) 
    at Amazon.S3.AmazonS3Client.getResponseCallback[T](IAsyncResult result) 
    at Amazon.S3.AmazonS3Client.endOperation[T](IAsyncResult result) 
    at Amazon.S3.AmazonS3Client.EndGetObject(IAsyncResult asyncResult) 
    at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endMethod, TaskCompletionSource`1 tcs) 
    --- End of inner exception stack trace --- 
---> (Inner Exception #0) Amazon.S3.AmazonS3Exception: Maximum number of retry attempts reached : 3 
    at Amazon.S3.AmazonS3Client.pauseOnRetry(Int32 retries, Int32 maxRetries, HttpStatusCode status, String requestAddr, WebHeaderCollection headers, Exception cause) 
    at Amazon.S3.AmazonS3Client.handleHttpResponse[T](S3Request userRequest, HttpWebRequest request, HttpWebResponse httpResponse, Int32 retries, TimeSpan lengthOfRequest, T& response, Exception& cause, HttpStatusCode& statusCode) 
    at Amazon.S3.AmazonS3Client.getResponseCallback[T](IAsyncResult result) 
    at Amazon.S3.AmazonS3Client.endOperation[T](IAsyncResult result) 
    at Amazon.S3.AmazonS3Client.EndGetObject(IAsyncResult asyncResult) 
    at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endMethod, TaskCompletionSource`1 tcs)<--- 

Trả lời

2

Tôi cũng đã đăng câu hỏi này trên diễn đàn nhà phát triển Amazon và nhận được thư trả lời từ nhân viên AWS chính thức:

Sau khi điều tra điều này, chúng tôi hiểu được vấn đề nhưng chúng tôi đang tìm kiếm để biết phản hồi về cách xử lý tốt nhất.

Cách tiếp cận đầu tiên là trả về hoạt động này với thuộc tính trên GetObjectResponse cho biết đối tượng không được trả lại hoặc đặt luồng đầu ra thành không. Điều này sẽ được sạch hơn để mã chống lại nhưng nó tạo ra một hành vi vi phạm nhẹ cho bất cứ ai dựa vào một ngoại lệ được ném, mặc dù sau khi 3 thử lại. Nó cũng sẽ là không phù hợp với thao tác CopyObject mà ném một ngoại lệ mà không cần phải thử lại toàn bộ.

Tùy chọn khác là chúng tôi ném một ngoại lệ tương tự như CopyObject mà giữ cho chúng tôi nhất quán và không có thay đổi đột phá nhưng khó khăn hơn để mã chống lại.

Nếu có ai có ý kiến ​​về cách xử lý việc này, vui lòng trả lời chủ đề này.

Norm

tôi đã thêm những suy nghĩ của tôi vào chủ đề, nếu ai khác quan tâm đến việc tham gia ở đây là liên kết:

AmazonS3.GetObject sees HTTP 304 (NotModified) as an error. Way to allow it?


LƯU Ý: Khi điều này đã được giải quyết bởi Amazon Tôi sẽ cập nhật câu trả lời của tôi để phản ánh kết quả.


UPDATE: (2012/01/24) Vẫn còn chờ đợi để biết thêm thông tin từ Amazon.

+0

Chúng tôi đã thực hiện điều này gần đây và tôi đã quyết định bản vá nhanh cho SDK AWS sẽ là câu trả lời hay nhất vì Amazon rõ ràng sẽ không sửa lỗi này sớm. https://github.com/skilitix/aws-sdk-net là ngã ba của chúng tôi sửa lỗi thử lại trên 304 và thêm boolean 'NotModified' vào' GetObjectResponse' - nếu tôi dành thời gian để tìm ra API tương thích ngược hơn Tôi sẽ gửi một bản vá cho Amazon (trong khi chờ đợi, chúng tôi chấp nhận PR: P). –

+0

@SimonBuchan Tuyệt vời! Tôi sẽ kiểm tra nó. – InvertedAcceleration

+0

Lưu ý rằng chúng tôi không bắt kịp với thượng lưu, chúng tôi đã có ~ 3 điểm phát hành phía sau, nhưng chúng dường như chỉ là các API mới và nên tự động hợp nhất. –

Các vấn đề liên quan