快取Cache詳解
對快取的概念一直不清不楚,導致在使用PHP寫快取的時候也很沒感覺。這篇文章將全面介紹有關 快取 ( 互動百科 | 維基百科 )cache以及利用PHP寫快取caching的技術。
什麼是快取Cache? 為什麼人們要使用它?
一個使用快取Cache的站點會監聽客戶端向伺服器端發出的請求,並儲存伺服器端的迴應——比如HTML頁面、圖片等檔案。接著,如果有另外一個使用相同URL傳送請求,他能夠使用之前已經儲存下來的反饋檔案,而不是再次向伺服器發出請求。
有兩個主要的理由讓人們使用快取:
- 減少延遲 — 因為所發出的網頁請求是指向更接近客戶端的快取而不再是源伺服器端,因此請求所花費時間更短,這讓網站看上去反應更快。
- 降低網路負荷 — 因為快取檔案可以重複使用,節省了不少的頻寬.這也給使用者省了不少流量.
快取 Caches種類
瀏覽器快取 Caches
在現代瀏覽器(比如IE、Chrome、Mozilla等等)都有快取設定選項,它可以將你瀏覽過的網頁全部儲存到你本地電腦的硬碟中。當你點選瀏 覽器的“後退”或者曾經瀏覽過的頁面的連結時就能使用這種快取了,同樣的,如果你在自己的網站使用導航圖片,瀏覽器快取也能迅速地做出反應。瀏覽器快取原理機制(擴充套件閱讀>>)如下圖所示:
代理快取 Caches
web代理快取使用相同的原理,但卻有大得多的規模,代理可以用相同的方法為幾百甚至幾千的使用者服務;一些大公司和ISPs通常為它們設定了防火牆,或者單獨的裝置。
因為代理快取既不屬於客戶端也不屬於伺服器端,而是利用網路路由請求資訊。有一種方式可以做到這一點,就是手動設定瀏覽器的代理。你還可以使用網頁代理,網頁代理將你的url請求通過它潛在的網路定向到他們,所以使用者甚至無須手動配置它們。
代理快取是共享快取的一種,不是隻有一個人正在使用它們,而是同時又大量的使用者,因為他們可以非常好的節約了頻寬和網頁延遲。
閘道器快取
就像前面提到的“反向代理快取” 和 “代理快取”,閘道器快取同樣是充當一種代理的角色,通過網路管理員(或是站長自己),可以讓頻寬更有效的利用,讓他們的網站變得更加可靠。
Content delivery networks (CDNs) 出售他們的快取服務.
快取對網站的影響? 怎樣正確地使用快取?
網站的快取經常被誤解,站長認為代理快取可以“隱藏”起來,給他們的使用者帶去麻煩的同時,又不能及時地更新網站的內容。本教程可以讓你網站的教程變 得友好起來。CDNs不像代理快取,他們的閘道器服務快取可以根據網站自行設定。另一方面,這種快取還能加快你網站的載入速度,使用者體驗得到質的提高。
許多大公司花費了幾百萬美金在全世界的進行伺服器叢集來複制他們的網站內容,就是為了保證使用網站的使用者能保持最快的響應速度。快取能夠為你做同樣的事,甚至可以說快取更接近終端使用者,而這一切是免費的。
不管你願不願意,代理快取和瀏覽器快取是既存的事實。如果你不能夠正確地配置你網站快取,網站將始終保持快取功能。
網站快取的工作原理
所有的快取都有一整套工作機制(當然,在快取沒有被禁止的前提下),其中一些規則來自於HTTP協議(擴充套件閱讀>>)(HTTP 1.0 和 1.1),另一些則來自管理員(有可能是瀏覽器,也有可能是代理)。
通常來說,它們有一些共有的規則:
- header響應頭部分可以設定了是否進行快取.
- 如果請求是經過HTTP 認證 (HTTP AUTH擴充套件閱讀>>)或是SSL安全連結 (i.e., HTTPS),快取也無法工作.
- 如果符合以下條件,快取機制的啟用是通過頁面的重新整理引起(不需要經過檢測伺服器就可以直接傳送到客戶端):
- 時間沒有超過已設定的快取頁面過期時間或者其它類似 age-controlling(指示客戶機可以接收生存期不大於指定時間的響應) 的設定。
- 快取是最近請求時儲存的,或是快取修改的時間也是新的。
- 當資源過期時(使用Cache-Control標識的max-age),發現資源具有Last-Modified(Etag)宣告,則再次向web伺服器請求時帶上頭 If-Modified-Since(If-None-Match),表示客戶端請求時間。web伺服器收到請求後發現有頭If-Modified-Since(If-None-Match)則與被請求資源的最後修改時間進行比對。若最後修改時間較新,說明資源又被改動過,則響應整片資源內容(寫在響應訊息包體內),HTTP 200;若最後修改時間較舊,說明資源無新修改,則響應HTTP 304 (無需包體,節省瀏覽),告知瀏覽器繼續使用所儲存的cache。
- 特定情況— 比如, 與伺服器斷開連線 — 快取會直接作為請求的響應.
重新整理和驗證都是快取機制作用於網站內容的方式,使用者行為和瀏覽器快取之間的聯絡可參考下圖:
如何設定網站的快取 Caches
有一些工具可以幫助站長和開發人員為他們的網站設定快取。它可能會要求配置你的伺服器,更具體的內容點選這裡Implementation。
HTML Meta 標籤Tags vs. HTTP 報頭Headers
我們可以在HTML檔案中的<HEAD>部分寫入tag標籤來描述該檔案的屬性。meta tags 常常可以用來標籤檔案是否啟用快取和設定快取的過期時間。Meta tags 很容易使用,但是卻很沒效率.那是因為他們只對瀏覽器部分的快取有用,而代理快取(代理從來不會讀取HTML檔案). 如果你的主機放在ISP或者叢集伺服器,他們講不會給你隨意寫入HTTP協議的許可權 (Expires
以及Cache-Control
).
另一方面,真正的 HTTP headers 是不能在 HTML檔案裡看到的,他們通常由Web伺服器自動地生成. 即使這樣,你仍然可以依據網站所在的伺服器,在某種程度上控制它們。接下來,你講發現HTTP 協議headers 十分有趣.
HTTP headers 在伺服器端傳送HTML之前就已經傳輸了, 你只能通過類似firebug之類的瀏覽器外掛檢查. 典型的 HTTP 1.1 頭部響應就像下面這段程式碼:
HTTP/1.1 200 OK Date: Fri, 30 Oct 1998 13:19:41 GMT Server: Apache/1.3.3 (Unix) Cache-Control: max-age=3600, must-revalidate Expires: Fri, 30 Oct 1998 14:19:41 GMT Last-Modified: Mon, 29 Jun 1998 02:28:12 GMT ETag: "3e86-410-3596fbbc" Content-Length: 1040 Content-Type: text/html
HTML將出現在這些頭部資訊的下面,更多設定HTTP Headers方法Implementation點選這裡.
Pragma HTTP Headers (為什麼HTTP頭對快取不起作用?)
許多人相信設定一個 Pragma: no-cache
HTTP 協議可以控制快取是否開啟。這其實不是完全正確的。HTTP 協議的詳細說明中並沒有設定任何有關Pragma的條例,相反,Pragma請求十分有爭議。雖然一部分快取會受到此引數的影響,但大多數一點作用也沒有,請使用header頭協議代替它!
HTTP Header 控制快取更新
過期HTTP 協議header是控制快取的基本意義所在。它能夠告訴所有的快取生存時間。超過了那個時間,快取就要去請求一次伺服器來檢視網頁檔案是否已經更新。過期時間的頭部設定幾乎支援所有的快取。
大多數的網站伺服器允許你有好幾種的方式來設定過期頭部資訊。通常,允許設定一個確定的過期時間(與使用者最新一次發出請求的時間做對比),或者是伺服器端的最後一次修改網頁檔案的時間。
過期時間的頭部設定尤其對生成靜態的圖片有好處(比如logo,按鈕等)。因為他們不會有太多的改動,你能夠對它們設定很長的過期時間,使得你的站 點響應更快。這種方式對更新很有規律的頁面同樣受用。比如,如果你更新一個新聞頁面在每天6點鐘左右,你就可以把過期時間設定為那個時間點,這樣一來,即 使你的使用者沒有點選“重新載入”也能夠更新快取。
注意:
Expires
的值是HTTP協議日期,任何其它值都會被當做 已過期
快取的時間,這就會直接導致無法進行頁面快取。HTTP協議日期是格林威治時間而不是你的本地時間。
For example:
Expires: Fri, 30 Oct 1998 14:19:41 GMT
當你要使用Expires
引數時,確保你的網站伺服器時間精確,這一點非常重要。你可以用 Network Time Protocol (NTP)做到這一點。雖然Expires
過期時間的設定很有用,但是依然限制很多,首先,它涉及一個時間,網站伺服器時間必須和快取時間保持同步。另一問題就是,你很容易忘記一些已經設定了Expires
的網頁,如果你沒有在超過網站的過期時間之前更新 Expires
,以後的每個請求都會返回到您的Web伺服器,增加負載和延遲。
HTTP Header 引數Cache-Control
HTTP 1.1 ( 互動百科 | 維基百科 )
引入了 Cache-Control
響應頭引數以給站長們更多控制網站內容的權力,同時彌補了 Expires的侷限
.
Cache-Control
的引數包括:
max-age=
[單位:秒 seconds] — 設定快取最大的有效時間. 類似於Expires
, 但是這個引數定義的是時間大小(比如:60)而不是確定的時間點.單位是[秒 seconds].s-maxage=
[單位:秒 seconds] — 類似於max-age
, 但是它只用於公享快取 (e.g., proxy) .public
— 響應會被快取,並且在多使用者間共享。正常情況, 如果要求 HTTP 認證,響應會自動設定為 private.private
— 響應只能夠作為私有的快取(e.g., 在一個瀏覽器中),不能再使用者間共享。no-cache
— 響應不會被快取,而是實時向伺服器端請求資源。這一點很有用,這對保證HTTP 認證能夠嚴格地禁止快取以保證安全性很有用(這是指頁面與public結合使用的情況下).既沒有犧牲快取的效率,又能保證安全。no-store
— 在任何條件下,響應都不會被快取,並且不會被寫入到客戶端的磁盤裡,這也是基於安全考慮的某些敏感的響應才會使用這個。must-revalidate
— 響應在特定條件下會被重用,以滿足接下來的請求,但是它必須到伺服器端去驗證它是不是仍然是最新的。proxy-revalidate
— 類似於must-revalidate
,但不適用於代理快取.
For example:
Cache-Control: max-age=3600, must-revalidate
如果Cache-Control
和 Expires
同時設定, Cache-Control
優先.如果你打算使用 Cache-Control
,別忘記好好看看關於 HTTP 1.1協議的文件。【檢視 References
and Further Information更多相關資訊>>.】
快取的驗證程式
之前我們討論過 網站快取是如何工作的?,我們所討論的快取驗證指,當響應的資源做出了改變時,伺服器與快取之間的通訊所使用的驗證。通過這種驗證,如果在本地已有一份拷貝資源,快取就可以避免下載整個資原始檔。
驗證器十分重要:假如沒有它,就沒有更新的報頭(Expires
or Cache-Control
), 快取將無法儲存響應資源.大多數的驗證程式是記錄了資源最後一次修改的時間(報頭引數中的Last-Modified
),當快取儲存了包含引數Last-Modified
的響應資源時,它將使用一個包含引數If-Modified-Since
的請求與伺服器上資源的最後修改時間做對比,以檢視資源是否已作出改變。
HTTP 1.1 協議同時引入一個新的驗證器,名為Etag。這種驗證器擁有特殊的標示符,它來自於伺服器,並且隨著響應資源的改變而改變。簡單點即 伺服器響應時給請求URL標記,並在HTTP響應頭中將其傳送到客戶端,在Http響應頭中包含 Etag:“5d8c72a5edda8d6a:3239”標識,等於告訴客戶端,你拿到的這個的資源有表示 ID:5d8c72a5edda8d6a:3239。當下次需要發Request索要同一個URI的時候,瀏覽器同時發出一個If-None-Match 報頭(Http RequestHeader)此時包頭中資訊包含上次訪問得到的,即Etag:“5d8c72a5edda8d6a:3239”標識:
If-None-Match:"5d8c72a5edda8d6a:3239"
這樣,客戶端等於Cache了兩份,伺服器端就會比對2者的Etag。如果If-None-Match為False,返回304(快取讀取) ,不返回200(伺服器讀取)。
幾乎所有的快取都是使用了 Last-Modified作為驗證器,而Etag有更高的優先權。大多數的網站伺服器將自動產生 ETag
及 Last-Modified
作為靜態內容的驗證器(i.e., files);你不需要做任何改變。但是,對於動態內容(像CGI, PHP or database sites之類)卻毫無作用;你可以檢視本文介紹的相關內容怎樣寫動態網站的快取指令碼.
設定優良的網站快取機制方法
有很多的方法可以讓你的網站快取更加友好:
- 使用一致的 URLs — 這是使用快取的黃金法則.如果你為不同的使用者提供、或是從不同的網站採集相同的內容到不同的網站頁面,請使用一條URL地址。For example,如果你一旦使用了 “/index.html” ,對於其他的 HTML 檔案URL也採用相同的命名方式.
- 使用圖片庫 來查閱不同地方使用的圖片.
- 建立快取儲存不常變動的圖片和頁面 ,可以把引數
Cache-Control: max-age
報頭引數的值設定得大些. - 為規律更新的網頁設定定時快取, 可以設定合適的 max-age or expiration 時間引數.
- 如果一個資源(尤其是可下載檔案)改變了,把它的名字也改了. 用這種方式,你可以讓快取在很長的一段時間之後才過期,並且保證提供的版本是正確的。連結到改資源的網頁需要將快取時間設定得短一些.
- 除非必要,不要隨意修改檔案. 如果隨意修改,報頭引數
Last-Modified
將始終使用最新的日期.比如,當你升級網站,不要複製整個站點; 只要移動你修改的檔案即可. - 只在有必要的地方使用cookies — cookies 非常難快取, 大多數情況也沒必要快取.如果你一定需要有cookies,將它們限制在動態頁面中.
- 儘量少地使用 SSL安全協議 — 因為加密的頁面將不會採用共享快取的方式儲存,儘量在需要的時候使用SSL, 並且在SSL頁面儘量少用圖片.
- 用 REDbot檢測你的網站頁面— 本教程所描述的大多數概念在使用該工具時都很有用.
怎樣寫動態網站的快取指令碼
預設情況下,大多數的指令碼語言將不會返回驗證器(Last-Modified
or ETag
響應頭)或者快取更新提示(Expires
or Cache-Control
)。同時,一些真正的指令碼語言是動態的(意味著他們對每個請求返回不同的響應資源),大多數站點(像搜尋引擎和資料庫驅動站點)都能從快取指令碼從受益。
一般來講,如果在間隔的時間段(不管是相差幾天還是幾分鐘),發出相同的請求,能夠複寫一個指令碼輸出,那麼它就能夠快取。如果指令碼輸出的內容會隨著URL的改變而改變,也是可以進行快取的;但是如果指令碼輸出要依賴cookies,認證等,則不能快取。
- 寫一個優良的快取指令碼的最好辦法是:不管內容何時更改,都將指令碼的內容輸出到普通的檔案中,以便網站的伺服器能夠想其他網頁一樣對待它,從而生成和使用快取的驗證器。記住只對那些已經改變的檔案進行寫入,這樣可以讓
Last-Modified
的值被保護起來. - 另一個讓指令碼可以快取的方法是,設定一個有關存活時間的響應頭,值設定為指令碼能夠使用的時間。雖然
Expires設定可以實現這一點
,但是設定Cache-Control: max-age
是最簡單的, 它可以在一次請求發生後的一段時間裡又發出新的請求。 - 如果你不能做到這些,你將需要讓指令碼生成一個驗證器,然後對瀏覽器發出請求中的
If-Modified-Since
和/或If-None-Match
做出響應. 通過分析HTTP 頭你能夠做到這一點,只要在適當的時候返回304(快取讀取)響應狀態即可。
小技巧:
- 如非必要,儘量不使用 POST方式. 大多數的快取無法保持對POST方式響應,你過你想通過路徑或請求(GET)傳送一些資訊,快取能夠在未來存貯資訊。
- 除非整個內容是要呈現給完整的使用者,否則不要用URL來傳遞使用者的身份資訊.
- 不要指望來自一個使用者的所有請求都是從同一個主機發出的, 因為快取經常一起產生作用.
- 設定響應頭中的
Content-Length
(用於描述HTTP訊息實體的傳輸長度). 它允許你的指令碼可以在長連線通訊時仍有響應,並且客戶端可以通過一個TCP/IP連線請求不同的資源,而不是為一次請求的都建立一個通訊.
快取常見問題大全
哪些內容是需要設定為快取的?
有一個很好的策略,確定出網站最多人瀏覽、資料量(尤其是圖片)最大的部分。
我怎樣用快取讓我的網頁儘可能快?
大多數的快取響應資源都設定了重新整理請求時間,快取驗證可以幫助你減少檢視資源是否更新的時間,但是快取始終是需要和伺服器通訊來檢查更新的。
我已經知道快取的優勢,但我需要為我的頁面統計流量資料!
如果你必須知道頁面每次被瀏覽的資料,你可以在頁面上分類一小部分設定為不快取,比如,將一個 1*1大小的圖片放到每一個頁面中,相關的響應頭將包含所在頁面的資訊。
考慮到這樣做不僅無法統計有關準確的使用者資料,並且有害於網路和使用者(產生無效流量,增加延遲時間),你可以考慮使用第三方統計工具 相關資訊>>.
如何檢視HTTP 協議頭?
許多瀏覽器可以在頁面資訊中檢視到 Expires
和 Last-Modified
頭部引數,也可用Chrome 或是 Mozilla 的firebug檢視.
如果響應更完整的響應頭資訊,你可以用Telnet客戶端來連線網站,方法如下:
第一步:在“開始”選單中,點選“執行”命令,輸入“telnet ec-shalom.com:80”。
GET /683_webfilecoding.html HTTP/1.1 [return] Host: ec-shalom.com [return][return]
每次看到 [return]時按下回車
; 最後要點選兩次回車.它將列印所有頭部資訊,和響應資源,如果只需要頭部資訊,將GET換成HEAD 。
我的頁面設定了密碼保護,代理快取會怎樣處理它們呢?
預設情況下,設定了HTTP認證的頁面會被當做private處理;它們將不會被共享快取儲存下來。然而,你能通過頁面頭部設定引數 Cache-Control來達到目的;HTTP 1.1-協議將會採用快取.
如果你想要這個頁面能夠被快取起來,但是卻能夠驗證每一個使用者,將 Cache-Control: public
和 no-cache
結合起來. 它讓客戶端傳送的驗證資訊在連線資料庫之前先讀取了快取內容:
Cache-Control: public, no-cache
不管怎樣,儘量少地使用驗證;比如,如果你頁面的圖片是沒必要經過驗證的,你就把他們放到單獨的資料夾中,並且配置你的伺服器不要驗證它。
通過快取瀏覽我的網站是否安全?
代理伺服器上SSL頁面不會被快取(不推薦被快取),所以你不必為此擔心。但是,由於快取儲存了非SSL請求和從他們抓取的URL,你要意識到沒有安全保護的網站,可能被不道德的管理員可能蒐集使用者隱私,特別是通過URL。
實際上,位於伺服器和客戶端之間的管理員可以蒐集這類資訊。特別是通過CGI指令碼在通過URL傳遞使用者名稱和密碼的時候會有很大問題;這對洩露使用者名稱和密碼是一個很大的漏洞;
如果你初步懂得網際網路的安全機制,你不會對快取伺服器有任何。
我在尋找一個包含在Web釋出系統解決方案,那些是比較有快取意識的系統?
這很難說,一般說來系統越複雜越難快取。最差就是全動態釋出並不提供校驗引數;你無發快取任何內容。可以向系統提供商的技術人員瞭解一下,並參考後面的實現說明。
我的圖片設定了1個月後過期,但是我現在需要現在更新。
過期時間是繞不過去的,除非快取(瀏覽器或者代理伺服器)空間不足才會刪除副本,快取副本在過期之間會被一直使用。
最好的辦法是改變它們的連結,這樣,新的副本將會從源伺服器上重新下載。記住:引用它們的頁面本身也會被快取。因此,使用靜態圖片和類似內容是很容易快取的,而引用他們的HTML頁面則要保持非常更新;
如果你希望對指定的快取伺服器重新載入一個副本,你可以強制使用“重新整理”(在FireFox中在reload的時候按住shift鍵:就會有前面提到惡Pragma: no-cache頭資訊發出)。或者你可以讓快取的管理員從他們的介面中刪除相應內容;
我執行一個Web託管服務,如何讓我的使用者釋出快取友好的網頁?
如果你使用apahe,可以考慮允許他們使用.htaccess檔案並提供相應的文件;
另外一方面: 你也可以考慮在各種虛擬主機上建立各種快取策略。例如: 你可以設定一個目錄 /cache-1m 專門用於存放訪問1個月的訪問,另外一個 /no-cache目錄則被用提供不可儲存副本的服務。
無論如何:對於大量使用者訪問還是應該用快取。對於大網站,這方面的節約很明顯(頻寬和伺服器負載);
我標記了一些網頁是可快取的,但是瀏覽器仍然每次傳送請求給服務。如何強制他們儲存副本?
快取伺服器並不會總儲存副本並重用副本;他們只是在特定情況下會不儲存並使用副本。所有的快取伺服器都回基於檔案的大小,型別(例如:圖片 頁面),或者伺服器空間的剩餘來確定如何快取。你的頁面相比更熱門或者更大的檔案相比,並不值得快取。
所以有些快取伺服器允許管理員根據檔案型別確定快取副本的優先順序,允許某些副本被永久快取並長期有效;
快取機制的實現 - Web伺服器端配置
一般說來,應該選擇最新版本的Web伺服器程式來部署。不僅因為它們包含更多利於快取的功能,新版本往往在效能和安全性方面都有很多的改善。
Apache HTTP伺服器
Apache有些可選的模組來包含這些頭資訊: 包括Expires和Cache-Control。 這些模組在1.2版本以上都支援;
這些模組需要和apache一起編譯;雖然他們已經包含在釋出版本中,但預設並沒有啟用。為了確定相應模組已經被啟用:找到httpd程式並執行httpd -l 它會列出可用的模組,我們需要用的模組是mod_expires和mod_headers
- 如 果這些模組不可用,你需要聯絡管理員,重新編譯幷包含這些模組。這些模組有時候通過配置檔案中把註釋掉的配置啟用,或者在編譯的時候增加-enable -module=expires和-enable-module=headers選項(在apache 1.3和以上版本)。 參考Apache釋出版中的INSTALL檔案;
Apache一旦啟用了相應的模組,你就可以在.htaccess檔案或者在伺服器的access.conf檔案中通過mod_expires設定副本什 麼時候過期。你可設定過期從訪問時間或檔案修改時間開始計算,並且應用到某種檔案型別上或預設設定,參考模組的文件獲得更多資訊,或者遇到問題的時候向你身邊的apache專家討教。
應用Cache-Control頭資訊,你需要使用mod_headers,它將允許你設定任意的HTTP頭資訊,參考mod_headers的文件可以獲得更多資料;
這裡有個例子說明如何使用頭資訊:
- .htaccess檔案允許web釋出者使用命令只在配置檔案中用到的命令。他影響到所在目錄及其子目錄;問一下你的伺服器管理員確認這個功能是否啟用了。
ExpiresActive On
### 設定 .gif 在被訪問過後1個月過期。
ExpiresByType image/gif A2592000
### 其他檔案設定為最後修改時間1天后過期
### (用了另外的語法)
ExpiresDefault "modification plus 1 day"
### 在index.html檔案應用 Cache-Control頭屬性
<Files index.html>
Header append Cache-Control "public, must-revalidate"
</Files>
- 注意: 在適當情況下mod_expires會自動計算並插入Cache-Control:max-age 頭資訊
Microsoft IIS伺服器
Microsoft的IIS可以非常容易的設定頭資訊,注意:這隻針對IIS 4.0伺服器,並且只能在NT伺服器上執行。
為網站的一個區域設定頭資訊,先要到管理員工具介面中,然後設定屬性。選擇HTTP Header選單,你會看到2個有趣的區域:啟用內容過期和定製HTTP頭資訊。頭一個設定會自動配置,第二個可以用於設定Cache-Control頭資訊;
設定asp頁面的頭資訊可以參考後面的ASP章節,也可以通過ISAPI模組設定頭資訊,細節請參考MSDN。
Netscape/iPlanet企業伺服器
3.6版本以後,Netscape/iPlanet已經不能設定Expires頭資訊了,他從3.0版本開始支援HTTP 1.1的功能。這意味著HTTP 1.1的快取(代理伺服器/瀏覽器)優勢都可以通過你對Cache-Control設定來獲得。
使用Cache-Control頭資訊,在管理伺服器上選擇內容管理|快取設定目錄。然後:使用資源選擇器,選擇你希望設定頭資訊的目錄。設定完頭資訊後,點選“OK”。更多資訊請參考Netscape/iPlanet企業伺服器的手冊。
快取機制的實現:伺服器端指令碼
需要注意的一點是:也許伺服器設定HTTP頭資訊比指令碼語言更容易,但是兩者你都應該使用。
因為伺服器端的指令碼主要是為了動態內容,他本身不產生可快取的檔案頁面,即使內容實際是可以快取的。如果你的內容經常改變,但是不是每次頁面請求都改變, 考慮設定一個Cache-Control: max-age頭資訊;大部分使用者會在短時間內多次訪問同一頁面。例如: 使用者點選“後退”按鈕,即使沒有新內容,他們仍然要再次從伺服器下載內容檢視。
CGI程式
CGI指令碼是生成內容最流行的方式之一,你可以很容易在傳送內容之前的擴充套件HTTP頭資訊;大部分CGI實現都需要你寫 Content-Type頭資訊,例如這個Perl指令碼:
#!/usr/bin/perlprint "Content-type: text/html\n";
print "Expires: Thu, 29 Oct 1998 17:04:19 GMT\n";
print "\n";
### 後面是內容體...
由於都是文字,你可以很容易通過內建函式生成Expires和其他日期相關的頭資訊。如果你使用Cache-Control: max-age;會更簡單;
print "Cache-Control: max-age=600\n";
這樣指令碼可以在被請求後快取10分鐘;這樣使用者如果按“後退”按鈕,他們不會重新提交請求;
CGI的規範同時也允許客戶端傳送頭資訊,每個頭資訊都有一個‘HTTP_’的字首;這樣如果一個客戶端傳送一個If-Modified-Since請求,就是這樣的:
參考一下cgi_buffer庫,一個自動處理ETag的生成和校驗的庫,生成Content-Length屬性和對內容進行gzip壓縮。在Python指令碼中也只需加入一行;
伺服器端包含 Server Side Includes
SSI(經常使用.shtml副檔名)是網站釋出者最早可以生成動態內容的方案。通過在頁面中設定特別的標記,也成為一種嵌入HTML的指令碼;
大部分SSI的實現無法設定校驗器,於是無法快取。但是Apache可以通過對特定檔案的組執行許可權設定實現允許使用者設定那種SSI可以被快取;結合XbitHack調整整個目錄。更多文件請參考mod_include文件。
PHP
PHP是一個內建在web伺服器中的伺服器端指令碼語言,當做為HTML嵌入式指令碼,很像SSI,但是有更多的選項,PHP可以在各種Web伺服器上設定為CGI模式執行,或者做為Apache的模組;
預設PHP生成副本沒有設定校驗器,於是也無法快取,但是開發者可以通過Header()函式來生成HTTP的頭資訊;
例如:以下程式碼會生成一個Cache-Control頭資訊,並設定為3天以後過期的Expires頭資訊;
Header("Cache-Control: must-revalidate");$offset = 60 * 60 * 24 * 3;
$ExpStr = "Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT";
Header($ExpStr);
?>
記住: Header()的輸出必須先於所有其他HTML的輸出;
正如你看到的:你可以手工建立HTTP日期;PHP沒有為你提供專門的函式(新版本已經讓這個越來越容易了,請參考PHP的日期相關函式文件),當然,最簡單的還是設定Cache-Control: max-age頭資訊,而且對於大部分情況都比較適用;
更多資訊,請參考header相關的文件;
也請參考一下cgi_buffer庫,自動處理ETag的生成和校驗,Content-Length生成和內容的gzip壓縮,PHP指令碼只需包含1行程式碼;
Cold Fusion
Cold Fusion是Macromedia的商業伺服器端指令碼引擎,並且支援多種Windows平臺,Linux平臺和多種Unix平臺。Cold Fusion通過CFHEADER標記設定HTTP頭資訊相對容易。可惜的是:以下的Expires頭資訊的設定有些容易誤導;
<CFHEADER NAME="Expires" VALUE="#Now()#">
它並不像你想像的那樣工作,因為時間(本例中為請求發起的時間)並不會被轉換成一個符合HTTP時間,而且打印出副本的Cold fusion的日期/時間物件,大部分客戶端會忽略或者將其轉換成1970年1月1日。
但是:Cold Fusion另外提供了一套日期格式化函式, GetHttpTimeSTring. 結合DateAdd函式,就很容易設定過期時間了,這裡我們設定一個Header宣告副本在1個月以後過期;
你也可以使用CFHEADER標籤來設定Cache-Control: max-age等其他頭資訊;
記住:Web伺服器也會將頭資訊設定轉給Cold Fusion(做為CGI執行的時候),檢查你的伺服器設定並確定你是否可以利用伺服器設定代替Cold Fusion。
ASP和ASP.NET
在asp中設定HTTP頭資訊是:確認Response方法先於HTML內容輸出前被呼叫,或者使用 Response.Buffer暫存輸出;同樣的:注意某些版本的IIS預設設定會輸出Cache-Control: private 頭資訊,必須宣告成public才能被共享快取伺服器快取。
IIS的ASP和其他web伺服器都允許你設定HTTP頭資訊,例如: 設定過期時間,你可以設定Response物件的屬性;
設定請求的副本在輸出的指定分鐘後過期,類似的:也可以設定絕對的過期時間(確認你的HTTP日期格式正確)
<% Response.ExpiresAbsolute=#May 31,1996 13:30:15 GMT# %>Cache-Control頭資訊可以這樣設定:
<% Response.CacheControl="public" %>在ASP.NET中,Response.Expires 已經不推薦使用了,正確的方法是通過Response.Cache設定Cache相關的頭資訊;
Response.Cache.SetExpires ( DateTime.Now.AddMinutes ( 60 ) ) ;Response.Cache.SetCacheability ( HttpCacheability.Public ) ;
參考MSDN文件可以找到更多相關新年系;
參考文件和深入閱讀
HTTP 1.1的規範有大量的擴充套件用於頁面快取,以及權威的介面實現指南,參考章節:13, 14.9, 14.21, 以及 14.25.
非常精彩的介紹快取相關概念,並介紹其他線上資源。
Jeff Goldberg內容豐富的演說告訴你為什麼不應該過度依賴訪問統計和計數器;
可快取的引擎設計,檢測網頁並確定其如何與Web快取伺服器互動, 這個引擎配合這篇指南是一個很好的除錯工具,
包含庫:用於CGI模式執行的Perl/Python/PHP指令碼,自動處理ETag生成/校驗,Content-Length生成和內容壓縮。正確地。 Python版本也被用作其他大量的CGI指令碼。