aldy120 / s3-note

Note for Amazon S3
0 stars 0 forks source link

Conditional request #2

Open aldy120 opened 5 years ago

aldy120 commented 5 years ago

發出 request 的時候,在 header 裡面放 validator ,用來讓 server 知道目前現在 client 的狀況,以此決定要發什麼 response 。 validator 通常是以下兩種。

aldy120 commented 5 years ago

實際上的例子可能是下面這樣。

首次發送 request

Client 發出 request 給 Server ,因為這是第一次發請求, client 這時還沒有 cache 。 Server 收到請求,回傳 response ,這時這個 response 最好的情況下會帶有 validator header Last-ModifiedEtag,看 server 高興,有可能只有一個 validator ,也可能沒有 。

第二次發送 request

有一個 header 叫做 Cache-Control 這負責告訴 client 說,這個 response 你可以放你在你的 cache ,可以放多久。通常來說,如果時間還沒超過 Cache-Control 的時間的話, Client 就不會特別發 request 給 server ,而是會直接使用用 client cache 的內容。

一但超過了 Cache-Control 所定出的時間, client 就會發送請求給 server 索取資料。此時發出的時候, client request header 會有 validator ,用來讓 server 知道現在 client 的狀況,讓 server 知道 client 現在擁有哪個版本的資料。通常使用的 header 有 If-Modified-SinceIf-None-Match 。這可以讓 server 判斷,如果在特定日期之後有更新或有新版本,就會回傳完整的新資料,否則會回傳 304 Not Modified 。如果有新版本,那就回傳 200 並且回傳最新版本的資料,附上最新的 validator header (Etag and Last-Modified)。

由於 304 並沒有傳回完整的資料,相對來說節省了一些網路頻寬,只是告訴 client 說你的 cache 雖然過期了,但是由於我們這邊也沒有更新版的資料,所以你可以繼續使用你那邊的 cache 。

aldy120 commented 5 years ago

Integrity of a partial download

如果有個下載的動作做到一半就被取消,要是可以支援續傳的話就很理想了。 image

如果 server 支援 partial download 的話,會在 header 裡面通知,例如 Accept-Range: bytes 。如果下次 client 想發出續傳的 request ,只需要在 header 加上 Range 即可。

唯一可能的問題是,要是兩次下載之間, server 的檔案有異動版本的話,可能兩次續傳的部分會無法接在一起,造成檔案損毀。因此這時 validator 又派上用場了。 image

如果 server 發現續傳 request 的 validator 跟目前版本不一致,會回傳 412 Precondition Failed 。 client 收到之後,就會知道他之前下載的是白費功夫,所以會再次發送一個不帶有 validator 的 request 。

aldy120 commented 5 years ago

Avoiding the lost update problem with optimistic locking

編輯功能是常常在 CMS 裡面會出現的,通常我們會需要做到以下事情。

但是,要是你修改文章花太久時間,很可能在你送出更新的時候,別人已經試圖更新一版本過了,那這時候你更新就會完全讓別人的努力白費。這種更新蓋來蓋去的問題,就叫做 Race Condition 。 image

這兩個 client 必有一個受傷,但是我們通常使用 optimistic locking algorithm ,讓後來修改的人無法修改,而不是讓第一個人的修改被覆蓋掉。

因此我們在發送 PUT request 修改檔案的時候,會在 request 的時候加上 validator (通常是 If-MatchIf-Unmodified-Since),如此一台相當於告訴 server ,目前 client 身上最新的版本。一但 server 發現 client 身上明明不是最新的版本還想要 PUT ,就會回應 412 Precondition Failed 。當發生這種情況的時候, client 有權決定如何處理此種情形。常見的方法有兩種,第一種是直接讓 user 放棄當前修改,從新的版本開始從頭改起。另一種則 diff 出最新版本 (這就要多花一次 request 取回最新版了) 跟舊版的差異,讓 user 可以更清楚的知道最新版本做了什麼樣的更動。

Dealing with the first upload of a resourceSection

當第一次上傳的時候,如果有兩人同時上傳初版本,我們需要在這時候避免 race condition。因此我們在 If-None-Match: * ,要是 server 有任何版本,都會回傳 412 Percondition Failimage