1. 程式人生 > 實用技巧 >http的快取機制

http的快取機制

http的快取機制

前言

瞭解http的快取機制有利於提高網站的效能,減少伺服器的壓力,加速響應客戶端的請求。

什麼是http的快取?

httpd的快取是在瀏覽器和web伺服器或web代理伺服器之間進行的。當客戶端傳送請求時,如果本地的瀏覽器快取有“副本”(即請求的資料)的話,且副本在有效時間內的話,那麼資料將直接從瀏覽器快取中返回,這樣,就不需要到後端原始伺服器上進行載入了,從而達到減少網路頻寬、提高web伺服器效能的目的。

http的快取通常指的是瀏覽區快取、代理快取和web cache快取。通常這些機制都可以用來快取伺服器響應的資料。當然有些資料是不能快取的,比如客戶端的私有資訊,如cookie資訊就不能快取。通常這需要取決於你的快取策略。當客戶端發起請求時,首先會到本地瀏覽器快取中查詢是否有該web資源的副本(即請求的資料),如果有,且在有效期內的話,則直接返回給客戶端,如果沒有則向代理伺服器或web cache伺服器發起請求,如果有且是有效的話,則直接返回給客戶端。如果有,但是過期的話,那麼就需要向原始伺服器發起新鮮度驗證,以驗證該web資源是否被更新過。如果,這些快取機制中都沒有的話,那麼直接有原始伺服器(或者稱為後端伺服器)進行響應,然後根據響應的內容,來決定是否需要對這些資料進行快取。這就是http的快取機制。因此,快取具有如下好處:


快取的好處

1、減少了網路出口頻寬

2、如果快取中有請求的web資源,且是有效的話,則直接構建響應報文並響應給客戶端。這些請求就不需要交給後端的伺服器進行處理了,從而減少了伺服器的壓力,提高了web伺服器的效能。

3、可以減少網路傳輸延遲,加速響應客戶度的請求。以提高客戶端體驗。

公共快取和私有快取

公共快取:即資料可以共享給多個使用者

私有快取:快取的資料只能被自己使用(如cookie資訊就不能快取在公共快取上)。比如瀏覽器通常快取的是使用者的私有資訊。


快取機制處理的幾個步驟:

1、接受請求

2、解析請求,由於具備解析的功能,因此該快取具備代理的功能

3、查詢該快取上是否有該請求的web資源的副本

4、如果有,則需要檢驗該web資源的新鮮度,確保該web資源是否被更改過。如果沒有,則直接有後端伺服器進行響應,並確定是否將該資料快取在該快取上,然後在響應給客戶端。

5、如果該快取有快取並且是有效的話,則直接構建響應報文

6、該快取將響應報文返回給客戶端

7、將此過程記錄到日誌中



快取資源的新鮮度檢測

快取資源的新鮮度檢測用來檢測該資源是否是最先的。快取資源的新鮮度檢測有二種方式:

一、根據資源的過期時間進行檢測

1、在http 1.0協議中,通過原始伺服器返回的響應首部Expires來確定該資源是否是最新的。這個時間是一個絕對時間。

當客戶端第一次請求時,由於快取中沒有該資源的副本,因此,會將請求交給後端原始伺服器進行處理。當原始伺服器響應該資料時,則會返回一個響應首部Expires:date。比如:Expires:30 May 2015,表示該資源可以被快取到2015年5月30號。該資源被快取,最後再響應給客戶端。當客戶端下一次在請求相同的資源時,由於該快取上有該資源的副本,從而需要對該資源的副本進行新鮮度驗證。如果請求的時間是在這個時間內的話,那麼表示該資源沒有過期,則直接有該快取機制直接構建響應報文直接響應給客戶端,並返回304狀態碼。如果請求的時間已經超過了該時間,表示該資源已經過期,需要該快取向後端的原始伺服器發起請求。後端原始伺服器接受請求後,即使後端伺服器沒有對該資源做任何修改,仍然會響應最新資料,且響應時返回Expires:date的首部,以告知該資源新的過期時間,當快取機制快取該資源時,會覆蓋原來舊的資源(不管返回的資源是否被修改,快取機制都會將舊資源覆蓋掉),並最終響應給客戶端,並返回200的狀態碼。

如果客戶端的時間與快取機制的時間不同步的話,那麼會導致快取資源很可能是過期的。因此,這種方式並不是可靠


2、在http 1.1協議中,通過原始伺服器返回的響應報文首部Cache-Control:max-age來確定該資源是否是最新的。這個時間是一個相對時間。

當客戶端第一次請求時,由於快取中沒有該資源的副本,因此,會將請求交給後端原始伺服器進行處理。當原始伺服器響應該資料時,會返回一個響應首部cache-control:max-age。比如Cache-Control:max-age=3600,表示該資源可以快取一個小時。該資源會被快取,最後再響應給客戶端。當客戶端下一次在請求相同的資源時,由於該快取上有該資源的副本,從而需要對該資源的副本進行新鮮度驗證。如果請求的資源是在這一小時內進行的話,那麼表示快取是有效的,快取機制直接將快取上的資源構建響應報文並返回給客戶端。並返回304的狀態碼。如果請求的資源不是在這一小時內進行的話,表示該資源時過期的。然後該快取機制向後端的原始伺服器發起請求,後端的原始伺服器接受請求並對其響應,不管該資源是否被修改過,後端原始伺服器仍然會響應最新資料。且返回一個cache-control:max-age=N,表示該資源可以快取N時間。當快取機制快取該資源時,會覆蓋原來舊的資源(不管返回的資源是否被修改,快取機制都會將舊資源覆蓋掉),並最終響應給客戶端,並返回200的狀態碼。



二、根據條件式請求來進行新鮮度檢測

條件式請求首部有2個:If-Modified-Since和If-None-Match

If-Modified-Since請求首部是根據請求資源的最近一次的修改時間來判斷資源是否是最新的。

當客戶端第一次請求時,由於快取中沒有該資源的副本,因此,會將請求交給後端原始伺服器進行處理。後端原始伺服器響應時,快取機制會將該資源快取起來,然後在響應給客戶端。當客戶端下次請求相同資源時。快取機制會在請求首部新增一個If-Modified-Since:date首部,告訴原始伺服器在這個時間後(這裡指的是date這個時間)後,該資源是否被更新過,如果原始伺服器沒有更改該資源,則響應304狀態碼給快取機制,這樣快取機制就會將快取上的資源構建響應報文並返回給客戶端,響應給客戶端的狀態碼為200。如果該資源被更該過,則響應200狀態碼,並將最新資料返回給快取機制,且響應首部中包含一個Last-Modified首部,以告知該資源最近一次被修改的時間。最終快取機制將其快取下來並返回給客戶端,響應給客戶端的狀態碼為200。


If-Modified-Since請求首部是根據請求資源的Etag標籤來判斷該資源是否是最新的。只要資源沒有被改變,則Etag標籤就不會改變。一旦資源改變了,則Etag標籤就會發生改變。

當客戶端第一次請求時,由於快取中沒有該資源的副本,因此,會將請求交給後端原始伺服器進行處理。後端原始伺服器響應時,快取機制會將該資源快取起來,然後在響應給客戶端。當客戶端下次請求相同資源時。快取機制會在請求首部新增一個If-None-Match首部,當後端伺服器接受請求時會將If-None-Match的值與本地資源的Etag值進行比較,如果相同則表示該資源沒有被改變,仍然是最新的,則後端原始伺服器返回304狀態碼。然後快取機制將快取上的資源構建響應報文並返回給客戶端,響應給客戶端的狀態碼為200。如果If-None-Match的值與後端原始伺服器資源的Etag值不一樣,則表示該資源被更新了,則後端原始伺服器響應最新資料和該資源最新的Etag給快取機制,響應狀態碼為200。最後在將資源響應給客戶端,狀態碼為200。


那麼是基於時間的條件式請求精確些還是基於Etag標籤的條件式請求精確些?

其實後者通過對比ETag首部來判斷快取資料的新鮮度比前者通過資料的最近一次修改時間判斷快取資料的新鮮度更加的精確。為什麼呢?這是因為前者通過資料的最近一次時間來判斷快取資料的新鮮度,它所能夠精確的時間範圍僅僅到秒而已。也就是說,當後端原始伺服器上的資料修改在秒以內完成的話,則這種判斷方式將會導致錯誤。這樣,快取機制上的快取的資料和後端原始伺服器上的資料將會不一致。而通過對比ETag首部則不一樣,一旦原始伺服器上的資料發生改變,則ETag值也一定會發生改變。所以後者很好了解決了前者的漏洞,比前者判斷的更加精確。



小結

根據資源的過期時間來判斷資源是否是最新的,你會發現,只有資源是過期的,那麼就後端原始伺服器就必須響應最新資料給快取機制(不管後端原始伺服器上的資源是否改變,都會返回資源)。有時候快取上的資源雖然是過期的,但是後端原始伺服器並沒有對這些資源做任何修改,因此該資源仍然是最新的,所以,在這種情況下,後端原始伺服器就不需要再次傳送該資源了。從而可以避免一些相同資料的重複傳輸。

而條件式請求首部雖然可以避免相同資料的重複傳輸,但是每次請求時,快取機制都會做條件式請求,因此,這種請求方式也會消耗一些時間,因此兩種方式好像都並不是那麼完美。因此,常見新鮮度檢測的方式就是將這兩種方式結合起來一次來使用。


過期時間和條件式請求的結合使用

當客戶端第一次請求時,由於快取中沒有該資源的副本,因此,會將請求交給後端原始伺服器進行處理。當原始伺服器響應該資料時,會返回一個響應首部cache-control:max-age。比如Cache-Control:max-age=3600,表示該資源可以快取一個小時。該資源會被快取,最後再響應給客戶端。當客戶端下一次在請求相同的資源時,由於該快取上有該資源的副本,從而需要對該資源的副本進行新鮮度驗證。如果請求的資源是在這一小時內進行的話,那麼表示快取是有效的,快取機制直接將快取上的資源構建響應報文並返回給客戶端。並返回304的狀態碼。

如果請求的時間已經超過了該時間,表示該資源已經過期,則快取機制將會發起條件式請求,比如會在請求首部加上If-None-Match:abcd首部,後端伺服器接受請求後,將請求首部中的If-None-Match首部中的值abcd與後端伺服器上該資源的Etag值進行對比。如果Etag值一樣表示該資源沒有被修改,資源仍然是最新的,則後端原始伺服器返回304狀態碼給快取機制,並返回Cache-Control:max-age=N首部給快取機制,表示該資源可以快取N這麼長的時間。然後快取機制將從快取上的資源構建響應報文給客戶端,響應狀態碼為200。如果Etag值不一樣,表示資料被修改過,則後端原始伺服器將會將最新資源和該資源的Etag值響應給快取機制,並最終響應給客戶端,狀態碼為200。

說明:一旦做了新鮮度檢測(即請求達到了原始伺服器),其響應客戶端成功的狀態碼為200。不管資源是否被更新過。


當兩種方式集合起來一起使用時,其http的請求流程圖如下:

客戶端第一次請求流程如下:

wKiom1UpHxXRzEDdAACpCFXW1SQ751.jpg

客戶端下次請求流程為:

wKiom1UpHyKxlQwTAAFEaDQJnI8186.jpg

http的相關快取首部引數

在快取伺服器或原始伺服器定義的首部

1Expires:用來定義web物件的過期日期或時間,通常為GMT格式。Expireshttp 1.0的東西,現在瀏覽器預設使用的是http 1.1,所有它的作用基本忽略。不過Expires有一個缺點就是它的過期時間使用的是絕對時間,如果客戶端和伺服器時間不同步(或跨時區),則會導致誤差。在http 1.1中使用Cache-Control:max-age替代了。

2Cache-Control:這是所有的快取機制必須遵守的快取指示。它有許多子命令,分別如下:

public:該響應可以快取在瀏覽器或web代理或web快取伺服器中,該快取作為公共快取,可以在多個使用者之間共享。這也是預設的快取機制。

private:該響應作為private快取,只能快取在瀏覽器中,不能快取在web代理或web快取伺服器等公共快取上。如使用者的cookie資訊、登陸時使用的使用者名稱和密碼等都只能快取在private快取上,因此只能快取在瀏覽器這樣的private快取上,不能快取在公共快取上。如cdn。

no-cache:表示該響應可以快取,在使用該快取物件時,必須先做新鮮度驗證。

no-store:表示該響應不能快取,通常這些資料是一些敏感資料。

max-age:定義快取的有效時長。它比Expires的優先順序高,也就是說max-age設定的時間會忽略Expires中設定的時間。max-age設定的是一個相對時間,比如:max-age=3600,表示該資源可以快取1個小時。如果web物件過期了,則快取伺服器必須向後端伺服器新鮮度確認。

s-maxage:這是用來定義公共快取,而max-age是用來定義私有快取的。如果該引數不存在,則取決於max-age。

must-revalidate:如果緩衝物件過期,必須傳送到伺服器端重新進行新鮮度驗證。


3Etag:響應首部,用於在響應報文中為某web資源定義版本識別符號;該版本識別符號必須是唯一的,一旦該響應報文的資料發生改變,則Etag值也會發生改變。它可以用來驗證快取資源是否被更新過。當快取伺服器發起條件式請求時,會在請求報文中新增一個請求首部If-None-Match:value,該value就是原始伺服器響應的Etag值。當原始伺服器接受該請求時時,會對比請求首部中的Etag值與本地資源的Etag值是否一致,從而判斷原始伺服器上的資源是否被更新過。


4Last-Modified:響應首部,用於通知快取伺服器或客戶端其請求的資源最近一次的修改時間。該響應首部也可以用來判斷請求的資源是否被更新過。當快取伺服器發起條件式請求時,會在請求報文中新增一個請求首部If-Modified-Since:date,這個date時間就是當時原始伺服器返回的響應首部中Last-Modified的值,當原始伺服器接受請求時,會對比本地資源的最一次修改時間和該date值,從而判斷該資源是否被更新過。

5If-Modified-Since:條件式請求首部,如果在此請求首部指定的時間後其請求的web資源發生了更改,則伺服器響應更改後的內容,否則,則響應304(not modified)


6If-None-Match:條件式請求首部,web伺服器會為某web資源定義一個ETag首部,,並將其返回給快取伺服器,快取伺服器會將該首部儲存在本地。當下一次請求時,快取伺服器會攜帶該請求首部,原始伺服器端收到後,對比該請求報文中的ETag和伺服器端的本地資源的ETag是否一樣,如果一樣,表示快取沒有更新,則返回304(not modified);否則,將返回伺服器端最新的資料給原始伺服器。


7Vary:響應首部,請求訊息和響應訊息在客戶端與伺服器端之間所經過的代理或閘道器。


8Age:快取伺服器可以傳送的一個額外的響應首部,用於指定響應的有效期限;瀏覽器通常根據此首部決定內容的快取時長;如果響應報文首部還使用了max-age指令,那麼快取的有效時長為“max-age減去Age”的結果;


與客戶端相關的快取首部

cache-control:

max-stale:告知快取機制可以使用過期的快取資源。

no-cache:告知快取機制必須對請求的資源做新鮮度驗證,不會接受任何快取資源。

no-store:告知快取機制必須儘快刪除快取中的資源。


轉載於:https://blog.51cto.com/xslwahaha/1631348