- 什麼是Web緩存,爲什麼要使用它?
- 緩存的類型:
- Web緩存無害嗎?爲什麼要鼓勵緩存?
- Web緩存如何工作
- 如何控制緩存和不緩存:
- 創建支持緩存網站的小技巧;
- 編寫支持緩存的腳本;
- 常見問題解答;
- 實現需注意的:Web服務器端;
- 實現需注意的:服務端腳本;
- 參考文檔和拓展閱讀;
- 關於本文檔;
什麼是Web緩存,爲什麼要使用它?
Web緩存遊走於服務器和客戶端之間。這個服務器可能是源服務器(資源所駐留的服務器Add),數量可能是1個或多個;這個客戶端也可能是1個或多個。Web緩存就在服務器-客戶端之間搞監控,監控請求,並且把請求輸出的內容(例如html頁面、 圖片和文件)(統稱爲副本)另存一份;然後,如果下一個請求是相同的URL,則直接請求保存的副本,而不是再次麻煩源服務器。
使用緩存的2個主要原因:
- 降低延遲:緩存離客戶端更近,因此,從緩存請求內容比從源服務器所用時間更少,呈現速度更快,網站就顯得更靈敏。
- 降低網絡傳輸:副本被重複使用,大大降低了用戶的帶寬使用,其實也是一種變相的省錢(如果流量要付費的話),同時保證了帶寬請求在一個低水平上,更容易維護了。
Web緩存的類型
1. 瀏覽器緩存
在任何現代瀏覽器上(如IE, FireFox, Chrome)折騰清除隱私數據(//zxx: 原文說的是首選項,顯然out了,這裏有改動)的對話框,你很可能會注意到“緩存”這個設置項。
瀏覽器會在你的硬盤上專門開闢一個空間專門爲你存儲資源副本。瀏覽器緩存的工作規則很簡單:檢查以確保副本是最新的,通常只要一次會話(就是當前瀏覽器調用的這次N)。
瀏覽器緩存在用戶觸發“後退”操作或點擊一個之前看過的鏈接的時候很管用。同樣,如果你在網站上訪問同一張圖片,該圖片可以從瀏覽器緩存中調出並幾乎立即顯現出來。
2. 代理服務器緩存
Web代理服務器使用同樣的緩存原理,只是規模更大。代理以同樣的方式服務千萬用戶,大公司和ISP(Internet Server Provider, Internet服務提供商Add)經常在他們的防火牆或者單獨的設備(也被稱爲中介(intermediaries))上架設代理緩存。
由於代理服務器緩存並非客戶端或者源服務器的一部分,而是處於網絡中,請求需要以某種方式路由到它們。一種方法是手動設置,告訴瀏覽器的你常用的代理服務器(//zxx: 翻牆的時候常用的),另外就是使用攔截。攔截代理(Interception proxies)把Web請求根據自己的底層網絡重定向,因此,客戶端無需配置,甚至都不需要知道它們。//zxx: 維基百科上提供的幾種檢測攔截代理服務器存在的方法add,您若有興趣,可以點擊這裏查看。
代理緩存屬於一種共享緩存;往往有大量的用戶使用,因此,其在降低延時和網絡流量上很有用,畢竟每個副本都被大量重用。//zxx: 這裏我有疑問:就算是放在代理服務器上,每次獲取還是要通過網絡的啊,如何降低了網絡流量呢?希望誰可以幫忙解惑下。
3. 網關緩存
也被稱爲“反向代理緩存”或“替代緩存”。網關緩存同樣是起中介作用的,不過不是(素不相識、不曾謀面的Add)網絡管理員部署的,而多半是網站管理員(公司專門的運維工程師、或UED或程序組某人Add)他們自己部署,這樣更容易擴展與維護。
可以有多種方法把請求路由到網關緩存,但通常使用某種形式的負載均衡器①,使它們中的一個或多個看起來像是源服務器。內容分發網絡②(CDNs)爲整個網絡(或部分)分配網關緩存,然後把這些緩存賣給需要的網站。Speedera③和Akamai④就是代表性的網絡內容發佈商。
①負載均衡器:是一種採用各種分配算法把網絡請求分散到一個服務器集羣中的可用服務器上去,通過管理進入的Web數據流量和增加有效的網絡帶寬,從而使網絡訪問者獲得儘可能最佳的聯網體驗的硬件設備。
②內容分發網絡:即CDN, 基本思路是儘可能避開互聯網上有可能影響數據傳輸速度和穩定性的瓶頸和環節,使內容傳輸的更快、更穩定。通過在網絡各處放置節點服務器所構成的在現有的互聯網基礎之上的一層智能虛擬網絡,CDN系統能夠實時地根據網絡流量和各節點的連接、負載狀況以及到用戶的距離和響應時間等綜合信息將用戶的請求重新導向離用戶最近的服務節點上。其目的是使用戶可就近取得所需內容,解決 Internet網絡擁擠的狀況,提高用戶訪問網站的響應速度。
③Speedera:是一家全球性的內容服務提供商,它與北美、歐洲以及亞太地區的1000多家大型運營商都有聯繫,併爲那些不想在自己服務器上寄存內容的公司提供軟件下載、媒體及其它服務管理等業務。05年的時候被下面要介紹的Akamai以$130m的價格給收購了。
④Akamai:美國Akamai是國際上最大的CDN服務商,它巨大的網絡分發能力在峯值時可達到15Tbps。Akamai公司是爲數不多的旨在消除Internet瓶頸和提高下載速度的幾家新公司之一,是一個致力於網絡交通提速的”內容發佈”公司,是波士頓高技術區最卓越的新興企業之一。Akamai公司向全球企業提供發送互聯網內容,匯流媒體和應用程序的服務(目前,該公司爲15個國家的企業管理着8000多臺服務器)。1998年,丹尼爾。L和麻省理工學院的一些研究人員一起創立了這家公司,他在麻省理工學院的碩士論文構成了Akamai公司最初的”自由流”(Freeflow)技術的核心。
本教程重點在瀏覽器和代理緩存,儘管有些信息對網關緩存感興趣的人也適用。
Web緩存無害嗎?爲什麼要鼓勵緩存?
Web緩存是互聯網中最容易被誤解的技術之一。網站管理員特別希望知道網站的一舉一動,比方說多少人訪問啦,訪問時間啊什麼的,而緩存會“隱藏”他們的用戶,他們就無從得知到底誰訪問了這個站點。
撿了芝麻丟西瓜,自認爲放棄緩存可以精確跟蹤用戶,實際上,互聯網中有太多的變數,想精確得到一張用戶查看網站的圖片?沒那麼簡單的,親!如果你很重視這個問題,恭喜你,本文正好提供瞭解決之道,即保證緩存友好,同時又能獲得統計。
另外需要注意的是,緩存的內容都是舊的過時的。因此,如何準確更新就成了一個問題。不過不要擔心,本文會向你展示如何配置服務器,讓緩存就像你的女僕——隨便調教。
CDN算是個挺有意思的技術,不同於代理緩存,CDN的網關緩存和被緩存的Web站點的利益是一致的,因此,上面提到的問題對於CDN而言是沒有的。不過,即使你使用了CDN,你仍要顧慮下游的代理和瀏覽器緩存。
以上爲緩存可能的“糟粕”,那他好的地方呢?緩存可以讓你的Web站點加載更快,讓你的服務器和互聯網鏈接間負擔更小。這種差異會導致一些類似質的變化,一個網站要幾秒鐘才能加載出來,而另外一個充分發揮緩存的優勢,幾乎瞬間顯示。用戶自然更喜歡那個加載迅速的站點,訪問也更多。
再說個現實示例,許多大型互聯網公司花費了數百萬美元,在世界各地設立服務器集羣來複制他們的內容,以使其儘可能快被他們的用戶訪問。緩存爲你做同樣的事情,而且他們更接近最終用戶。最重要的是,你不要花銀子。
實際上呢,無論你喜歡與否,代理和瀏覽器緩存都會被使用。如果你站點的緩存配置不正確,你只能聽天由命了。
Web緩存如何工作
所以的緩存都有一套自己的規則,可以用來決定何時跟緩存曖昧往來。其中部分規則設定在協議中(HTTP 1.0 以及 1.1),部分由緩存管理員⑤設置。
⑤緩存管理員:如果指的是瀏覽器緩存,則有可能就是我們服務器專家同事,在服務器上配置一些緩存規則;如果是代理緩存,則指的就是處理代理服務器這塊的管理人員。
一般而言有如下常用規則N:
- 響應頭明確說明,偶不想被緩存,則不會被緩存;
- 如果請求信息是需要認證或者安全加密的(如, HTTPS),相應內容也不會被緩存;
- 緩存如果有以下表現,則認爲是fresh新鮮的(無需檢查源服務器,直接發送給客戶端):
- 含有完整的過期時間和壽命控制頭信息,並且內容仍在保鮮期內,或者
- 緩存最近已展現,並且在不久前修改。
則內容緩存直取,繞過源服務器。
- 若內容陳舊,則會要求源服務器做驗證 validate ,或者告訴緩存其拷貝副本是否是OK的。
- 特定情況下——例如,斷網了,之前有過的響應緩存直取而不檢查源服務器。
響應如果沒有類似ETag或Last-Modified頭這樣的校驗器,也沒有明確的更新信息,通常(並不絕對)認爲是不可緩存的。
總而言之,新鮮度freshness和校驗validation是確定緩存內容是否可用的最重要途徑。如果要展示的足夠新,直接緩存取;如果檢測發現展示內容並未變化,則不會再來一次完整的傳輸。
如何控制緩存和不緩存
有很多工具可以幫助設計師和網站管理員調整服務器緩存網站的方式,這也許需要你親自動手對服務器的配置進行一些調整,但絕對值得。瞭解如何使用這些工具請參考本文後面的章節。
HTML Meta標籤 vs. HTTP頭信息
HTML重構人員可以在文檔的<head>
中添加標籤進行描述。這些meta標籤通常用來標記不可緩存或過期時間。
Meta標籤使用簡單,但效果一般。因爲只被少數幾個瀏覽器寵幸,而代理緩存基本上就不訪問HTML文檔。儘管我們可以在頁面上試圖添加no-cache
meta標籤讓頁面一直是最新的,但其實沒必要。
如果你的網站託管在ISP或者主機託管商那裏,並且他們沒有賦予您任意設置HTTP頭信息的能力(比如Expires和Cache-Control),你要投訴爭取,因爲在你的工作中這些是必須的。
另外一方面: HTTP頭信息可以讓你對瀏覽器和代理服務器如何處理你的副本進行更多的控制。他們在HTML代碼中是看不見的,一般由Web服務器自動生成。但是,根據你使用的服務器,你可以在某種程度上進行控制。在下文中:你將看到一些有趣的HTTP頭信息,以及如何在你的站點上應用部署這些特性。
HTTP頭信息發送在HTML代碼之前,只能被瀏覽器和一些中間緩存能看到,一個典型的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頭信息請參考對應章節。
Pragma HTTP頭信息(以及爲什麼不起作用)
很多人認爲在HTTP頭信息中設置了Pragma: no-cache
後會讓內容無法被緩存。但事實並非如此:HTTP的規範中,響應型頭信息沒有任何關於Pragma屬性的說明,只說明了請求頭信息(瀏覽器發送給服務器的頭信息)中的Pragma屬性。雖然有少部分緩存會買賬,但大部分無視,使用Pragma沒作用。若要使用,試試下面的頭信息。
使用Expires HTTP頭信息控制不過期
Expires HTTP頭是控制緩存的基本手段,Expires的中文意思是“有效期”,顯然,就是告訴瀏覽器緩存的有效期。如果過期,緩存會檢查源服務器以確定文件是否改變了。Expires頭幾乎每個緩存都支持。
大部分的服務器允許你以多種方式設置Expires響應頭。通常,他們允許設置一個絕對過期時間,然後對比最後一次訪問的時候或者最後一次文檔修改的時候決定客戶端內容的獲取方式。
對於靜態圖片(如導航或按鈕的圖片)而言,Expires頭信息是相當有用的,因爲圖片不怎麼修改,您可以給圖片設置一個相當長的過期時間,這回讓你的用戶感覺網站變快了。Expires對於控制有改變規律的網頁也很有用,例如:你有一個新聞聚合頁面,每天早上6點鐘準時更新,您可以設置緩存的過期時間也是這個點,於是緩存就可以很聰明地知道什麼時候該去重載新的內容,什麼時候睡大覺。
Expires頭唯一的有效值是HTTP時間,其他值都會被認爲是“前男友前女友”之類,不會去緩存的。注意:時間是格林威治時間(GMT),而不是本地時間。如下所示:
Expires: Fri, 30 Oct 1998 14:19:41 GMT
顯然,如果你要使用Expires頭,確保你的Web服務器時間的準備就非常重要了。使用網絡時間協議(Network Time Protocol – NTP)不失爲一個號方法。如果你的身邊有本地系統管理員,可以向他諮詢,或者查看下面的百科Add ⑥。
儘管Expires頭很有用,但它有一定的侷限性。首先,因爲牽扯到時間,Web服務器端的時鐘必須和緩存的同步,否則很可能實現不了預期的結果——緩存把前女友當初現女友,把現女友當作過去式——那就悲劇了。
另外一個問題是,你很容易忘記給某內容設置了一個特定時間,如果返回內容的時候沒有更新這個過期時間,則每個請求都是上訪到服務器,反而增加了負載和響應時間。
⑥網絡時間協議(NTP): 以封包交換把兩臺電腦的時鐘同步化的網絡協議。NTP使用UDP端口123作爲傳輸層。它是用作抵銷可變延遲的影響。NTP是仍在使用中的最古老的網絡協議之一(在1985年前開始)。NTP最初由德拉瓦州大學的Dave Mills設計,他與一羣志願者仍在維護NTP。
Cache-Control(緩存控制)HTTP頭信息
HTTP 1.1引入了新的頭信息:Cache-Control
響應頭信息,讓網站的發佈者可以更全面的控制他們的內容,更好地處理Expires的些限制。Cache-Control
有用的響應頭包括:
- max-age=[秒]:表示在這個時間範圍內緩存是新鮮的無需更新。類似Expires時間,不過這個時間是相對的,而不是絕對的。也就是某次請求成功後多少秒內緩存是新鮮的。
- s-maxage=[秒]:類似
max-age
, 除了僅應用於共享緩存(如代理)。 - public:標記認證的響應才能夠被緩存。一般而言,需要認證HTTP請求內容會自動私有化(不會被緩存Add)。
- privateN:允許緩存專門爲某一個用戶存儲響應,比方說在瀏覽器中;共享緩存一般不會,例如在代理中。
- no-cache:每次在釋放緩存副本之前都強制發送請求給源服務器進行驗證,這在確保認證有效性上很管用(和
public
結合使用)或者保證內容必須是即時的,不得無視緩存的所有優點,如國內的微博、twitter等的刷新顯示Add。 - no-store:強制緩存在任何情況下都不要保留任何副本。
- must-revalidate:告訴緩存,我給你準備了一些關於新鮮度的信息,在表現的時候要嚴格遵循之。HTTP允許緩存在某些特定情況下返回過期數據,指定了這個屬性,相對於告訴緩存,你丫必須嚴格遵循我的規則。
- proxy-revalidate:類似
must-revalidate
,除了只能應用於代理緩存。
舉個板栗:
Cache-Control: max-age=3600, must-revalidate
如果Cache-Control
和Expires
同時存在,Cache-Control
說了算N。如果你打算使用Cache-Control
頭,你應該好好看看”HTTP
1.1 規範“, 詳見參考文章以及拓展閱讀。
驗證器和驗證
在緩存如何工作這段譯文中,我們說過,服務器以及緩存通過驗證來判斷內容是否改變,在不確定內容是否過期的時候,可以避免本地已經存在副本的時候下載整個內容。
驗證器是很重要的,如果一個都沒有,同時沒有可用的新鮮度信息(Expires
或Cache-Control
),緩存一點兒都不會存儲內容。
最常見的驗證是通過Last-Modified
頭信息通信確定文檔最後的修改時間,如果緩存有內容存儲,會包含Last-Modified
信息的,輔助If-Modified-Since
請求,我們可以詢問服務器內容是否改變了。
HTTP 1.1引入了一個新的驗證器,稱爲Etag
⑦. Etag
是每次展現內容改變時候由服務器生成的唯一標識符,由於服務器控制ETag
如何生成,當緩存發起If-None-Match
請求的時候,如果Etag
匹配,就可以確定展示內容其實是一樣的。
⑦Etag: HTTP協議規格說明定義ETag爲”被請求變量的實體值”。另一種說法是,ETag是一個可以與Web資源關聯的記號(token)。典型的Web資源可以一個Web頁,但也可能是JSON或XML文檔。服務器單獨負責判斷記號是什麼及其含義,並在HTTP響應頭中將其傳送到客戶端,以下是服務器端返回的格式:ETag:”50b1c1d4f775c61:df3″客戶端的查詢更新格式是這樣的:If-None-Match : W / “50b1c1d4f775c61:df3″如果ETag沒改變,則返回狀態304然後不返回,這也和Last-Modified一樣。測試Etag主要在斷點下載時比較有用。
幾乎所有的緩存使用Last-Modified
時間作爲驗證器,Etag
驗證也開始變得流行。
所有新一代的Web服務器都對靜態內容(如:文件)自動生成ETag
和Last-Modified
頭信息,而你不必做任何設置。但是,服務器對於動態內容(例如:CGI,
ASP或數據庫生成的網站)並不知道如何生成這些信息,參考一下編寫支持緩存的腳本章節;
創建支持緩存網站的小技巧
除了使用新鮮度信息以及驗證,還有其他一些技巧可以讓你網站的緩存更加友好:
- 保持URL穩定:這是緩存的金科玉律,如果你爲不同頁面,不同用戶或不同網站提供相同的內容,他們應該使用相同的URL. 這是簡單卻非常行之有效的方法。例如,你的HTML中的某個引用地址是
"/index.html"
, 則要一直使用這個地址。 - 不同地方的圖片和其他元素使用同一庫。
- 對於不經常改變的圖片/頁面啓用緩存,通過將
Cache-Control: max-age
頭信息的值設大一點。 - 對於定期更新的內容通過指定
max-age
或過期時間實現緩存。 - 如果資源改變了(尤其下載文件),改變其名字。由於一般這種資源會有很長的過期時間,而服務器上一直是正確的版本;因此,鏈接這個下載資源的頁面需要要比較短的過期時間(//zxx: 我司頁面5分鐘過期)。否則,會出現服務器的資源是新的,但頁面被緩存了,其中的鏈接地址還是舊的,就會出現新舊版本衝突的可能Add。
- 萬不得已不要變動文件:否則你要設置一個新的
Last-Modified
值。另外,當你更新站點的時候,只要上傳改動的那些文件,而不要把整個站點都覆蓋過去。 - Cookie能不用就不用:Cookie難以被緩存,且大多情境下是沒有必要的。如果你非得使用Cookie,建議用在動態頁面上。
- 減少SSL⑧的使用:因爲共享緩存不能存儲認證頁面,只在必要的時候使用,並且在SSL頁面上減少圖片的使用。
- 使用REDbot⑨檢查你的網站:可以幫助你應用本文所介紹的一些概念。
⑧ SSL:全稱Secure Socket Layer – 安全套接層,爲Netscape所研發,用以保障在Internet上數據傳輸之安全,利用數據加密(Encryption)技術,可確保數據在網絡上之傳輸過程中不會被截取及竊聽。目前一般通用之規格爲40 bit之安全標準,美國則已推出128 bit之更高安全標準,但限制出境。只要3.0版本以上之I.E.或Netscape瀏覽器即可支持SSL。
⑨ REDbot:REDbot = RED + robot,是個機器人,檢查HTTP資源,看他們如何會表現,指出常見的問題,並提出改進建議。雖然它屬於HTTP一致性測試儀,但卻可以找到不少HTTP相關問題。
編寫支持緩存的腳本
默認情況下,大多數的腳本不會返回驗證器(Last-Modified
或Etag
響應頭)或新鮮度信息(Expires
或Cache-Control
)。儘管有些腳本的確是動態的(意味着每次請求都有不同的響應),還是有很多(如搜索引擎或數據庫驅動的)網站可以從緩存中受益。
一般來講,對於同一個請求(無論是幾分鐘還是幾天之後),如果腳本產生的內容是可重複的,則可以緩存。腳本內容的改變僅僅依賴於URL,則可以緩存。如果是依賴於Cookie,認證信息或其他外部條件,很可能不緩存。
- 最利於緩存的腳本就是在內容改變時導出成靜態文件,服務器會想對待其他Web一樣對待它的,生成以及使用驗證器,於是你可以好好地喝杯咖啡了。記住,只有文件更改的時候才寫入,這樣Last-Modified時間就會被保存下來。
- 另外的腳本緩存之道就是使用
age
相關的頭部,相比Expires
,Cache-Control: max-age
更容易些,因爲是相對時間,每次新請求完成後重新設置,時間到了,再重新請求,再設置新的相對過期時間。 - 如果上面的做法你搞不定,你還可以試試通過腳本生成一個校驗器, 然後迴應
If-Modified-Since
和/或If-None-Match
請求。通過分析HTTP頭信息,在適合的時候迴應304 Not Modified
. 不幸的是,這不是個打打醬油就能搞定的任務。
其他一些技巧
- 不要使用POST:若是獲取數據,儘量不使用POST模式,因爲POST方式返回內容大部分不會被緩存,相對的,通過GET以路徑和查詢發送的信息被緩存存儲下來供後續使用。
- URL地址中不要嵌入特定的用戶信息,除非生成的內容對於用戶而言是唯一的。
- 不要指望同一用戶的所有請求來自同一主機,因爲緩存經常協同工作。//zxx: 嘛意思?
- 生成Content-Length⑩頭信息。實現不難,可讓你的腳本以持久連接(persistent connection)形式響應。這允許客戶端在一個TCP/IP請求上請求多個內容,而不是爲每次請求單獨建立連接,這樣你的網站相應會快很多。
詳見實現注意事項。
⑩Content-Length:指明實體正文的長度,以字節方式存儲的十進制數字來表示。在數據下行的過程中,Content-Length的方式要預先在服務器中緩存所有數據,然後所有數據再一股腦兒地發給客戶端。
常見問題解答
緩存可用的最重要事情是?
其中一個不錯的策略是找出常用的、規模較大的內容(尤其圖片),然後優先處理之。
我該如何利用緩存讓我的頁面儘可能的快?
最應該緩存的內容設置一個較長的過期時間。驗證有助於減少查看內容的時間,不過緩存仍會連接源服務器查看是不是過期了。如果緩存已經知道內容是新鮮的,直接返回。
我知道緩存是個好東西,但是我想隨時知道多少人訪問了我的網頁!
如果你必須知道每一次頁面被訪問的情況,可以選擇頁面上的一個小元素(或頁面本身),然後給這個元素一個適當的頭信息使它是不可緩存。比如,你可以在每一個頁面上引用一個1像素×1像素的不可緩存(如scr地址後面加個隨機數Add)的透明圖片。Referer頭信息將會包含調用它的頁面信息。
請注意,即使這樣也不能給出你用戶的精確統計,並且對通過互聯網訪問的用戶也不是很友好:產生不必要的流量,並強迫用戶等待未被緩存的內容從網絡上下載回來。更多的信息可參見拓展閱讀中的“解讀訪問統計”對應內容。
我該如何查看HTTP頭?
許多瀏覽器可以查看Expires
和Last-Modified
頭信息,如右鍵→查看頁面信息或類似面板。例如,在Firefox瀏覽器下Add:
表示要看到完整的頭,您可以使用Telnet⑪客戶端手動連接到Web服務器上。
爲此,你可能需要用一個字段指定端口(默認是80),或者連接到www.example.com:80
或者www.example.com
80
(注意是空格),更多設置請參考一下telnet客戶端的文檔。
一旦連接到該網站,輸入請求。比如,你想查看http://www.example.com/foo.html
的頭信息,首先連接到www.example.com
,
使用80端口,並輸入:
GET /foo.html HTTP/1.1 [return] Host: www.example.com [return][return]
[return]
等同敲回車鍵,最後輸入兩次確認。這樣就會輸出頭信息,然後跟着實際內容。如果只想看到頭信息,使用HEAD
來替換GET
.
⑪Telnet:Telnet協議是TCP/IP協議族中的一員,是Internet遠程登陸服務的標準協議和主要方式。它爲用戶提供了在本地計算機上完成遠程主機工作的能力。在終端使用者的電腦上使用telnet程序,用它連接到服務器。終端使用者可以在telnet程序中輸入命令,這些命令會在服務器上運行,就像直接在服務器的控制檯上輸入一樣。可以在本地就能控制服務器。要開始一個telnet會話,必須輸入用戶名和密碼來登錄服務器。Telnet是常用的遠程控制Web服務器的方法。
我的頁面是密碼保護的,代理緩存是怎麼處理的?
默認情況下,HTTP驗證保護的頁面是私有的,共享緩存是不能保存的。然而,你可以通過Cache-Control: public
頭的設置使其公有。HTTP 1.1標準兼容的緩存服務器可以使之緩存。
如果你希望這些緩存的頁面在用戶查看之前還要驗證一下,可以組合使用Cache-Control: public
和no-cache
頭,這相對於告訴緩存器它從緩存中送出內容前必須遞交客戶端的驗證給原始服務器。這個頭信息如下所示:
Cache-Control: public, no-cache
不管怎麼,這是最小化驗證最好的方法;例如,你的圖片不敏感,你可以把它放在分離的目錄中,並配置你的服務對它們不做強制驗證。這樣,那些圖片就會很自然的被緩存了。
如果人們通過緩存訪問我的網站,我應該擔心安全嗎?
SSL頁面不會被代理服務器緩存,所以這個你不需要擔心。但是,代理服務器就好非SSL頁面請求以及URL抓取這口,你懂的,這是不安全的。無良的管理員可能就會收集網站用戶的信息,尤其在URL中。
事實上,任何網絡管理員都可以收集你的客戶端和服務器端之間的這類信息。CGI⑫腳本有個漏洞,會把用戶名和密碼放在自身的URL地址中,這很容易讓其他人發現用戶的登陸信息。
如果你懂得互聯網安全的些基本機制,就不會對代理緩存感到任何驚訝。
⑫CGI:通用網關接口(Common Gateway Interface). 用於初始化軟件服務的服務器方接口。這套接口描述了Web服務器與同一計算機上的軟件的通信方式。
通用網關接口,它是一段程序,運行在服務器上,提供同客戶端HTML頁面的接口,通俗的講CGI就像是一座橋,把網頁和WEB服務器中的執行程序連接起來,它把HTML接收的指令傳遞給服務器,再把服務器執行的結果返還給HTML頁;用CGI可以實現處理表格,數據庫查詢,發送電子郵件等許多操作,最常見的CGI程序就是計數器。CGI使網頁變得不是靜態的,而是交互式的。
我在尋找一個集成的Web發佈解決方案。哪些是可緩存的?
這個是不確定的。一般來說,越複雜的系統越難緩存。最差的情況就是所有的內容都是動態生成,並且不提供校驗器,與緩存壓根無緣。你可以和你供應商的技術人員溝通獲取更多信息,並參考下面實現注意事項。
我的圖片緩存一個月後纔到期,我現在就想變動!Expires
頭是繞不過去的,除非緩存(瀏覽器或者代理)空間不足纔會刪除副本,緩存副本會一直使用。
最有效的方法是修改鏈接,這樣會從源服務器獲取完整的新內容。請記住,調用圖片的這個頁面也會被緩存的,正因如此,我們需要讓圖片以及其他類似的靜態資源易緩存,而頁面呢可以隨着自身的改變(例如改變了一個圖片的URL地址Add)即時更新。
如果你想擺脫特定緩存,重載內容,可以試試強制刷新(在FireFox中,shift鍵+reload按鈕等同於處理Pragma: no-cache
請求頭)或者讓緩存管理員使用某些接口刪除內容。
我運行一個Web Hosting服務。我怎樣才能讓我的用戶發佈緩存友好的網頁?
如果你使用apahe,可以考慮允許他們使用.htaccess
文件並提供相應的文檔。
否則你需要在每一個虛擬主機上爲各種緩存屬性建立預定的區域。比如:你可以指定一個叫/cache-1m
的目錄用來放讀取後要緩存一個月的內容,然後再建一個/no-cache
的目錄,並在頭信息中指定這麼目錄中的內容不被緩存。
不管上面你做的如何,總之最好優先給用戶量大的客戶做緩存處理。大部分服務器節約的流量以及負載都是來自高容量的網站。
我明明告訴網頁要好好緩存,但它老是去請求,怎麼破?
緩存服務器並不總是要求內容要保持並重用,某些條件下,他們是不保存不重用的,所有的緩存服務器都回基於文件的大小、類型(圖片、頁面…),或者服務器空間的剩餘來確定如何緩存。如果你的文件比較大或很熱門,可能就不會被緩存。有些緩存服務器允許管理員決定哪些內容要存儲,有些緩存服務器允許內容長存緩存中,所以,它們總是可用的。
實現需注意的:Web服務器端
一般說來,應該選擇最新版本的Web服務器程序來部署。不僅因爲它們包含更多利於緩存的功能,新版本往往在性能和安全性方面都有很多的改善。
Apache HTTP服務器
Apache使用可選模塊包含頭信息,頭信息Expires
和Cache-Control
一併包含。這些模塊在1.2版本以上都支持。
這些模塊需要編譯到Apache中,雖然包含,但是默認並未開啓。爲了確定相應模塊已經被啓用,找到httpd⑬程序,運行httpd
-l
, 它會列出可用的模塊(注意,僅有內部編譯的模塊列表纔會顯示,在較新版本的Apache中,使用httpd -M
可以包含動態加載的模塊N),我們需要關注的是expires模塊(expires_module
)和headers模塊(headers_module
)。
⑬httpd:httpd是Apache超文本傳輸協議(HTTP)服務器的主程序。被設計爲一個獨立運行的後臺進程,它會建立一個處理請求的子進程或線程的池。
- 如果這些模塊不可用,你需要聯繫管理員,重新編譯以包含這些模塊。這些模塊可以通過取消配置文件中的註釋掉啓用,或者在編譯的時候增加
-enable -module=expires
和-enable-module=headers
參數(apache 1.3+). 參開Apache中的INSTALL文件。
一旦你的Apache有了相應的模塊,你可以使用mod_expires
指定過期的時間,要麼在.htaccess
文件,要麼在服務器的access.conf
文件。你可以設置過期時間是從訪問時間開始還是文件修改時間開始,並應用到特定類型文件上或設爲默認配置。查看官方該模塊文檔獲得更多信息,或者遇到問題的時候向你身邊的apache專家討教。
爲應用Cache-Control
頭,你需要使用mod_headers
模塊,其允許你爲資源指定任意的頭信息。可參考mod_headers官方文檔。
下面是.htaccess
文件展示瞭如何使用頭信息:
.htaccess
文件允許Web發佈者使用配置文件中的指定。可以影響目錄以及子目錄內容。和你的服務器管理員溝通下,看看它們是否可用。### activate mod_expires ExpiresActive On ### Expire .gif's 1 month from when they're accessed ExpiresByType image/gif A2592000 ### Expire everything else 1 day from when it's last modified ### (this uses the Alternative syntax) ExpiresDefault "modification plus 1 day" ### Apply a Cache-Control header to index.html <Files index.html> Header append Cache-Control "public, must-revalidate" </Files>
- 注意,在有些情況下,
mod_expires
會自動計算並插入Cache-Control:max-age
頭信息。
Apache 2′s的配置和1.3類似,更多信息可以參考2.2N的mod_expires和mod_headers文檔。
微軟IIS
微軟的IIS有一些靈活的方式可以很容易得設置頭信息,不過似乎只針對IIS 4.0服務器,並且只能在NT服務器上運行。
爲了給網站某區域指定頭信息,需要進入Administration
(管理員)工具面板,然後再設置屬性。選擇HTTP
Headers
選項卡後,你會看到兩個有意思的區域:Enable Content Expiration
和Custom
HTTP headers
, 第一個含義一目瞭然,第二個用來應用Cache-Control
頭。//zxx:
此處的操作描述很過時了,看看window7下,操作界面早就大變樣了!
設置ASP頁面(Active Server Pages)的頭信息可以參考後面的ASP章節,也可以通過ISAPI模塊設置頭信息,細節請參考MSDN。
Netscape/iPlanet企業服務器
3.6版本以後,企業版服務器已經不能以任何方式設置Expires
頭信息了。然而,其從3.0版本開始支持HTTP 1.1的功能。這意味着HTTP 1.1的緩存(代理服務器/瀏覽器)利用你對Cache-Control
的設置來獲得。
爲了使用Cache-Control
頭,在管理員服務器中選擇Content
Management | Cache Control Directives
(內容管理|緩存控制指令)。然後,使用資源選擇器(Resource Picker),選擇你希望設置頭信息的目錄。設置完頭信息後,點擊”確定”。更多信息請參考NES手冊。
實現需注意的:服務端腳本
時刻謹記,在Web服務器上設置HTTP要比通過腳本設置輕鬆些。你可以兩者都試試。
因爲服務器端的腳本主要是爲了動態內容,所以即使實際上內容可以被緩存的,其也不會生成緩存很強的頁面。如果你的頁面內容經常變動,但不是每個頁面都中槍,可以考慮設置Cache-Control:
max-age
頭信息,大部分用戶是在相對端的時間內再次訪問這個頁面。例如:用戶點擊“後退”按鈕,如果沒有任何驗證或新鮮度信息,他們將不得不等待,直到從服務器頁面重新下載才能看到它。
CGI
CGI腳本是生成內容最常用的技術之一。你可以輕輕鬆鬆在請求發送給主體之前添加HTTP請求信息。大部分CGI實現都需要添加Content-Type
頭信息,例如這個Perl腳本://zxx:
還是挺好懂的
<#!/usr/bin/perl print "Content-type: text/html\n"; print "Expires: Thu, 29 Oct 1998 17:04:19 GMT\n"; print "\n"; ### the content body follows.../pre>
由於都是文本,你可以很容易通過內置函數生成Expires
和其他日期相關的頭信息。如果你使用Cache-Control:
max-age
會更簡單:
print "Cache-Control: max-age=600\n";
上面腳本可以讓請求完成後緩存10分鐘,因此,當用戶點擊“後退”按鈕的時候,就不會重新塗膠請求了。
CGI的規範同時也允許在腳本環境中,客戶端發送請求頭信息,每個頭信息都有一個'HTTP_'的前綴。於是乎,如果一個客戶端發送一個If-Modified-Since
請求,就是這樣的:
HTTP_IF_MODIFIED_SINCE
可觀摩cgi_buffer庫,其可以自動實現Etag
生成和驗證,Content-Length
生成及gzip內容,而所有這些實現,只需要一行include,就可以爲Perl和Python寫CGI腳本。Python版本還可以包裝任意的CGI腳本。
服務器端包含
SSI(擴展名通常是.shtml
)最早可以生成動態內容的網站發佈方案。通過在頁面中使用特定的標籤,有一定限制的內HTML腳本就可以使用了。大部分的SSI實現不設置驗證器,故無法緩存。不過Apache服務器允許通過設置讓SSI文件可緩存,通過適當的文件並結合XbitHack
full
指令設置組執行權限。欲瞭解更多信息,請參閱mod_include文檔。
PHP
PHP爲服務器端腳本語言,在服務器內置的時候,可以在HTML頁面中內嵌使用,很像SSL,不過有更多的可選項。PHP可以在任何Web服務器(Unix或Windows)或Apache模塊上作爲CGI使用。
默認情況下,PHP生成的內容沒有分配驗證器,因此,不能緩存。不過,開發人員可以通過Header()
函數設置HTTP頭信息。例如,創建Cache-Control
頭,過期時間爲3天:
<?php 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()
需要在所有的輸出之前。
正如你看到的,你可以手工創建HTTP日期。PHP沒有專門的函數(新版本已改進,請參考PHP的日期相關函數文檔)。當然,最簡單的還是設置Cache-Control:
max-age
頭信息,適用於大部分情況。
更多內容,請參閱header手冊。
還是cgi_buffer庫,只要一行包含,就能以PHP腳本形式自動實現Etag
生成和驗證,Content-Length
生成及gzip內容。
Cold Fusion
Cold Fusion是Macromedia的商業服務器端腳本引擎,並且支持多種Windows平臺,Linux平臺和多種Unix平臺。//zxx: 看到Macromedia心亮了半截,幾百年前就被收購的公司……此文未免太過時了點了~~大家這段可以跳過了,幾乎沒有任何價值……
Cold Fusion通過CFHEADER標記設置HTTP頭信息相對容易。可惜的是,以下的Expires頭信息的設置有些容易誤導:
<CFHEADER NAME="Expires" VALUE="#Now()#">
它並不像你想像的那樣工作,因爲時間(本例中爲請求發起的時間)並不會被轉換成一個符合HTTP時間,而且打印出副本的Cold fusion的日期/時間對象,大部分客戶端會忽略或者將其轉換成1970年1月1日。
但是:Cold Fusion另外提供了一套日期格式化函數-GetHttpTimeSTring. 結合DateAdd函數,就很容易設置過期時間了,這裏我們設置一個頭信息,聲明內容在1個月以後過期:
<cfheader name="Expires" value="#GetHttpTimeString(DateAdd('m', 1, Now()))#">
你也可以使用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
才能被共享緩存服務器緩存。
ASP(Active Server Pages),IIS內置,也可用於其他Web服務器,同樣允許你設置HTTP頭。例如設置過期時間,你可以使用Response
自帶屬性:
<% Response.Expires=1440 %>
指定內容過期的分鐘數。Cache-Control
頭添加如下:
<% Response.CacheControl="public" %>
在ASP.NET中,Response.Expires
已經不推薦使用了,正確的方法是通過Response.Cache
設置緩存相關的頭信息,如下:
Response.Cache.SetExpires ( DateTime.Now.AddMinutes ( 60 ) ) ; Response.Cache.SetCacheability ( HttpCacheability.Public ) ;
參考文檔和拓展閱讀
HTTP 1.1規範
HTTP 1.1的規範對頁面緩存以及權威的接口實現指南有了大量的擴展,參考章節:13, 14.9, 14.21以及14.25 .
Web-Caching.com
對緩存概念有很好的介紹,並且有很多其他在線資源的鏈接。
解讀訪問統計
Jeff Goldberg這篇內容豐富敘述會告訴你爲什麼不應該過度依賴訪問統計和計數器。//zxx 上世紀的復古頁面...
REDbot
檢查HTTP資源,以確定它們如何與Web緩存交互,以及通常如何使用該協議。
cgi_buffer庫
只要包含一行Perl CGI, Python CGI以及PHP腳本,就能自動實現Etag
生成以及驗證,Content-Length
生成以及Gzip內容的正確編碼。Python版本還可以包裝任意的CGI腳本。
關於本文檔
本文版權屬於Mark Nottingham © 1998-2013 郵箱爲[email protected]
.
本作品遵循知識共享署名 - 非商業性使用 - 禁止演繹3.0聲明頁面許可證N。
所有的商標版權爲其持有人所有。
內容在發佈時是可以確保其正確性,但是,隨着時間推移,就不能保證正確無誤了。因此,如有鏈接404,描述錯誤或其他需要糾正的問題請儘快告知作者。
本文最新版本可以從http://www.mnot.net/cache_docs/獲得
文檔說明:含有上標N的表示與前輩翻譯時候相比新增的;上標Add表示作爲譯者的我爲了便於理解自己添加的;上標數字(①-⑬)是對一些可能不熟悉的名詞的百科解釋。
雖然原作語言不生動,教科書般一板一眼⑭;有些可能過時了。不過,還是學到了很多東西。還是很值的!歡迎分享,歡迎傳播,以後面試之前來這裏看看,可能會有幫助哦!
⑭ 如果我介紹緩存,我可能就這麼講:緩存是什麼?顧名思意,就是緩慢的存錢。爲什麼要緩慢的存錢,因爲工資卡都上交老婆了,爲了攢點零花錢又不能被老婆發現,只能慢慢存了。那緩存有什麼用呢?你想啊,自己有點小錢,做事情就方便快捷了,比方說我想買個魚竿,就不要去向老婆要(給不給先不談),自己從自己這邊取,大大提高了執行的速度。
那什麼時候可以存什麼時候不能存呢?老婆給零花錢的時候,可能會有過期時間頭,例如,週一甩了100塊錢,拿去,這是一週的伙食!這個一週就是過期時間頭(Expires Header),在這個時間內,你的錢可以從緩存,也就是自己這裏取……
轉自:http://www.zhangxinxu.com/wordpress/2013/05/caching-tutorial-for-web-authors-and-webmasters/