小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

設(shè)計(jì)一個(gè)完美的HTTP緩存策略

 德威雅 2019-08-24

1、前言

作為一個(gè)前端,了解http緩存是非常必要,它不僅是面試的必要環(huán)節(jié),也更是實(shí)戰(zhàn)開發(fā)中必不可少需要了解的知識點(diǎn),本文作者將從緩存的概念講到如何在業(yè)務(wù)中設(shè)計(jì)一個(gè)合理的緩存架構(gòu),帶你一步一步解開http緩存的神秘面紗。

2、http緩存定義

當(dāng)客戶端向服務(wù)器請求資源時(shí),會先抵達(dá)瀏覽器緩存,如果瀏覽器有“要請求資源”的副本,就可以直接從瀏覽器緩存中提取而不是從原始服務(wù)器中提取這個(gè)資源。http緩存一般針對GET請求,POST請求一般不會緩存,因?yàn)镻OST請求執(zhí)行的任務(wù)都是對服務(wù)器產(chǎn)生副作用或者非冪等性的任務(wù),既然要改變服務(wù)器資源,自然請求是要進(jìn)入服務(wù)器進(jìn)行處理的。緩存帶來的好處是巨大的,減少了http請求,自然也就減少的服務(wù)端壓力,并且增加了資源的訪問速度,但是胡亂使用緩存,將會帶來資源的不及時(shí)更新,甚至資源更新錯(cuò)位,災(zāi)難也是巨大的。
http緩存分為強(qiáng)緩存和協(xié)商緩存,下面帶大家一一了解兩種緩存機(jī)制。

3、強(qiáng)緩存

3.1、強(qiáng)緩存定義

如果命中緩存,直接從緩存中拿數(shù)據(jù),請求不會經(jīng)過服務(wù)器,返回的http狀態(tài)碼為200(from disk cache)

下面給一張流程圖來說明強(qiáng)緩存的請求過程,為了方便假設(shè)瀏覽器存在一個(gè)緩存數(shù)據(jù)庫(其實(shí)就是disk磁盤,緩存數(shù)據(jù)存放的地方)。

仔細(xì)看上面的流程圖,強(qiáng)緩存的最大特點(diǎn)就是在命中緩存的情況下不會經(jīng)過服務(wù)器,而是直接返回。

3.2、Http頭Expires/Cache-Control設(shè)置強(qiáng)緩存

Cache-Control里面存在多個(gè)屬性來控制緩存,設(shè)置強(qiáng)緩存即設(shè)置資源的有效期,屬性為max-age.
下面使用Express給大家演示一下

app.get('/script1.js', function (req, res, next) { // res.header('Cache-Control', 'must-revalidate, max-age=600') // res.header('Content-Type', 'text/html') res.header('Cache-Control', 'max-age=20') res.sendFile(__dirname + '/script.js')})

Expires和max-age都是用于控制緩存的生命周期。不同的是Expires指定的是過期的具體時(shí)間,例如Sun, 21 Mar 2027 08:52:14 GMT,而max-age指定的是生命時(shí)長秒數(shù)315360000。
區(qū)別在于Expires是 HTTP/1.0 的中的標(biāo)準(zhǔn),而max-age是屬于Cache-Control的內(nèi)容,是 HTTP/1.1 中的定義的。但為了想向前兼容,這兩個(gè)屬性仍然要同時(shí)存在。max-age是要優(yōu)先于Expires的。

4、協(xié)商/對比緩存

4.1、定義

協(xié)商緩存與強(qiáng)制緩存的不同之處在于,協(xié)商緩存每次讀取數(shù)據(jù)時(shí)都需要跟服務(wù)器通信,并且會增加緩存標(biāo)識。在第一次請求服務(wù)器時(shí),服務(wù)器會返回資源,并且返回一個(gè)資源的緩存標(biāo)識,一起存到瀏覽器的緩存數(shù)據(jù)庫。當(dāng)?shù)诙握埱筚Y源時(shí),瀏覽器會首先將緩存標(biāo)識發(fā)送給服務(wù)器,服務(wù)器拿到標(biāo)識后判斷標(biāo)識是否匹配,如果不匹配,表示資源有更新,服務(wù)器會將新數(shù)據(jù)和新的緩存標(biāo)識一起返回到瀏覽器;如果緩存標(biāo)識匹配,表示資源沒有更新,并且返回 304 狀態(tài)碼,瀏覽器就讀取本地緩存服務(wù)器中的數(shù)據(jù)。
協(xié)商緩存的最大特點(diǎn)是要經(jīng)過服務(wù)器驗(yàn)證的,下面我們來講解協(xié)商緩存的驗(yàn)證流程。
第一次訪問:

再次訪問:

還是給一張流程圖來說明。(圖是盜的,協(xié)商緩存也可以成為對比緩存,圖中的對比緩存就是協(xié)商緩存)

4.2、協(xié)商緩存如何驗(yàn)證

第一次請求將response header的Last-Modified和Etag存起來,在第二次請求通過request header的If-Modified-Since和If-None-Match傳到服務(wù)端進(jìn)行驗(yàn)證,如果命中緩存,返回304,不帶返回的數(shù)據(jù),瀏覽器自動從緩存中獲取數(shù)據(jù)資源,若未命中緩存返回200,帶上數(shù)據(jù)資源。

** Last-Modified:**
服務(wù)器在響應(yīng)請求時(shí),告訴瀏覽器資源的最后修改時(shí)間。

** If-Modified-Since:**
再次請求服務(wù)器時(shí),通過此字段通知服務(wù)器上次請求時(shí),服務(wù)器返回的資源最后修改時(shí)間。
服務(wù)器收到請求后發(fā)現(xiàn)有頭If-Modified-Since 則與被請求資源的最后修改時(shí)間進(jìn)行比對。
若資源的最后修改時(shí)間大于If-Modified-Since,說明資源又被改動過,則響應(yīng)整片資源內(nèi)容,返回狀態(tài)碼200;
若資源的最后修改時(shí)間小于或等于If-Modified-Since,說明資源無新修改,則響應(yīng)HTTP 304,告知瀏覽器繼續(xù)使用所保存的cache。

** Etag / If-None-Match(優(yōu)先級高于Last-Modified / If-Modified-Since) **
** Etag:**
服務(wù)器響應(yīng)請求時(shí),告訴瀏覽器當(dāng)前資源在服務(wù)器的唯一標(biāo)識(生成規(guī)則由服務(wù)器決定)。

** If-None-Match:**
再次請求服務(wù)器時(shí),通過此字段通知服務(wù)器客戶段緩存數(shù)據(jù)的唯一標(biāo)識。
服務(wù)器收到請求后發(fā)現(xiàn)有頭If-None-Match 則與被請求資源的唯一標(biāo)識進(jìn)行比對,
不同,說明資源又被改動過,則響應(yīng)整片資源內(nèi)容,返回狀態(tài)碼200;
相同,說明資源無新修改,則響應(yīng)HTTP 304,告知瀏覽器繼續(xù)使用所保存的cache。

4.3、Http頭如何設(shè)置協(xié)商緩存

在強(qiáng)緩存那一節(jié)說到使用Cache-Control的max-age來設(shè)置資源過期時(shí)間,那么當(dāng)max-age=0的時(shí)候呢,自然瀏覽器第一時(shí)間發(fā)現(xiàn)資源過期,request header就會帶著If-Modified-Since和If-None-Match去服務(wù)端驗(yàn)證。
所以設(shè)置response header為:

Cache-Control: max-age=0

就可以觸發(fā)協(xié)商緩存了,其實(shí)Cache-Control中還有兩個(gè)屬性都可以設(shè)置協(xié)商緩存 must-revalidate和no-cache
must-revalidate的意義為必須進(jìn)行驗(yàn)證,但是它一般是和max-age一起使用的,不會單獨(dú)使用,

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

該頭信息意義就是在資源有效期過后必須進(jìn)行驗(yàn)證, 與只設(shè)置max-age=600的區(qū)別是,前面一個(gè)是MUST,而后面一個(gè)是SHOULD,理論上來說它們的效果是一致的。
no-cache的意義千萬不能理解為不緩存,下面兩段代碼的意義是一樣的,即請求必須進(jìn)行驗(yàn)證,才可以使用緩存資源,注意是MUST

Cache-Control: no-cacheCache-Control: must-revalidate, max-age=0

如果要不緩存,每次都請求新的資源應(yīng)該使用

Cache-Control: no-store

5、關(guān)于緩存的Http頭總結(jié)

5.1、'no-cache', 'no-store', 'must-revalidate'

Cache-Control字段可以設(shè)置的不僅僅是max-age存儲時(shí)間,還有其他額外的值可以填寫,甚至可以組合。主要使用的值有如下:
no-cache: 雖然字面意義是“不要緩存”。但它實(shí)際上的機(jī)制是,仍然對資源使用緩存,但每一次在使用緩存之前必須(MUST)向服務(wù)器對緩存資源進(jìn)行驗(yàn)證。
no-store: 不使用任何緩存
must-revalidate: 如果你配置了max-age信息,當(dāng)緩存資源仍然新鮮(小于max-age)時(shí)使用緩存,否則需要對資源進(jìn)行驗(yàn)證。所以must-revalidate可以和max-age組合使用Cache-Control: must-revalidate, max-age=60
有趣的事情是,雖然no-cache意為對緩存進(jìn)行驗(yàn)證,但是因?yàn)榇蠹覐V泛的錯(cuò)誤的把它當(dāng)作no-store來使用,所以有的瀏覽器也就附和了這種設(shè)計(jì)。這是一個(gè)典型的劣幣驅(qū)逐良幣。

5.2、Expires VS. max-age

Expires和max-age都是用于控制緩存的生命周期。不同的是Expires指定的是過期的具體時(shí)間,例如Sun, 21 Mar 2027 08:52:14 GMT,而max-age指定的是生命時(shí)長秒數(shù)315360000。
區(qū)別在于Expires是 HTTP/1.0 的中的標(biāo)準(zhǔn),而max-age是屬于Cache-Control的內(nèi)容,是 HTTP/1.1 中的定義的。但為了想向前兼容,這兩個(gè)屬性仍然要同時(shí)存在。
但有一種更傾向于使用max-age的觀點(diǎn)認(rèn)為Expires過于復(fù)雜了。例如上面的例子Sun, 21 Mar 2027 08:52:14 GMT,如果你在表示小時(shí)的數(shù)字缺少了一個(gè)0,則很有可能出現(xiàn)出錯(cuò);如果日期沒有轉(zhuǎn)換到用戶的正確時(shí)區(qū),則有可能出錯(cuò)。這里出錯(cuò)的意思可能包括但不限于緩存失效、緩存生命周期出錯(cuò)等。

5.3、Etag VS. Last-Modified

Etag和Last-Modified都可以用于對資源進(jìn)行驗(yàn)證,而Last-Modified顧名思義,表示資源最后的更新時(shí)間。
我們把這兩者都成為驗(yàn)證器(Validators),不同的是,Etag屬于強(qiáng)驗(yàn)證(Strong Validation),因?yàn)樗谕氖琴Y源字節(jié)級別的一致;而Last-Modified屬于弱驗(yàn)證(Weak Validation),只要資源的主要內(nèi)容一致即可,允許例如頁底的廣告,頁腳不同。
根據(jù)RFC 2616標(biāo)準(zhǔn)中的13.3.4小節(jié),一個(gè)使用HTTP 1.1標(biāo)準(zhǔn)的服務(wù)端應(yīng)該(SHOULD)同時(shí)發(fā)送Etag和Last-Modified字段。同時(shí)一個(gè)支持HTTP 1.1的客戶端,比如瀏覽器,如果服務(wù)端有提供Etag的話,必須(MUST)首先對Etag進(jìn)行Conditional Request(If-None-Match頭信息);如果兩者都有提供,那么應(yīng)該(SHOULD)同時(shí)對兩者進(jìn)行Conditional Request(If-Modified-Since頭信息)。如果服務(wù)端對兩者的驗(yàn)證結(jié)果不一致,例如通過一個(gè)條件判斷資源發(fā)生了更改,而另一個(gè)判定資源沒有發(fā)生更改,則不允許返回304狀態(tài)。但話說回來,是否返回還是通過服務(wù)端編寫的實(shí)際代碼決定的。所以仍然有操縱的空間。

5.4、max-age=0 VS. no-cache

max-age=0是在告訴瀏覽器,資源已經(jīng)過期了,你應(yīng)該(SHOULD)對資源進(jìn)行重新驗(yàn)證了;而no-cache則是告訴瀏覽器在每一次使用緩存之前,你必須(MUST)對資源進(jìn)行重新驗(yàn)證。
區(qū)別在于,SHOULD是非強(qiáng)制性的,而MUST是強(qiáng)制性的。在no-cache的情況下,瀏覽器在向服務(wù)器驗(yàn)證成功之前絕不會使用過期的緩存資源,而max-age=0則不一定了。雖然理論上來說它們的效果應(yīng)該是一致的。

5.5、public VS. private

要知道從服務(wù)器到瀏覽器之間并非只有瀏覽器能夠?qū)Y源進(jìn)行緩存,服務(wù)器的返回可能會經(jīng)過一些中間(intermediate)服務(wù)器甚至甚至專業(yè)的中間緩存服務(wù)器,還有CDN。而有些請求返回是用戶級別、是私人的,所以你可能不希望這些中間服務(wù)器緩存返回。此時(shí)你需要將Cache-Control設(shè)置為private以避免暴露。

6、緩存實(shí)戰(zhàn)

前面寫了很多緩存的基礎(chǔ)知識,那么如何設(shè)計(jì)一個(gè)可靠的緩存規(guī)則,這個(gè)其實(shí)得根據(jù)你的實(shí)際需求而定。
比如某個(gè)資源永遠(yuǎn)不會改變,比如某些第三方庫(一般都放CDN做優(yōu)化了),或者某些圖片,比如百度的圖片,就讓它們永久緩存著吧,設(shè)置一個(gè)最大的max-age

Cache-Control: max-age=31536000

其他的資源可根據(jù)下面這張決策樹來進(jìn)行設(shè)置

7、memory cache

“內(nèi)存緩存”中主要包含的是當(dāng)前文檔中頁面中已經(jīng)抓取到的資源。例如頁面上已經(jīng)下載的樣式、腳本、圖片等。我們不排除頁面可能會對這些資源再次發(fā)出請求,所以這些資源都暫存在內(nèi)存中,當(dāng)用戶結(jié)束瀏覽網(wǎng)頁并且關(guān)閉網(wǎng)頁時(shí),內(nèi)存緩存的資源會被釋放掉。
這其中最重要的緩存資源其實(shí)是preloader相關(guān)指令(例如)下載的資源??偹苤猵reloader的相關(guān)指令已經(jīng)是頁面優(yōu)化的常見手段之一,而通過這些指令下載的資源也都會暫存到內(nèi)存中。根據(jù)一些材料,如果資源已經(jīng)存在于緩存中,則可能不會再進(jìn)行preload。
需要注意的事情是,內(nèi)存緩存在緩存資源時(shí)并不關(guān)心返回資源的HTTP緩存頭Cache-Control是什么值,同時(shí)資源的匹配也并非僅僅是對URL做匹配,還可能會對Content-Type,CORS等其他特征做校驗(yàn)
這個(gè)應(yīng)該是瀏覽器做的一種優(yōu)化,緩存也只是暫時(shí)的。

8、瀏覽器可能會限制Cache-Control頭無效

Linux公社的RSS地址https://www./rssFeed.aspx

本文永久更新鏈接地址https://www./Linux/2019-08/160265.htm

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多