緩存友好的網頁
緩存友好的網頁
by Jennifer Vesperman ?03/07/2002 ?原文地址:http://www.linuxdevcenter.com/pub/a/linux/2002/02/28/cachefriendly.html
翻譯:ShiningRay @ Nirvana Studio
現在我們有很多HTTP緩存。他們存放你的頁面多久呢?他們應該存放多久呢?RFC 2616(HTTP/1.1)指出了緩存必須遵循Expires和Cache-Control頭——那么你的頁面是否都有呢?
“在HTTP/1.1種的緩存的目的是為了在很多情況下消除發送請求的需要,同時在其他一些情況下消除發送完整的響應的需要。” RFC 2616
緩存友好頁面的優點
“當緩存可以完全避免對原始服務器發送請求時,HTTP緩存的工作是最佳的。避免請求的主要機制是,針對原始服務器提供未來的一個確切的失效時間,表示一個響應 可以 被用來滿足后續的請求。換句話說,一個緩存可以返回一個新的響應而不必先聯系服務器。” RFC 2616
RFC寫的時候是期望網頁要包含失效期頭的。如果謹慎地選擇頭中的失效時間,緩存可以不失去任何意義來提供存儲了的頁面。?
當原始服務器不提供失效頭時,緩存根據諸如“Last-Modified”之類的頭來推斷,猜測出一個合適的失效時間。與由了解頁面內容以及更改頻率的人設置的失效日期相比,推斷的方法顯然效率較低。?
“由于推斷的失效時間也許會降低語義透明度,應該被謹慎使用,同時我們鼓勵原始服務器盡可能提供確切的失效時間。” RFC 2616
關于緩存的注意事項
HTTP/1.1標準(第13節)關于緩存有一個強制的要求:它要求他們提供語義的透明——返回一個緩存了的響應必須提供本來從原始服務器上獲取的同樣的數據;同時它提倡讀取原始服務器和客戶端所提供的新鮮度要求。
緩存必須傳遞由上游緩存或者是原始服務器提供的警告,而且如果提供了一個陳舊的響應,他們也必須加入警告。一個緩存可以在特定的情況下提供一個陳舊的響應,大部分情況下是如果緩存無法連接到原始服務器同時客戶端聲明它可以接受一個陳舊的響應。?
如果一個緩存收到了針對一個陳舊頁面的請求,它發送一個驗證請求詢問原始服務器頁面是否已經更改。最常見的驗證工具便是最后的更新時間。如果在一秒鐘內存儲了兩次更改,Last-Modified將會不正確。因此,HTTP/1.1利用Entity Tag頭提供了更加嚴格的驗證。?
最簡便的協助緩存的方法是保持你的HTTP服務器上的時間精確且總是發送Date和Last-Modified頭。?
另外,要成為一個真正的緩存友好的站長,還要在你的頁面中加入緩存頭。?
可用的緩存頭
Expires頭是最快捷最方便的解決方案。這個頭聲明了頁面被認為不再可被緩存的時間,在這之后,任何保存了這個頁面副本的緩存都應該聯系原始服務器。語法是:?
Expires: <date in RFC 1123 format>
例如:?
Expires: Sun, 10 Feb 2002 16:00:00 GMT
若要標記一個響應為已經“已經過期”或者“不可緩存”,頭則應該設置為發送響應的時間。若要標記一個響應為“永不過期”,則應該將頭設置為未來的一年。?
另一個頭是Cache-Control。Cache-Control包括了這些元素:指明頁面元素最大時限,他應該如何被緩存的,他如何被轉換到另一個不同的媒介,以及他如何被存放在持久媒介中的。
本文使用Apache為例,設置頭并在例子中詳細討論Cache-Control頭。
在Apache中設置緩存頭
主要的方法:Expires頭
要使用Expires頭,你需要運行在Apache 1.2或者更新的版本上,同時要啟用 mod_expires 模塊。去掉 httpd.conf 文件在“Dynamic Object Support”一節中的 expires_module 一行上的注釋,然后重新編譯Apache。
#
# Dynamic Shared Object (DSO) Support
#
?
# LoadModule cern_meta_module /usr/lib/apache/1.3/mod_cern_meta.so
LoadModule expires_module /usr/lib/apache/1.3/mod_expires.so
(如果你運行的是Apache 1.3或更新的版本,同時它已經配置為運行時加載模塊,你可以編輯 httpd.conf 然后重新啟動Apache而無需重新編譯。)
mod_expires 基于三條指令來計算Expires頭。這些指令可以應用于文檔范圍同時也可以在任何以下范圍內使用:“server config”、“virutal host”、“directory”、或者“.htaccess”。
Expires指令有兩種語法。其中一個有點難以閱讀;它要你計算到失效為止用的秒數。幸運的是,這個模塊同樣可以讀取一個更加人性化的語法。本文將解釋較為可讀的語法。
要用到的指令是:
ExpiresActive on|off
ExpiresDefault "<base> [plus] {<num> ?<type>}*"
ExpiresByType type/encoding "<base> [plus] {<num> <type>}*"
base 可以是以下其中之一:
-
access ?
-
now (等同于“access”)
-
modification ?
num 是一個整數值,單位是 type :
-
years ?
-
months ?
-
weeks ?
-
days ?
-
hours ?
-
minutes ?
-
seconds ?
如果你準備對一個服務器、虛擬主機或者是目錄使用Expires指令,編輯 httpd.conf 文件并在所需的范圍內加入以下指令。
<Directory /whichever/directory/here>
? ? # 包括 任何其他你想要加入這一節的東西
? ? ExpiresActive on
? ? ExpiresByType image/gif "access plus 1 year"
? ? ExpiresByType text/html "modification plus 2 days"
? ? # ExpiresDefault "now plus 0 seconds"
? ? ExpiresDefault "now plus 1 month"
</Directory>
如果你要在 .htaccess 文件中使用Expires頭,那么你要先編輯 httpd.conf 設置相應的目錄的AllowOverride。Apache只會讀取設置了“Indexes”覆蓋的目錄中的 .htaccess 。
# 針對使用.htaccess的目錄,允許Indexes覆蓋
<Directory /whichever/directory/here>
? ? # 包括 任何其他你想要加入這一節的東西
? ? AllowOverride Indexes
</Directory>
在相應目錄里的 .htaccess 文件中加入Expires指令。站長可以編輯 .htaccess 文件而無需修改 httpd.conf 。
“.htaccess”方法的主要問題是Indexes覆蓋,這樣 .htaccess 文件將給予站長更多的配置選項而非僅僅Expires頭。這也許并不是系統管理員所期望的。
候選方法:Cache-Control 頭
mod_cern_meta 允許文件級的控制,同時它也可以使用Cache-Control頭(或任何其他頭)。響應頭是放在原始目錄的子目錄中,根據原始文件名所命名的一個文件。
去掉 cern_meta_module 一行的注釋并重新編譯,和上一節中對 expires_module 的一樣。
在 httpd.conf 文件中,打開 MetaFiles on ,將 MetaDirectory 設置為子目錄名,同時把 MetaSuffix 設為頭的文件的后綴名。
MetaFiles on
MetaDirectory .web
MetaSuffix .meta
使用這些值的話,文件 /var/www/www.example.org/index.html 將會以 /var/www/www.example.org/.web/index.html.meta. 為元文件。
任何有效的HTTP頭都可以放在這些文件中。這提供了另一種使用Expires頭的方式,同時它可以加入Cache-Control頭。相應的Cache-Control頭如下:?
Cache-Control : max-age = [delta-seconds]
修改失效機制,將覆蓋Expires頭。Max-age隱含了Canche-Control: public。
Cache-Control : public
表示對象可以被存在緩存中。這是默認值。?
Cache-Control : private
Cache-Control : private = [field-name]
表示對象(或指定字段)不能被保存在一個共享的緩存中同時是針對一個單獨的用戶的。它可以被保存在一個私有的緩存中。?
Cache-Control : no-cache
Cache-Control : no-cache = [field-name]
表示對象(或者指定字段)可以被緩存,但不能直接給客戶除非經過原始服務器的重新驗證。?
Cache-Control : no-store
表示條目不能存儲在持久的存儲媒介中,同時應該盡可能快地從非未定存儲媒介中刪除。?
Cache-Control : no-transform
代理可以將數據從一個存儲系統中轉換到另外一個。這個指令表示(大多數)響應不能被轉換。(RFC允許某些字段的轉換,即使存在這個頭)?
Cache-Control : must-revalidate
Cache-Control : proxy-revalidate
強制代理重新驗證該頁面即使客戶可以接受一個陳舊的響應。請在使用這些頭之前閱讀RFC,關于他們的使用有一些限制。
警告
-
HTTP/1.0有一個很小的緩存控制機制,僅能理解Pragma: no-cache頭。使用HTTP/1.0的緩存將忽略Expires和Cache-Control頭。
-
任何一個Cache-Control指令都不能保證隱私性或者數據的安全性。“private”和“no-store”指令可以為隱私性和安全性方面提供一些幫助,但是他們并不能用于替代身份驗證和加密。
-
本文不能代替RFC。如果你要實現Cache-Control頭,請閱讀RFC來獲取每個頭的含義和限制的詳細描述。
最后的話
緩存是Internet的現實問題同時它能讓帶寬的使用更加有效。你的客戶也許是通過一個緩存來瀏覽你的頁面的,有時候還會用多個緩存。給你的頁面加上緩存頭可以保護你的頁面內容也可以讓你的客戶節省他們的帶寬。?
進一步閱讀
-
RFC 2616 :
-
Apache 用戶手冊:http://httpd.apache.org/
-
你的Web服務器的用戶手冊?