Web緩存:
// 是可以自動保存常見文檔副本的HTTP設備.
// 當Web請求抵達緩存時,如果本地有"已緩存的"副本,就可以從本地存儲設備而不是原始服務器中提取這個文檔.
冗余的數據傳輸:
// 有很多客戶端訪問一個流行的原始服務器頁面時,服務器會多次傳輸同一份文檔
// 每次傳遞給一個客戶端.這樣一些相同的字節會在網絡中一遍遍的傳輸,大 大的降低了網絡的傳輸效率,浪費Web資源.
// 有了緩存,就可以保留第一條服務器響應的副本.
帶寬瓶頸:
// 很多網絡為本地網絡客戶端提供的帶寬比遠程服務器提供的帶寬要寬.因此提供緩存可以提供交互的速度
緩存未命中:
// 一些到達緩存的請求可能會由于沒用副本可用,而被轉發給原始服務器,稱為緩存未命中.
再驗證:
// 原始服務器的內容可能會發生變化,緩存要不時對其進行檢測,看看它們保存的副本是否仍時服務器上最新的副本
// 這些"新鮮度檢測"被稱為HTTP再驗證
再驗證命中(緩慢命中):
// 緩存對緩存的副本進行再驗證時,會向原始服務器發送一個小的在驗證請求.如果內容沒有變化
// 服務器會以一個小的304 Not Modified進行響應.
// 只要緩存知道副本仍然有效,就會再次將副本標識為暫時新鮮的,并將副本提供給客戶端,這被稱作在驗證命中或緩慢命中
緩存命中率:
// 緩存提供服務的請求所占的比例稱為緩存命中率
// 對中等規模的Web緩存來說,40%的命中率是很合理的
字節命中率:
// 緩存提供的字節在傳輸的所有字節中所占的比例
私有緩存:
// 私有緩存不需要很大的存儲空間,這樣可以做得很小很便宜.
// Web瀏覽器中有內建的私有緩存---大多數瀏覽器都會將常用文檔緩存在個人電腦的磁盤和內存中,并且允許用戶區配置緩存的大小和各種設置
公有代理緩存:
// 公有緩存是特殊的共享代理服務器,被稱為緩存代理服務器(caching proxy server)或常見的代理緩存(proxy cache)
// 代理緩存會從本地緩存中提供文檔,或者代表用戶于服務器進行聯系
內容路由器:
// 有些網絡結構會構建復雜的網狀緩存,網狀緩存中的代理緩存之間會以更加復雜的方式進行對話,做出動態的緩存通信決策
// 決定與哪個父緩存進行對話,或者決定繞開緩存,直接連接原始服務器.這種代理緩存會決定選擇何種路由器對內容進行訪問、管理和傳送
文檔過期:
// HTTP有一些簡單的機制可以再不要求服務器記住有哪些緩存擁有其文檔副本的情況下,保持已緩存數據與服務器之間充分一致
// HTTP將之稱為文檔過期.// 文檔過期(Expires首部)
HTTP/1.0 200 OK
Date: Sat, 29 Jun 2002, 14:30:00 GMT
Content-type: text/plain
Content-legnth: 67
Expires: Fri, 05 Jul 2002, 05:00:00 GMTIndependence Day sale at Joe`s Hardware Come shop with us today!// Cache-Control: max-age 首部 (最大的生存時間,單位:秒)
HTTP/1.0 200 OK
Date: Sat, 29 Jun 2002, 14:30:00 GMT
Content-type: text/plain
Content-length: 67
Cache-Control: max-age=484200Independence Day sale at Joe`s Hardware Come shop with us today!
服務器再驗證:
// 僅僅是已緩存文檔過期了并不意味著它和原始服務器上目前處于活躍狀態的文檔有實際區別;只是意味著到了要進行核對的時間了.
// 這種情況稱為“服務器再驗證”// If-Modified-Since:Date再驗證
// 條件請求
GET /announce.html HTTP/1.0
If-Modified-Since: Sat, 29 Jun 2002, 14:30:00 GMT// 響應(成功的在驗證)
HTTP/1.0 304 Not Modified
Date: Wed, 03 Jul 2002, 19:18:23 GMT
Expires: Fri, 05 Jul 2002, 14:30:00 GMT// 響應(失敗的再驗證)
HTTP/1.0 200 OK
Date: Fri, 05 Jul 2002, 17:54:40 GMT
Content-length: 124
Expires: Mon, 09 Sep 2002, 05:00:00 GMTAll exterior house paint on sale through Labor Day.
Just Another reason for you to shop this summer at Joe`s Hardware!// If-None-Match:實體標簽再驗證(再某些情況下,僅使用最后修改日期再驗證是不夠的)
// 條件請求
GET /announce.html HTTP/1.0
If-None-Match: "v2.6"// 響應
HTTP/1.0 304 Not Modified
Date: Wed, 03 Jul 2002, 19:18:23 GMT
ETag: "v2.6"
Expires: Fri, 05 Jul 2002, 05:00:00 GMT// 強弱驗證器
// 有時服務器希望對文檔進行一些非實質性或不重要的修改時,不要使所有的已緩存副本都失效,
// HTTP/1.1支持"弱驗證器"
// 服務器會用"W/"來標識弱驗證器
ETag: W/"v2.6"
If-None-Match: W/"v2.6"
no-Store與no-Cache響應首部
Pragma: no-cache
Cache-Control: no-store
Cache-Control: no-cache
// no-store:禁止緩存對響應進行復制
// no-cache的響應在與原始服務器進行新鮮度再驗證之前,緩存不能將其提供給客戶端使用
// 以上2種對象是HTTP/1.1提供的,為了兼容于HTTP/1.0+,使用了Pragma: no-cache
max-age:
Cache-Control: max-age=3600
Cache-Control: s-maxage=3600
// max-age 此文檔處于新鮮狀態的秒數
// s-maxage 此文檔處于新鮮狀態的秒數,但僅適用于共享(公有)緩存// 服務器請求緩存不緩存該文檔:
Cache-Control: max-age=0
Cache-Control: s-maxage = 0
Expires:
Expires: Fri, 05 Jul 2002, 05:00:00 GMT
// 實際的過期日期
// 不推薦使用的原因:許多服務器的時鐘都不同步,或者不正確,所以最好用剩余秒數
must-revalidate:
Cache-Control: must-revalidate
// 原始服務器希望緩存嚴格遵守過期信息
// 該響應首部告訴緩存,在事先沒有跟原始服務器進行再驗證的情況下,不能提供對這個對象的陳舊副本
試探性過期
// 如果響應種沒有Cache-Control: max-age首部,也沒有Expires首部,緩存可以計算出一個試探性最大使用期
// 如果得到的最大試用期大于24小時,就應該向響應首部添加一個Heuristic Expiration WarningLM-Factor算法:
// 邏輯:
// 如果已緩存文檔最后一次修改發生在很久以前,它可能會是一份穩定的文檔,不太會突然發生變化 ,因此將其繼續保存在緩存中
// 如果已緩存文檔近期被修改過,就說明它很可能會頻繁發生變化,因此在與服務器進行再驗證之前,只應該將其緩存很短一段時間
// 下面是LM-factor算法的Perl偽代碼:
$time_since_modify = max(0, $server_Date - $server_Last_Modified);
$server_freshness_limit = int($time_since_modify * $lm_factor);
Apache關于緩存的HTTP首部
// mod_headers
// 將某目錄下的所有HTML文件都標識為非緩存
<Files * .html>Header set Cache-control no-cache
</Files>// mode_expires
// 將文檔的過期日期設置為對其最后一次被訪問之后或者其最近修改日期之后的某一時間
// 可以為不同的文件類型設置不同的過期日期
ExpiresDefault A3600
ExpiresDefault M86400
ExpiresDefault "access plus 1 week"
ExpiresByType text/html "modification plus 2 days 6 hours 12 minutes"
通過HTTP-EQUIV控制HTML緩存
// 讓coder無需與Web服務器的配置文件進行交互,能夠更容易地為所提供地HTML文檔分配HTTP首部信息
// HTML2.0 定義了 <META HTTP-EQUIV>標簽
<HTML><HEAD><TITLE>My Document</TITLE><META HTTP-EQUIV="Cache-control" CONNECT="no-cache"></HEAD>...
</HTML>
新鮮度算法(服務器)
sub server_freshness_limit
{local($heuristic, $server_freshness_limit,$time_since_last_modify);$heuristic = 0;if ($Max_Age_value_set) {$server_freshness_limit = $Max_Age_value;} else if ($Expires_value_set) {$server_freshness_limit = $Expires_value - $Date_value;} else if($Last_Modified_value_set) {$time_since_last_modify = max(0, $Date_value - $Last_Modified_value);$server_freshness_limit = int($time_since_last_modify * $lm_factor);$heuristic = 1;} else{$server_freshness_limit = $default_cache_min_lifetime;$heuristic = 1;}if($heuristic) {if($server_freshness_limit > $default_cache_max_lifetime) {$server_freshness_limit = $default_cache_max_lifetime;}if( $server_freshness_limit < $default_cache_min_lifetime) {$server_freshness_limit = $default_cache_min_lifetime;}return ($server_freshness_limit);}
}
新鮮度算法(客戶端)
sub client_modified_freshness_limit
{$age_limit = server_freshness_limit();if($Max_Stale_value_set) {if( $Max_Stale_value == $INT_MAX){$age_limit = $INT_MAX;} else{$age_limit = server_freshness_limit() + $Max_Stale_value;}}if( $Min_Fresh_value_set) {$get_limit = min($age_limit, server_freshness_limit() - $Min_Fresh_value_set);}if($Max_Age_value_set) {$age_limit = min($age_limit, $Max_Age_value);}
}
參考 《HTTP權威指南》第7章