本文內(nèi)容大多參考《圖解HTTP》一書
一. 認(rèn)識(shí)代理服務(wù)器
所以講緩存為什么要先扯代理服務(wù)器图仓?別急痢甘,讓我們看一下一個(gè)請(qǐng)求的簡(jiǎn)單示意圖。
我們看到客戶端(用戶)發(fā)送了一個(gè)請(qǐng)求并不是直接發(fā)給源服務(wù)器的而是經(jīng)過了代理服務(wù)器,然后經(jīng)由代理服務(wù)器再發(fā)送給源服務(wù)器,響應(yīng)也同樣遵循這個(gè)順序谭梗。
那么代理服務(wù)器在這中間擔(dān)任了什么角色?
1.1 代理服務(wù)器的分類
- 緩存代理
代理轉(zhuǎn)發(fā)響應(yīng)時(shí)宛蚓,緩存代理(Caching Proxy)會(huì)預(yù)先將資源的副本(緩存)保存在代理服務(wù)器上激捏。當(dāng)代理再次接收到對(duì)相同資源的請(qǐng)求時(shí),就可以不從源服務(wù)器那里
獲取資源凄吏,而是將之前緩存的資源作為響應(yīng)返回远舅。 - 透明代理(本文不做細(xì)致討論)
轉(zhuǎn)發(fā)請(qǐng)求或響應(yīng)時(shí),不對(duì)報(bào)文做任何加工的代理類型被稱為透明代理(Transparent Proxy)痕钢。反之图柏,對(duì)報(bào)文內(nèi)容進(jìn)行加工的代理被稱為非透明代理。
二. 保存資源的緩存
緩存是指代理服務(wù)器或客戶端本地磁盤內(nèi)保存的資源副本难咕。利用緩存可減少對(duì)源服務(wù)器的訪問课梳,因此也就節(jié)省了通信流量和通信時(shí)間距辆。
緩存服務(wù)器是代理服務(wù)器的一種,并歸類在緩存代理類型中暮刃。換句話說跨算,當(dāng)代理轉(zhuǎn)發(fā)從服務(wù)器返回的響應(yīng)時(shí),代理服務(wù)器將會(huì)保存一份資源的副本椭懊。
緩存服務(wù)器的優(yōu)勢(shì)在于利用緩存可避免多次從源服務(wù)器轉(zhuǎn)發(fā)資源诸蚕。因此客戶端可就近從緩存服務(wù)器上獲取資源,而源服務(wù)器也不必多次處理相同的請(qǐng)求了氧猬。
1.1 緩存的有效期限
即便緩存服務(wù)器和客戶端內(nèi)有緩存背犯,也不能每次都給我返回緩存吧,如果是這樣盅抚,源服務(wù)器更新了我也不知道漠魏,因?yàn)槲颐看味际强淳彺娴馁Y源。
為了解決這個(gè)問題妄均,針對(duì)緩存設(shè)計(jì)了時(shí)效性的概念:
即使存在緩存柱锹,也會(huì)因?yàn)榭蛻舳说囊蟆⒕彺娴挠行诘纫蛩胤岚蛟捶?wù)器確認(rèn)資源的有效性禁熏。若判斷緩存失效,緩存服務(wù)器將會(huì)再次從源服務(wù)器上獲取“新”資源邑彪。
1.2 客戶端的緩存
緩存不僅可以存在于緩存服務(wù)器內(nèi)瞧毙,還可以存在客戶端瀏覽器中。以Internet Explorer 程序?yàn)槔啃睿芽蛻舳司彺娣Q為臨時(shí)網(wǎng)絡(luò)文件(Temporary Internet File)升筏。
瀏覽器緩存如果有效,就不必再向服務(wù)器請(qǐng)求相同的資源了瘸爽,可以直接從本地磁盤內(nèi)讀取您访。
另外,和緩存服務(wù)器相同的一點(diǎn)是剪决,當(dāng)判定緩存過期后灵汪,會(huì)向源服務(wù)器確認(rèn)資源的有效性。若判斷瀏覽器緩存失效柑潦,瀏覽器會(huì)再次請(qǐng)求新資源享言。
三. 與控制緩存相關(guān)的HTTP首部字段
1. http1.0 時(shí)代的緩存方式
Pragma
Pragma 是HTTP/1.1 之前版本的歷史遺留字段,僅作為與HTTP/1.0的向后兼容而定義渗鬼。
規(guī)范定義的形式唯一览露,如下所示。
Pragma: no-cache
該首部字段屬于通用首部字段譬胎,但只用在客戶端發(fā)送的請(qǐng)求中差牛∶客戶端會(huì)要求所有的中間服務(wù)器不返回緩存的資源。
所有的中間服務(wù)器如果都能以HTTP/1.1 為基準(zhǔn)偏化, 那直接采用Cache-Control: no-cache 指定緩存的處理方式是最為理想的脐恩。但要整體掌握全部中間服務(wù)器使用的HTTP 協(xié)議版本卻是不現(xiàn)實(shí)的。因此侦讨,發(fā)送的請(qǐng)求會(huì)同時(shí)含有下面兩個(gè)首部字段驶冒。
Cache-Control: no-cache
Pragma: no-cache
Expires
Expires: Wed, 04 Jul 2012 08:26:05 GMT
首部字段Expires 會(huì)將資源失效的日期告知客戶端。緩存服務(wù)器在接收到含有首部字段Expires 的響應(yīng)后韵卤,會(huì)以緩存來應(yīng)答請(qǐng)求骗污,在Expires 字段值指定的時(shí)間之前,響應(yīng)的副本會(huì)一直被保存怜俐。當(dāng)超過指定的時(shí)間后身堡,緩存服務(wù)器在請(qǐng)求發(fā)送過來時(shí),會(huì)轉(zhuǎn)向源服務(wù)器請(qǐng)求資源拍鲤。
源服務(wù)器不希望緩存服務(wù)器對(duì)資源緩存時(shí)贴谎,最好在Expires 字段內(nèi)寫入與首部字段Date 相同的時(shí)間值。
但是季稳,當(dāng)首部字段Cache-Control 有指定max-age 指令時(shí)擅这,比起首部字段Expires,會(huì)優(yōu)先處理max-age 指令景鼠。
2. Cache-Control
通過指定首部字段Cache-Control 的指令仲翎,就能操作緩存的工作機(jī)制。
指令的參數(shù)是可選的铛漓,多個(gè)指令之間通過“,”分隔溯香。首部字段Cache-Control 的指令在請(qǐng)求和響應(yīng)下都適用。
Cache-Control: private, max-age=0, no-cache
2.1 Cache-Control指令一覽:
可用的指令按請(qǐng)求和響應(yīng)分類如下所示:
緩存請(qǐng)求指令
指令 | 參數(shù) | 說明 |
---|---|---|
no-cache | 無 | 強(qiáng)制向源服務(wù)器再次驗(yàn)證 |
no-store | 無 | 不緩存請(qǐng)求或響應(yīng)的任何內(nèi)容 |
max-age = [ 秒] | 必須有 | 響應(yīng)的最大Age值 |
max-stale( = [ 秒]) | 可省略 | 接收已過期的響應(yīng) |
min-fresh = [ 秒] | 必須有 | 期望在指定時(shí)間內(nèi)的響應(yīng)仍有效 |
no-transform | 無 | 代理不可更改媒體類型 |
only-if-cached | 無 | 從緩存獲取資源 |
cache-extension | - | 新指令標(biāo)記(token) |
緩存響應(yīng)指令
指令 | 參數(shù) | 說明 |
---|---|---|
public | 無 | 可向任意方提供響應(yīng)的緩存 |
private | 可省略 | 僅向特定用戶返回響應(yīng) |
no-cache | 可省略 | 緩存前必須先確認(rèn)其有效性 |
no-store | 無 | 不緩存請(qǐng)求或響應(yīng)的任何內(nèi)容 |
no-transform | 無 | 代理不可更改媒體類型 |
must-revalidate | 無 | 可緩存但必須再向源服務(wù)器進(jìn)行確認(rèn) |
proxy-revalidate | 無 | 要求緩存服務(wù)器對(duì)緩存的響應(yīng)有效性再進(jìn)行確認(rèn) |
max-age = [ 秒] | 必須有 | 響應(yīng)的最大Age值 |
s-maxage = [ 秒] | 必須有 | 公共緩存服務(wù)器響應(yīng)的最大Age值 |
cache-extension | - | 新指令標(biāo)記(token) |
2.2 Cache-Control指令詳細(xì)介紹
2.2.1. 表示是否能緩存的指令
public指令
Cache-Control: public
當(dāng)指定使用public 指令時(shí)浓恶,則明確表明其他用戶也可利用緩存玫坛。
private指令
Cache-Control: private
當(dāng)指定private 指令后,響應(yīng)只以特定的用戶作為對(duì)象包晰,這與public
指令的行為相反湿镀。
緩存服務(wù)器會(huì)對(duì)該特定用戶提供資源緩存的服務(wù),對(duì)于其他用戶發(fā)
送過來的請(qǐng)求伐憾,代理服務(wù)器則不會(huì)返回緩存勉痴。
no-cache指令
Cache-Control: no-cache
使用no-cache 指令的目的是為了防止從緩存中返回過期的資源∈魉啵客戶端發(fā)送的請(qǐng)求中如果包含no-cache 指令蒸矛,則表示客戶端將不會(huì)接收緩存過的響應(yīng)。于是,“中間”的緩存服務(wù)器必須把客戶端請(qǐng)求轉(zhuǎn)發(fā)給源服務(wù)器雏掠。
如果服務(wù)器返回的響應(yīng)中包含no-cache 指令廓脆,那么緩存服務(wù)器不能對(duì)資源進(jìn)行緩存。源服務(wù)器以后也將不再對(duì)緩存服務(wù)器請(qǐng)求中提出的資源有效性進(jìn)行確認(rèn)磁玉,且禁止其對(duì)響應(yīng)資源進(jìn)行緩存操作。
Cache-Control: no-cache=Location
由服務(wù)器返回的響應(yīng)中驾讲,若報(bào)文首部字段Cache-Control 中對(duì)no-cache字段名具體指定參數(shù)值蚊伞,那么客戶端在接收到這個(gè)被指定參數(shù)值的首部字段對(duì)應(yīng)的響應(yīng)報(bào)文后,就不能使用緩存吮铭。換言之时迫,無參數(shù)值的首部字段可以使用緩存。只能在響應(yīng)指令中指定該參數(shù)谓晌。
2.2.2. 控制可執(zhí)行緩存的對(duì)象的指令
no-store指令
Cache-Control: no-store
當(dāng)使用no-store 指令時(shí)掠拳,暗示請(qǐng)求(和對(duì)應(yīng)的響應(yīng))或響應(yīng)中包含機(jī)密信息。
因此纸肉,該指令規(guī)定緩存不能在本地存儲(chǔ)請(qǐng)求或響應(yīng)的任一部分溺欧。
ps:從字面意思上很容易把no-cache誤解成為不緩存,但事實(shí)上no-cache代表不緩存過期的資源柏肪,緩存會(huì)向源服務(wù)器進(jìn)行有效期確認(rèn)后處理資源姐刁,也許稱為do-not-serve-from-cache-without-revalidation更合適。no-store 才是真正地不進(jìn)行緩存烦味,請(qǐng)讀者注意區(qū)別理解聂使。
2.2.3. 指定緩存期限和認(rèn)證的指令
s-maxage指令
Cache-Control: s-maxage=604800 //(單位:秒)
s-maxage 指令的功能和max-age 指令的功能相同, 它們的不同點(diǎn)是s-maxage 指令只適用于供多位用戶使用的公共緩存服務(wù)器(這里指代理服務(wù)器)谬俄。也就是說柏靶,對(duì)于向同一用戶重復(fù)返回響應(yīng)的服務(wù)器來說,這個(gè)指令沒有任何作用溃论。
另外屎蜓,當(dāng)使用s-maxage 指令后,則直接忽略對(duì)Expires 首部字段及max-age 指令的處理蔬芥。
max-age指令
Cache-Control: max-age=604800 //(單位:秒)
當(dāng)客戶端發(fā)送的請(qǐng)求中包含max-age 指令時(shí)梆靖,如果判定緩存資源的緩存時(shí)間數(shù)值比指定時(shí)間的數(shù)值更小,那么客戶端就接收緩存的資源笔诵。
另外返吻,當(dāng)指定max-age 值為0,那么緩存服務(wù)器通常需要將請(qǐng)求轉(zhuǎn)發(fā)給源服務(wù)器乎婿。
當(dāng)服務(wù)器返回的響應(yīng)中包含max-age 指令時(shí)测僵,緩存服務(wù)器將不對(duì)資源的有效性再作確認(rèn),而max-age 數(shù)值代表資源保存為緩存的最長(zhǎng)時(shí)間。
應(yīng)用HTTP/1.1 版本的緩存服務(wù)器遇到同時(shí)存在Expires 首部字段的情況時(shí)捍靠,會(huì)優(yōu)先處理max-age 指令沐旨,而忽略掉Expires 首部字段。而HTTP/1.0 版本的緩存服務(wù)器的情況卻相反榨婆,max-age 指令會(huì)被忽略掉磁携。
min-fresh指令
Cache-Control: min-fresh=60 //(單位:秒)
min-fresh 指令要求緩存服務(wù)器返回至少還未過指定時(shí)間的緩存資源。
比如良风,當(dāng)指定min-fresh 為60 秒后谊迄,過了60 秒的資源都無法作為響應(yīng)返回了。
max-stale指令
Cache-Control: max-stale=3600 //(單位:秒)
使用max-stale 可指示緩存資源烟央,即使過期也照常接收统诺。
如果指令未指定參數(shù)值,那么無論經(jīng)過多久疑俭,客戶端都會(huì)接收響應(yīng)粮呢;如果指令中指定了具體數(shù)值,那么即使過期钞艇,只要仍處于max-stale 指定的時(shí)間內(nèi)啄寡,仍舊會(huì)被客戶端接收。
only-if-cached指令
Cache-Control: only-if-cached
使用only-if-cached 指令表示客戶端僅在緩存服務(wù)器本地緩存目標(biāo)資源的情況下才會(huì)要求其返回哩照。換言之这难,該指令要求緩存服務(wù)器不重新加載響應(yīng),也不會(huì)再次確認(rèn)資源有效性葡秒。若發(fā)生請(qǐng)求緩存服務(wù)器的本地緩存無響應(yīng)姻乓,則返回狀態(tài)碼504 Gateway Timeout。
must-revalidate指令
Cache-Control: must-revalidate
使用must-revalidate 指令眯牧,代理會(huì)向源服務(wù)器再次驗(yàn)證即將返回的響應(yīng)緩存目前是否仍然有效蹋岩。
若代理無法連通源服務(wù)器再次獲取有效資源的話,緩存必須給客戶端一條504(Gateway Timeout)狀態(tài)碼学少。
另外剪个,使用must-revalidate 指令會(huì)忽略請(qǐng)求的max-stale 指令(即使已經(jīng)在首部使用了max-stale,也不會(huì)再有效果)版确。
proxy-revalidate指令
Cache-Control: proxy-revalidate
proxy-revalidate 指令要求所有的緩存服務(wù)器在接收到客戶端帶有該指令的請(qǐng)求返回響應(yīng)之前扣囊,必須再次驗(yàn)證緩存的有效性。
no-transform指令
Cache-Control: no-transform
使用no-transform 指令規(guī)定無論是在請(qǐng)求還是響應(yīng)中绒疗,緩存都不能改變實(shí)體主體的媒體類型侵歇。這樣做可防止緩存或代理壓縮圖片等類似操作。
2.2.4. Cache-Control 擴(kuò)展
cache-extension token
Cache-Control: private, community="UCI"
通過 cache-extension 標(biāo)記(token)吓蘑,可以擴(kuò)展Cache-Control 首部字段內(nèi)的指令惕虑。
如上例坟冲,Cache-Control 首部字段本身沒有community 這個(gè)指令。借助extension tokens 實(shí)現(xiàn)了該指令的添加溃蔫。如果緩存服務(wù)器不能理community 這個(gè)新指令健提,就會(huì)直接忽略。因此伟叛,extension tokens 僅對(duì)能理解它的緩存服務(wù)器來說是有意義的私痹。
3. Last-Modified
Last-Modified: Wed, 23 May 2012 09:59:55 GMT
服務(wù)器將資源傳遞給客戶端時(shí),會(huì)將資源最后更改的時(shí)間以“Last-Modified: GMT”的形式加在實(shí)體首部上一起返回給客戶端统刮。
當(dāng)客戶端對(duì)同樣的資源發(fā)起同樣的請(qǐng)求時(shí)侄榴,會(huì)把該信息附帶在請(qǐng)求報(bào)文中一并帶給服務(wù)器去做檢查。
3.1 If-Modified-Since
If-Modified-Since: Thu, 15 Apr 2004 00:00:00 GMT
首部字段If-Modified-Since蕊爵,屬附帶條件之一辉哥,它會(huì)告知服務(wù)器若If-Modified-Since 字段值早于資源的更新時(shí)間,則希望能處理該請(qǐng)求攒射。而在指定If-Modified-Since 字段值的日期時(shí)間之后醋旦,如果請(qǐng)求的資源都沒有過更新,則返回狀態(tài)碼304 Not Modified 的響應(yīng)会放。
If-Modified-Since 用于確認(rèn)代理或客戶端擁有的本地資源的有效性饲齐。獲取資源的更新日期時(shí)間,可通過確認(rèn)首部字段Last-Modified 來確定咧最。
3.2 If-Unmodified-Since
If-Unmodified-Since: Thu, 03 Jul 2012 00:00:00 GMT
首部字段If-Unmodified-Since 和首部字段If-Modified-Since 的作用相反捂人。它的作用的是告知服務(wù)器,指定的請(qǐng)求資源只有在字段值內(nèi)指定的日期時(shí)間之后矢沿,未發(fā)生更新的情況下滥搭,才能處理請(qǐng)求。如果在指定日期時(shí)間后發(fā)生了更新捣鲸,則以狀態(tài)碼412 Precondition Failed 作為響應(yīng)返回瑟匆。
ps:Last-Modified 存在一定問題,如果在服務(wù)器上栽惶,一個(gè)資源被修改了愁溜,但其實(shí)際內(nèi)容根本沒發(fā)生改變,會(huì)因?yàn)長(zhǎng)ast-Modified時(shí)間匹配不上而返回了整個(gè)實(shí)體給客戶端(即使客戶端緩存里有個(gè)一模一樣的資源)外厂。
4. ETag
ETag: "82e22293907ce725faf67773957acd12"
首部字段ETag 能告知客戶端實(shí)體標(biāo)識(shí)冕象。它是一種可將資源以字符串形式做唯一性標(biāo)識(shí)的方式。服務(wù)器會(huì)為每份資源分配對(duì)應(yīng)的ETag 值汁蝶。
另外交惯,當(dāng)資源更新時(shí),ETag 值也需要更新。生成ETag 值時(shí)席爽,并沒有統(tǒng)一的算法規(guī)則意荤,而僅僅是由服務(wù)器來分配。
資源被緩存時(shí)只锻,就會(huì)被分配唯一性標(biāo)識(shí)玖像。
例如,當(dāng)使用中文版的瀏覽器訪問 http : //www.google.com/ 時(shí)齐饮,就會(huì)返回中文版對(duì)應(yīng)的資源捐寥,而使用英文版的瀏覽器訪問時(shí),則會(huì)返回英文版對(duì)應(yīng)的資源祖驱。
兩者的URI是相同的握恳,所以僅憑URI 指定緩存的資源是相當(dāng)困難的。若在下載過程中出現(xiàn)連接中斷捺僻、再連接的情況乡洼,都會(huì)依照ETag 值來指定資源。
4.1 強(qiáng)ETag 值和弱Tag 值
強(qiáng)ETag 值
強(qiáng)ETag 值匕坯,不論實(shí)體發(fā)生多么細(xì)微的變化都會(huì)改變其值束昵。
ETag: "usagi-1234"
弱ETag 值
弱ETag 值只用于提示資源是否相同。只有資源發(fā)生了根本改變葛峻,產(chǎn)
生差異時(shí)才會(huì)改變ETag 值锹雏。這時(shí),會(huì)在字段值最開始處附加W/术奖。
ETag: W/"usagi-1234"
4.2 If-Match
形如If-xxx 這種樣式的請(qǐng)求首部字段礁遵,都可稱為條件請(qǐng)求。服務(wù)器接收到附帶條件的請(qǐng)求后采记,只有判斷指定條件為真時(shí)榛丢,才會(huì)執(zhí)行請(qǐng)求。
If-Match: "123456"
首部字段If-Match晰赞,屬附帶條件之一,它會(huì)告知服務(wù)器匹配資源所用的實(shí)體標(biāo)記(ETag)值选侨。這時(shí)的服務(wù)器無法使用弱ETag 值掖鱼。
服務(wù)器會(huì)比對(duì)If-Match 的字段值和資源的ETag 值,僅當(dāng)兩者一致時(shí)援制,才會(huì)執(zhí)行請(qǐng)求戏挡。反之,則返回狀態(tài)碼412 Precondition Failed 的響應(yīng)晨仑。
還可以使用星號(hào)(*)指定If-Match 的字段值褐墅。針對(duì)這種情況拆檬,服務(wù)器將會(huì)忽略ETag 的值,只要資源存在就處理請(qǐng)求妥凳。
4.3 If-None-Match
首部字段If-None-Match 屬于附帶條件之一逝钥。它和首部字段If-Match 作用相反屑那。用于指定If-None-Match 字段值的實(shí)體標(biāo)記(ETag)值與請(qǐng)求資源的ETag 不一致時(shí),它就告知服務(wù)器處理該請(qǐng)求艘款。
在GET 或HEAD 方法中使用首部字段If-None-Match 可獲取最新的資源持际。因此,這與使用首部字段If-Modified-Since 時(shí)有些類似哗咆。
5. 用戶刷新/訪問行為
5.1 在URI輸入欄中輸入然后回車
不與服務(wù)器確認(rèn)蜘欲,而是直接使用瀏覽器緩存的內(nèi)容。其中響應(yīng)內(nèi)容和之前的響應(yīng)內(nèi)容一模一樣晌柬,例如其中的Date時(shí)間是上一次響應(yīng)的時(shí)間姥份。
5.2 F5/點(diǎn)擊工具欄中的刷新按鈕/右鍵菜單重新加載
F5的作用和直接在URI輸入欄中輸入然后回車是不一樣的,F(xiàn)5會(huì)讓瀏覽器無論如何都發(fā)一個(gè)HTTP Request給Server空繁,即使先前的響應(yīng)中有Expires頭部。
5.3 Ctl+F5
Ctrl+F5要的是徹底的從Server拿一份新的資源過來朱庆,所以不光要發(fā)送HTTP request給Server盛泡,而且這個(gè)請(qǐng)求里面連If-Modified-Since/If-None-Match都沒有,這樣就逼著Server不能返回304娱颊,而是把整個(gè)資源原原本本地返回一份傲诵,這樣,Ctrl+F5引發(fā)的傳輸時(shí)間變長(zhǎng)了箱硕,自然網(wǎng)頁Refresh的也慢一些拴竹。
6. 緩存實(shí)踐
6.1 Expires / Cache-Control
Cache-Control 是 HTTP1.1 才有的,不適用于 HTTP1.0剧罩,而 Expires 既適用于 HTTP1.0栓拜,也適用于 HTTP1.1,所以說在大多數(shù)情況下同時(shí)發(fā)送這兩個(gè)頭會(huì)是一個(gè)更好的選擇惠昔,當(dāng)客戶端兩種頭都能解析的時(shí)候幕与,會(huì)優(yōu)先使用 Cache-Control。
6.2 Last-Modified / ETag
二者都是通過某個(gè)標(biāo)識(shí)值來請(qǐng)求資源镇防, 如果服務(wù)器端的資源沒有變化啦鸣,則自動(dòng)返回 HTTP 304 (Not Changed)狀態(tài)碼,內(nèi)容為空来氧,這樣就節(jié)省了傳輸數(shù)據(jù)量诫给。當(dāng)資源變化后則返回新資源香拉。從而保證不向客戶端重復(fù)發(fā)出資源,也保證當(dāng)服務(wù)器有變化時(shí)中狂,客戶端能夠得到最新的資源凫碌。
其中Last-Modified使用文件最后修改作為文件標(biāo)識(shí)值,它無法處理文件一秒內(nèi)多次修改的情況吃型,而且只要文件修改了哪怕文件實(shí)質(zhì)內(nèi)容沒有修改证鸥,也會(huì)重新返回資源內(nèi)容;ETag作為“被請(qǐng)求變量的實(shí)體值”勤晚,其完全可以解決Last-Modified頭部的問題枉层,但是其計(jì)算過程需要耗費(fèi)服務(wù)器資源。
6.3 from-cache / 304
Expires和Cache-Control都有一個(gè)問題就是服務(wù)端的修改赐写,如果還在緩存時(shí)效里鸟蜡,那么客戶端是不會(huì)去請(qǐng)求服務(wù)端資源的(非刷新),這就存在一個(gè)資源版本不符的問題挺邀,而強(qiáng)制刷新一定會(huì)發(fā)起HTTP請(qǐng)求并返回資源內(nèi)容揉忘,無論該內(nèi)容在這段時(shí)間內(nèi)是否修改過;而Last-Modified和Etag每次請(qǐng)求資源都會(huì)發(fā)起請(qǐng)求端铛,哪怕是很久都不會(huì)有修改的資源泣矛,都至少有一次請(qǐng)求響應(yīng)的消耗。
對(duì)于所有可緩存資源禾蚕,指定一個(gè)Expires或Cache-Control max-age以及一個(gè)Last-Modified或ETag至關(guān)重要您朽。同時(shí)使用前者和后者可以很好的相互適應(yīng)。
前者不需要每次都發(fā)起一次請(qǐng)求來校驗(yàn)資源時(shí)效性换淆,后者保證當(dāng)資源未出現(xiàn)修改的時(shí)候不需要重新發(fā)送該資源哗总。而在用戶的不同刷新頁面行為中,二者的結(jié)合也能很好的利用HTTP緩存控制特性倍试,無論是在地址欄輸入U(xiǎn)RI然后輸入回車進(jìn)行訪問讯屈,還是點(diǎn)擊刷新按鈕,瀏覽器都能充分利用緩存內(nèi)容县习,避免進(jìn)行不必要的請(qǐng)求與數(shù)據(jù)傳輸涮母。
6.4 避免304
做法很簡(jiǎn)單,就是把可能會(huì)更新的資源以版本形式發(fā)布躁愿,常用的方法是在文件名或參數(shù)帶上一串md5或時(shí)間標(biāo)記符:
https://#/hm.js?e23800c454aa573c0ccb16b52665ac26
http://tb1.bdstatic.com/tb/_/tbean_safe_ajax_94e7ca2.js
http://img1.gtimg.com/ninja/2/2016/04/ninja145972803357449.jpg
可以看到上面的例子中有不同的做法哈蝇,有的在URI后面加上了md5參數(shù),有的將md5值作為文件名的一部分攘已,有的將資源放在特性版本的目錄中炮赦。
那么在文件沒有變動(dòng)的時(shí)候,瀏覽器不用發(fā)起請(qǐng)求直接可以使用緩存文件样勃;而在文件有變化的時(shí)候吠勘,由于文件版本號(hào)的變更性芬,導(dǎo)致文件名變化,請(qǐng)求的url變了剧防,自然文件就更新了植锉。這樣能確保客戶端能及時(shí)從服務(wù)器收取到新修改的文件峭拘。通過這樣的處理俊庇,增長(zhǎng)了靜態(tài)資源,特別是圖片資源的緩存時(shí)間鸡挠,避免該資源很快過期辉饱,客戶端頻繁向服務(wù)端發(fā)起資源請(qǐng)求,服務(wù)器再返回304響應(yīng)的情況(有Last-Modified/Etag)拣展。