<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          [面經(jīng)]淺析 HTTP 緩存

          共 4319字,需瀏覽 9分鐘

           ·

          2021-03-30 16:40


          1. 為什么需要緩存

          • 通過緩存機(jī)制,可以在相應(yīng)場景下復(fù)用以前獲取的資源。
          • 顯著提高網(wǎng)站的性能和響應(yīng)速度
          • 減少網(wǎng)絡(luò)流量和等待渲染時間
          • 降低服務(wù)器壓力

          2. HTTP 緩存類型

          • 強(qiáng)緩存
          • 協(xié)商緩存

          3. 強(qiáng)緩存

          對于強(qiáng)緩存,服務(wù)器返回的靜態(tài)資源響應(yīng)頭會設(shè)置一個強(qiáng)制緩存的時間,在緩存時間內(nèi),如刷新瀏覽器請求相同資源,在緩存時間未過期的情況下,則直接使用已緩存資源。如緩存資源已過期,執(zhí)行協(xié)商緩存策略。

          • 以下為與強(qiáng)緩存相關(guān)的 HTTP 頭部字段

          3.1 Expires

          • 響應(yīng)頭Expires字段包含強(qiáng)緩存資源的過期時間
          • 值為 0 表示資源已過期或非強(qiáng)緩存

          3.2 Cache-Control

          通用消息頭字段,通過指令來實現(xiàn)緩存機(jī)制。說明一下容易弄混的兩個字段,其他指令參考指令大全[1]

          • no-cache

          在發(fā)布緩存副本之前,強(qiáng)制要求緩存把請求提交給原始服務(wù)器進(jìn)行驗證(協(xié)商緩存驗證)。

          • no-store

          緩存不應(yīng)存儲有關(guān)客戶端請求或服務(wù)器響應(yīng)的任何內(nèi)容,即不使用任何緩存。

          3.3 Expires 和 Cache-Control 的區(qū)別

          • 時間區(qū)別
            • Expires 過期時間為絕對時間,指未來某個時間點緩存過期。
            • Cache-Control 為相對時間,相對于當(dāng)前時間,如 60s 后緩存過期
          • 優(yōu)先級
            • Expires 的優(yōu)先級低于 Cache-Control 字段
            • 同時存在 Cache-ControlExpires時,以 Cache-Control 指令為準(zhǔn)
          • HTTP 版本
            • Expires 是 HTTP/1.0 提出的,其瀏覽器兼容性更好
            • Cache-Control 是 HTTP/1.1 提出的,瀏覽器兼容性不佳,所以 ExpiresCache-Control 可以同時存在,在不支持 Cache-Control的瀏覽器則以Expires為準(zhǔn)

          4. 協(xié)商緩存

          • 協(xié)商緩存即和服務(wù)器協(xié)商是否使用緩存,通過判斷后決定重新加載資源 or HTTP StatusCode 304
          • 以下字段決定是否使用協(xié)商緩存,而非強(qiáng)緩存:

          4.1 Pragma

          • Pragma是一個 HTTP1.0 中規(guī)定的通用首部,如果Cache-Control不存在的話,它的行為與Cache-Control: no-cache一致。強(qiáng)制要求緩存服務(wù)器在返回緩存的版本之前將請求提交到源頭服務(wù)器進(jìn)行協(xié)商驗證。
          • Pragma 的值就只有一個,no-cache,并且它的優(yōu)先級比 Cache-Control 高。

          4.2 Cache-Control

          • 上文介紹過Cache-Control,它的指令既可以用于強(qiáng)緩存又可應(yīng)用于協(xié)商緩存策略中
          • 其中Cache-Control: no-cacheCache-Control: max-age=0 的作用一樣,強(qiáng)制要求發(fā)起請求給服務(wù)器進(jìn)行驗證 (協(xié)商資源驗證)。

          5. 協(xié)商策略

          當(dāng)出現(xiàn)Pragma字段或者Cache-Control:no-cache時,就需要使用協(xié)商策略,常見的兩對協(xié)商緩存字段如下

          • ETag/If-None-Match
          • Last-Modified/If-Modfied-Since

          優(yōu)缺點

          • 如果服務(wù)端修改了一段代碼,然后又改回去了。
            • 此時資源文件的修改時間變了
            • 實際上文件沒有發(fā)生改變
            • 這樣緩存就失效了,產(chǎn)生了不必要的傳輸
          • 而 ETag 可以根據(jù)內(nèi)容生成的 hash 來比較的,只要資源文件內(nèi)容不變,就會應(yīng)用客戶端的緩存,減少不必要的傳輸。
          • 所以 ETag 比 Last-Modified 緩存更精確、高效和節(jié)省帶寬。

          6. ETag

          6.1 什么是 ETag?

          Etag 是 Entity tag 的縮寫,可以理解為“被請求資源的摘要標(biāo)識”,Etag 是服務(wù)端的一個資源的標(biāo)識,在 HTTP 響應(yīng)頭中將其傳送到客戶端,類似這樣,ETag:W/"50b1c1d4f775c61:df3"

          6.2 ETag 格式

          • ETag:W/"xxxxxxxx"
          • ETag:"xxxxxxx"

          強(qiáng)類型驗證

          • 比對資源每個字節(jié)都要一樣。

          W/前綴代表使用弱類型驗證

          • 不需要每個字節(jié)都一樣,例如頁腳的時間 or 展示的廣告不一樣,都可以認(rèn)為是一樣的。構(gòu)建應(yīng)用于弱驗證類型的標(biāo)簽(etag)體系可能會比較復(fù)雜,因為這會涉及到對頁面上不同的元素的重要性進(jìn)行排序,但是會對緩存性能優(yōu)化相當(dāng)有幫助。

          6.3 ETag 生成需要滿足什么條件?

          1. 當(dāng)文件更改時,ETag 值必須改變
          2. 盡量便于計算,不會特別耗 CPU。
          3. 利用摘要算法生成(MD5, SHA128, SHA256)需慎重考慮,這些為 CPU 密集型運(yùn)算。
          4. 不是不能用。沒有最好的算法,只有適合對應(yīng)場景的算法。
          5. 必須橫向擴(kuò)展,分布式部署時多個服務(wù)器節(jié)點上生成的 ETag 值保持一致。

          6.4 ETag 是怎么生成的(Nginx)

          Nginx[2]的源碼中 ETag 由 last_modified 和 content_length 拼接而成

          etag->value.len = ngx_sprintf(etag->value.data, "\"%xT-%xO\"",
                                            r->headers_out.last_modified_time,
                                            r->headers_out.content_length_n)
                                - etag->value.data;
          • 翻譯為以下偽代碼
          etag = header.last_modified + "-" + header.content_lenth
          • 總結(jié):Nginx 中 ETag 由響應(yīng)頭的Last-ModifiedContent-Length表示為十六進(jìn)制組合而成。

          Lodash 網(wǎng)站請求檢驗

          const LAST_MODIFIED = new Date(parseInt('5fc4907d'16) * 1000).toJSON()
          const CONTENT_LENGTH = parseInt('f48'16)

          console.log(LAST_MODIFIED) // 2020-11-30T06:26:05.000Z
          console.log(CONTENT_LENGTH) // 3912
          • 輸出結(jié)果
          • 既然在nginxETagLast-ModifiedContent-Length組成,那它便算是一個加強(qiáng)版的Last-Modified了,那加強(qiáng)在什么地方呢?
          • Last-Modified只能作用于秒級的改變,而 nginx 中的 ETag 添加了文件大小的附加條件,不僅和修改時間有關(guān),也和內(nèi)容有關(guān),使之更加精確。

          6.5 Last-Modified 是怎么生成的

          在 linux 中

          • mtimemodified time指文件內(nèi)容改變的時間戳
          • ctimechange time指文件屬性改變的時間戳,屬性包括mtime。而在 windows 上,它表示的是creation time
          • 而 HTTP 服務(wù)選擇Last-Modified時一般會選擇mtime,表示文件內(nèi)容修改的時間,來兼容 Windows 和 Linux。
          • 以下為nginx 源碼[3]
              r->headers_out.status = NGX_HTTP_OK;
              r->headers_out.content_length_n = of.size;
              r->headers_out.last_modified_time = of.mtime;

          6.6 如果 http 響應(yīng)頭中 ETag 值改變了,是否意味著文件內(nèi)容一定已經(jīng)更改?

          • 不一定
          • 文件在一秒內(nèi)發(fā)生了改變而且文件大小不變
          • 這種情況非常極端,概率很低
          • 因此在正常情況下可以容忍一個不太完美但是高效的算法。

          參考資料

          [1]

          https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control

          [2]

          https://github.com/nginx/nginx/blob/6c3838f9ed45f5c2aa6a971a0da3cb6ffe45b61e/src/http/ngx_http_core_module.c#L1582

          [3]

          https://github.com/nginx/nginx/blob/4bf4650f2f10f7bbacfe7a33da744f18951d416d/src/http/modules/ngx_http_static_module.c#L217


          掃碼即可進(jìn)內(nèi)推群

          瀏覽 47
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产激情精品视频 | 日韩精品在线一二三四五区 | 亚洲视频 | 内射视频网站免费观看 | 一本无码在线观看 |