轉載 web緩存技術

Web緩存技術|網站緩存技術

這是一篇知識性的文檔,主要目的是爲了讓Web緩存相關概念更容易被開發者理解並應用於實際的應用環境中。爲了簡要起見,某些實現方面的細節被簡化或省略了。如果你更關心細節實現則完全不必耐心看完本文,後面參考文檔和更多深入閱讀部分可能是你更需要的內容。

  1. 什麼是Web緩存,爲什麼要使用它?
  2. 緩存的類型:
    1. 瀏覽器緩存;
    2. 代理服務器緩存;
  3. Web緩存無害嗎?爲什麼要鼓勵緩存?
  4. Web緩存如何工作:
  5. 如何控制(控制不)緩存:
    1. HTML Meta標籤 vs. HTTP頭信息;
    2. Pragma HTTP頭信息(爲什麼不起作用);
    3. 使用Expires(過期時間)HTTP頭信息控制保鮮期;
    4. Cache-Control(緩存控制) HTTP頭信息;
    5. 校驗參數和校驗;
  6. 創建利於緩存網站的竅門;
  7. 編寫利於緩存的腳本;
  8. 常見問題解答;
  9. 緩存機制的實現:Web服務器端配置;
  10. 緩存機制的實現:服務器端腳本;
  11. 參考文檔和深入閱讀;
  12. 關於本文檔;

什麼是Web緩存,爲什麼要使用它?

Web緩存位於Web服務器之間(1個或多個,內容源服務器)和客戶端之間(1個或多個):緩存會根據進來的請求保存輸出內容的副本,例如html頁面, 圖片,文件(統稱爲副本),然後,當下一個請求來到的時候:如果是相同的URL,緩存直接使用副本響應訪問請求,而不是向源服務器再次發送請求。

使用緩存主要有2大理由:

  • 減少相應延遲:因爲請求從緩存服務器(離客戶端更近)而不是源服務器被相應,這個過程耗時更少,讓web服務器看上去相應更快;
  • 減少網絡帶寬消耗:當副本被重用時會減低客戶端的帶寬消耗;客戶可以節省帶寬費用,控制帶寬的需求的增長並更易於管理。

緩存的類型

瀏覽器緩存

對 於新一代的Web瀏覽器來說(例如:IE,Firefox):一般都能在設置對話框中發現關於緩存的設置,通過在你的電腦上僻處一塊硬盤空間用於存儲你已 經看過的網站的副本。瀏覽器緩存根據非常簡單的規則進行工作:在同一個會話過程中(在當前瀏覽器沒有被關閉之前)會檢查一次並確定緩存的副本足夠新。這個 緩存對於用戶點擊“後退”或者點擊剛訪問過的鏈接特別有用,如果你瀏覽過程中訪問到同一個圖片,這些圖片可以從瀏覽器緩存中調出而即時顯現。

代理服務器緩存

Web代理服務器使用同樣的緩存原理,只是規模更大。代理服務器羣爲成百上千用戶服務使用同樣的機制;大公司和ISP經常在他們的防火牆上架設代理緩存或者單獨的緩存設備;

由 於帶路服務器緩存並非客戶端或者源服務器的一部分,而是位於原網絡之外,請求必須路由到他們才能起作用。一個方法是手工設置你的瀏覽器:告訴瀏覽器使用 那個代理,另外一個是通過中間服務器:這個中間服務器處理所有的web請求,並將請求轉發到後臺網絡,而用戶不必配置代理,甚至不必知道代理的存在;

代理服務器緩存:是一個共享緩存,不只爲一個用戶服務,經常爲大量用戶使用,因此在減少相應時間和帶寬使用方面很有效:因爲同一個副本會被重用多次。

網關緩存

也被稱爲反向代理緩存或間接代理緩存,網關緩存也是一箇中間服務器,和內網管理員部署緩存用於節省帶寬不同:網關緩存一般是網站管理員自己部署:讓他們的網站更容易擴展並獲得更好的性能;
請求有幾種方法被路由到網關緩存服務器上:其中典型的是讓用一臺或多臺負載均衡服務器從客戶端看上去是源服務器;

網絡內容發佈商  (Content delivery networks CDNs)分佈網關緩存到整個(或部分)互聯網上,並出售緩存服務給需要的網站,SpeederaAkamai就是典型的網絡內容發佈商(下文簡稱CDN)。

本問主要關注於瀏覽器和代理緩存,當然,有些信息對於網關緩存也同樣有效;

Web緩存無害嗎?爲什麼要鼓勵緩存?

Web緩存在互聯網上最容易被誤解的技術之一:網站管理員經常怕對網站失去控制,由於代理緩存會“隱藏”他們的用戶,讓他們感覺難以監控誰在使用他們的網站。
不幸的是:就算不考慮Web緩存,互聯網上也有很多網站使用非常多的參數以便管理員精確地跟蹤用戶如何使用他們的網站;如果這類問題也是你關心的,本文將告訴你如何獲得精確的統計而不必將網站設計的非常緩存不友好。
另外一個抱怨是緩存會給用戶過期或失效的數據;無論如何:本文可以告訴你怎樣配置你的服務器來控制你的內容將被如何緩存。

CDN是另外一個有趣的方向,和其他代理緩存不同:CDN的網關緩存爲希望被緩存的網站服務,沒有以上顧慮。即使你使用了CDN,你也要考慮後續的代理服務器緩存和瀏覽器緩存問題。

另外一方面:如果良好地規劃了你的網站,緩存會有助於網站服務更快,並節省服務器負載和互聯網的鏈接請求。這個改善是顯著的:一個難以緩存的網站可能需要幾秒去載入頁面,而對比有緩存的網站頁面幾乎是即時顯現:用戶更喜歡速度快的網站並更經常的訪問;

這樣想:很多大型互聯網公司爲全世界服務器羣投入上百萬資金,爲的就是讓用戶訪問儘可能快,客戶端緩存也是這個目的,只不過更靠近用戶一端,而且最好的一點是你甚至根本不用爲此付費。

事實上,無論你是否喜歡,代理服務器和瀏覽器都回啓用緩存。如果你沒有配置網站正確的緩存,他們會按照缺省或者緩存管理員的策略進行緩存。

緩存如何工作

所有的緩存都用一套規則來幫助他們決定什麼時候使用緩存中的副本提供服務(假設有副本可用的情況下);一些規則在協議中有定義(HTTP協議1.0和1.1),一些規則由緩存的管理員設置(瀏覽器的用戶或者代理服務器的管理員);
一般說來:遵循以下基本的規則(不必擔心,你不必知道所有的細節,細節將隨後說明)

  1. 如果響應頭信息:告訴緩存器不要保留緩存,緩存器就不會緩存相應內容;
  2. 如果請求信息是需要認證或者安全加密的,相應內容也不會被緩存;
  3. 如果在迴應中不存在校驗器(ETag或者Last-Modified頭信息),緩存服務器會認爲缺乏直接的更新度信息,內容將會被認爲不可緩存。
  4. 一個緩存的副本如果含有以下信息:內容將會被認爲是足夠新的
    • 含有完整的過期時間和壽命控制頭信息,並且內容仍在保鮮期內;
    • 瀏覽器已經使用過緩存副本,並且在一個會話中已經檢查過內容的新鮮度;
    • 緩存代理服務器近期內已經使用過緩存副本,並且內容的最後更新時間在上次使用期之前;
    • 夠新的副本將直接從緩存中送出,而不會向源服務器發送請求;
  5. 如果緩存的副本已經太舊了,緩存服務器將向源服務器發出請求校驗請求,用於確定是否可以繼續使用當前拷貝繼續服務;

總之:新鮮度校驗是確定內容是否可用的最重要途徑:

如果副本足夠新,從緩存中提取就立刻能用了;
而經緩存器校驗後發現副本的原件沒有變化,系統也會避免將副本內容從源服務器整個重新傳輸一遍。

如何控制(控制不)緩存

有很多工具可以幫助設計師和網站管理員調整緩存服務器對待網站的方式,這也許需要你親自下手對服務器的配置進行一些調整,但絕對值得;瞭解如何使用這些工具請參考後面的實現章節;

HTML meta標籤和HTTP 頭信息

HTML的編寫者會在文檔的<HEAD>區域中加入描述文檔的各種屬性,這些META標籤常常被用於標記文檔不可以被緩存或者標記多長時間後過期;
META標籤使用很簡單:但是效率並不高,因爲只有幾種瀏覽器會遵循這個標記(那些真正會“讀懂”HTML的瀏覽器),沒有一種緩存代理服務器能遵循這個 規則(因爲它們幾乎完全不解析文檔中HTML內容);有事會在Web頁面中增加:Pragma: 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(過期時間)屬性;

大部分Web服務器支持你用幾種方式設置Expires屬性;一般的:可以設計一個絕對時間間隔:基於客戶最後查看副本的時間(最後訪問時間)或者根據服務器上文檔最後被修改的時間;

Expires 頭信息:對於設置靜態圖片文件(例如導航欄和圖片按鈕)可緩存特別有用;因爲這些圖片修改很少,你可以給它們設置一個特別長的過期時間,這會使你的網站對 用戶變得相應非常快;他們對於控制有規律改變的網頁也很有用,例如:你每天早上6點更新新聞頁,你可以設置副本的過期時間也是這個時間,這樣緩存 服務器就知道什麼時候去取一個更新版本,而不必讓用戶去按瀏覽器的“刷新”按鈕。

過期時間頭信息屬性值只能是HTTP格式的日期時間,其他的都會被解析成當前時間“之前”,副本會過期,記住:HTTP的日期時間必須是格林威治時間(GMT),而不是本地時間。舉例:

Expires: Fri, 30 Oct 1998 14:19:41 GMT

所以使用過期時間屬性一定要確認你的Web服務器時間設置正確,一個途徑是通過網絡時間同步協議(Network Time Protocol NTP),和你的系統管理員那裏你可以瞭解更多細節。
雖然過期時間屬性非常有用,但是它還是有些侷限,首先:是牽扯到了日期,這樣Web服務器的時間和緩存服務器的時間必須是同步的,如果有些不同步,要麼是應該緩存的內容提前過期了,要麼是過期結果沒及時更新。
還有一個過期時間設置的問題也不容忽視:如果你設置的過期時間是一個固定的時間,如果你返回內容的時候又沒有連帶更新下次過期的時間,那麼之後所有訪問請求都會被髮送給源Web服務器,反而增加了負載和響應時間;

Cache-Control(緩存控制) HTTP頭信息

HTTP 1.1介紹了另外一組頭信息屬性:Cache-Control響應頭信息,讓網站的發佈者可以更全面的控制他們的內容,並定位過期時間的限制。
有用的 Cache-Control響應頭信息包括:

  • max-age=[秒] — 執行緩存被認爲是最新的最長時間。類似於過期時間,這個參數是基於請求時間的相對時間間隔,而不是絕對過期時間,[秒]是一個數字,單位是秒:從請求時間開始到過期時間之間的秒數。
  • s-maxage=[秒] — 類似於max-age屬性,除了他應用於共享(如:代理服務器)緩存
  • public — 標記認證內容也可以被緩存,一般來說: 經過HTTP認證才能訪問的內容,輸出是自動不可以緩存的;
  • no-cache — 強制每次請求直接發送給源服務器,而不經過本地緩存版本的校驗。這對於需要確認認證應用很有用(可以和public結合使用),或者嚴格要求使用最新數據的應用(不惜犧牲使用緩存的所有好處);
  • no-store — 強制緩存在任何情況下都不要保留任何副本
  • must-revalidate — 告訴緩存必須遵循所有你給予副本的新鮮度的,HTTP允許緩存在某些特定情況下返回過期數據,指定了這個屬性,你高速緩存,你希望嚴格的遵循你的規則。
  • proxy-revalidate — 和 must-revalidate類似,除了他只對緩存代理服務器起作用

舉例:

Cache-Control: max-age=3600, must-revalidate

如果你計劃試用Cache-Control屬性,你應該看一下這篇HTTP文檔,詳見參考和深入閱讀;

校驗參數和校驗

在Web緩存如何工作: 我們說過:校驗是當副本已經修改後,服務器和緩存之間的通訊機制;使用這個機制:緩存服務器可以避免副本實際上仍然足夠新的情況下重複下載整個原件。
校驗參數非常重要,如果1個不存在,並且沒有任何信息說明保鮮期(Expires或Cache-Control)的情況下,緩存將不會存儲任何副本;
最常見的校驗參數是文檔的最後修改時間,通過最後Last-Modified頭信息可以,當一份緩存包含Last-Modified信息,他基於此信息,通過添加一個If-Modified-Since請求參數,向服務器查詢:這個副本從上次查看後是否被修改了。
HTTP 1.1介紹了另外一個校驗參數: ETag,服務器是服務器生成的唯一標識符ETag,每次副本的標籤都會變化。由於服務器控制了ETag如何生成,緩存服務器可以通過If-None-Match請求的返回沒變則當前副本和原件完全一致。
所有的緩存服務器都使用Last-Modified時間來確定副本是否夠新,而ETag校驗正變得越來越流行;
所有新一代的Web服務器都對靜態內容(如:文件)自動生成ETag和Last-Modified頭信息,而你不必做任何設置。但是,服務器對於動態內容(例如:CGI,ASP或數據庫生成的網站)並不知道如何生成這些信息,參考一下編寫利於緩存的腳本章節;

創建利於緩存網站的竅門

除了使用新鮮度信息和校驗,你還有很多方法使你的網站緩存友好。

  • 保持URL穩定: 這是緩存的金科玉律,如果你給在不同的頁面上,給不同用戶或者從不同的站點上提供相同的內容,應該使用相同的URL,這是使你的網站緩存友好最簡單,也是 最高效的方法。例如:如果你在頁面上使用 “/index.html” 做爲引用,那麼就一直用這個地址;
  • 使用一個共用的庫存放每頁都引用的圖片和其他頁面元素;
  • 對於不經常改變的圖片/頁面啓用緩存,並使用Cache-Control: max-age屬性設置一個較長的過期時間;
  • 對於定期更新的內容設置一個緩存服務器可識別的max-age屬性或過期時間;
  • 如果數據源(特別是下載文件)變更,修改名稱,這樣:你可以讓其很長時間不過期,並且保證服務的是正確的版本;而鏈接到下載文件的頁面是一個需要設置較短過期時間的頁面。
  • 萬不得已不要改變文件,否則你會提供一個非常新的Last-Modified日期;例如:當你更新了網站,不要複製整個網站的所有文件,只上傳你修改的文件。
  • 只在必要的時候使用Cookie,cookie是非常難被緩存的,而且在大多數情況下是不必要的,如果使用cookie,控制在動態網頁上;
  • 減少試用SSL,加密的頁面不會被任何共享緩存服務器緩存,只在必要的時候使用,並且在SSL頁面上減少圖片的使用;
  • 使用可緩存性評估引擎,這對於你實踐本文的很多概念都很有幫助;

編寫利於緩存的腳本

腳本缺省不會返回校驗參數(返回Last-Modified或ETag頭信息)或其他新鮮度信息(Expires或Cache-Control),有些動 態腳本的確是動態內容(每次相應內容都不一樣),但是更多(搜索引擎,數據庫引擎網站)網站還是能從緩存友好中獲益的。
一般說來,如果腳本生成的輸出在未來一段時間(幾分鐘或者幾天)都是可重複複製的,那麼就是可緩存的。如果腳本輸出內容只隨URL變化而變化,也是可緩存的;但如果輸出會根據cookie,認證信息或者其他外部條件變化,則還是不可緩存的。

  • 最利於緩存的腳本就是將內容改變時導出成靜態文件,Web服務器可以將其當作另外一個網頁並生成和試用校驗參數,讓一些都變得更簡單,只需要寫入文件即可,這樣最後修改時間也有了;
  • 另外一個讓腳本可緩存的方法是對一段時間內能保持較新的內容設置一個相對壽命的頭信息,雖然通過Expires頭信息也可以實現,但更容易的是用Cache-Control: max-age屬性,它會讓首次請求後一段時間內緩存保持新鮮;
  • 如 果以上做法你都做不到,你可以讓腳本生成一個校驗屬性,並對 If-Modified-Since 和/或If-None-Match請求作出反應,這些屬性可以從解析HTTP頭信息得到,並對符合條件的內容返回304 Not Modified(內容未改變),可惜的是,這種做法比不上前2種高效;

其他竅門:

  • 儘量避免使用POST,除非萬不得已,POST模式的返回內容不會被大部分緩存服務器保存,如果你發送內容通過URL和查詢(通過GET模式)的內容可以緩存下來供以後使用;
  • 不要在URL中加入針對每個用戶的識別信息:除非內容是針對每個用戶不同的;
  • 不要統計一個用戶來自一個地址的所有請求,因爲緩存常常是一起工作的;
  • 生成並返回Content-Length頭信息,如果方便的話,這個屬性讓你的腳本在可持續鏈接模式時:客戶端可以通過一個TCP/IP鏈接同時請求多個副本,而不是爲每次請求單獨建立鏈接,這樣你的網站相應會快很多;

具體定義請參考實現章節。

常見問題解答

讓網站變得可緩存的要點是什麼?

好的策略是確定那些內容最熱門,大量的複製(特別是圖片)並針對這些內容先部署緩存。

如何讓頁面通過緩存達到最快相應?

緩存最好的副本是那些可以長時間保持新鮮的內容;基於校驗雖然有助於加快相應,但是它不得不和源服務器聯繫一次去檢查內容是否夠新,如果緩存服務器上就知道內容是新的,內容就可以直接相應返回了。

我理解緩存是好的,但是我不得不統計多少人訪問了我的網站!

如果你必須知道每次頁面訪問的,選擇【一】個頁面上的小元素,或者頁面本身,通過適當的頭信息讓其不可緩存,例如: 可以在每個頁面上部署一個1×1像素的透明圖片。Referer頭信息會有包含這個圖片的每個頁面信息;
明確一點:這個並不會給你一個關於你用戶精確度很高的統計,而且這對互聯網和你的用戶這都不太好,消耗了額外的帶寬,強迫用戶去訪問無法緩存的內容。瞭解更多信息,參考訪問統計資料。

我如何能看到HTTP頭信息的內容?

很多瀏覽器在頁面屬性或類似界面中可以讓你看到Expires 和Last-Modified信息;如果有的話:你會找到頁面信息的菜單和頁面相關的文件(如圖片),並且包含他們的詳細信息;
看到完整的頭信息,你可以用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 [回車]
GET /foo.html HTTP/1.1 [return]
Host: www.example.com [回車][回車] 
Host: www.example.com [return][return]

在[回車]處按鍵盤的回車鍵;在最後,要按2次回車,然後,就會輸出頭信息及完整頁面,如果只想看頭信息,將GET換成HEAD。

我的頁面是密碼保護的,代理緩存服務器如何處理他們?

缺省的,網頁被HTTP認證保護的都是私密內容,它們不會被任何共享緩存保留。但是,你可以通過設置Cache-Control: public讓認證頁面可緩存,HTTP 1.1標準兼容的緩存服務器會認出它們可緩存。
如果你認爲這些可緩存的頁面,但是需要每個用戶認證後才能看,可以組合使用Cache-Control: public和no-cache頭信息,高速緩存必須在提供副本之前,將將新客戶的認證信息提交給源服務器。設置就是這樣:

Cache-Control: public, no-cache

無論如何:這是減少認證請求的最好方法,例如: 你的圖片是不機密的,將它們部署在另外一個目錄,並對此配置服務器不強制認證。這樣,那些圖片會缺省都緩存。

我們是否要擔心用戶通過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發佈者使用命令只在配置文件中用到的命令。他影響到所在目錄及其子目錄;問一下你的服務器管理員確認這個功能是否啓用了。
### 啓用 mod_expires
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 頭信息

Apache 2.0的配置和1.3類似,更多信息可以參考2.0的mod_expiresmod_headers文檔

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/perl
print “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請求,就是這樣的:

HTTP_IF_MODIFIED_SINCE = Fri, 30 Oct 1998 14:19:41 GMT

參考一下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頭信息;

<?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()的輸出必須先於所有其他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 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才能被共享緩存服務器緩存。
IIS的ASP和其他web服務器都允許你設置HTTP頭信息,例如: 設置過期時間,你可以設置Response對象的屬性;

<% Response.Expires=1440 %>

設置請求的副本在輸出的指定分鐘後過期,類似的:也可以設置絕對的過期時間(確認你的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 規範定義

HTTP 1.1的規範有大量的擴展用於頁面緩存,以及權威的接口實現指南,參考章節:13, 14.9, 14.21, 以及 14.25.

Web-Caching.com

非常精彩的介紹緩存相關概念,並介紹其他在線資源。

關於非連續性訪問統計

Jeff Goldberg內容豐富的演說告訴你爲什麼不應該過度依賴訪問統計和計數器;

可緩存性檢測引擎

可緩存的引擎設計,檢測網頁並確定其如何與Web緩存服務器交互, 這個引擎配合這篇指南是一個很好的調試工具,

cgi_buffer庫

包含庫:用於CGI模式運行的Perl/Python/PHP腳本,自動處理ETag生成/校驗,Content-Length生成和內容壓縮。正確地。 Python版本也被用作其他大量的CGI腳本。

關於本文檔

本文版權屬於Mark Nottingham <[email protected]>,本作品遵循創作共用版權
如果你鏡像本文,請通過以上郵件告知,這樣你可以在更新時被通知;
所有的商標屬於其所有人。
雖然作者確信內容在發佈時的正確性,但不保證其應用或引申應用的正確性,如有誤傳,錯誤或其他需要澄清的問題請儘快告知作者;
本文最新版本可以從 http://www.mnot.net/cache_docs/ 獲得;
翻譯版本包括: 捷克語版法語版中文版
版本: 1.81 – 2007年3月16日
創作共用版權聲明
翻譯: 車東 2007年9月6日

發佈了77 篇原創文章 · 獲贊 1 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章