国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Http緩存機制

keke / 2065人閱讀

摘要:請求過程如下瀏覽器請求靜態資源服務器讀取磁盤文件,返給瀏覽器,同時帶上文件的唯一標識當瀏覽器上的緩存文件過期時,瀏覽器帶上請求頭等于上一次請求的請求服務器服務器比較請求頭里的和文件的。

前言 Http簡介

瀏覽器和服務器之間通信是通過HTTP協議,HTTP協議永遠都是客戶端發起請求,服務器回送響應。模型如下:

HTTP報文就是瀏覽器和服務器間通信時發送及響應的數據塊。瀏覽器向服務器請求數據,發送請求(request)報文;服務器向瀏覽器返回數據,返回響應(response)報文。報文信息主要分為兩部分:

報文頭部:一些附加信息(cookie,緩存信息等),與緩存相關的規則信息,均包含在頭部中
數據主體部分:HTTP請求真正想要傳輸的數據內容

緩存的作用

我們為什么使用緩存,是因為緩存可以給我們的 Web 項目帶來以下好處,以提高性能和用戶體驗。

加快了瀏覽器加載網頁的速度;
減少了冗余的數據傳輸,節省網絡流量和帶寬;
減少服務器的負擔,大大提高了網站的性能。

由于從本地緩存讀取靜態資源,加快瀏覽器的網頁加載速度是一定的,也確實的減少了數據傳輸,就提高網站性能來說,可能一兩個用戶的訪問對于減小服務器的負擔沒有明顯效果,但如果這個網站在高并發的情況下,使用緩存對于減小服務器壓力和整個網站的性能都會發生質的變化。

原始模型(不是用緩存)

搭建一個Express的服務器,不加任何緩存信息頭:

const express = require("express");
const app = express();
const port = 8080;
const fs = require("fs");
const path = require("path");

app.get("/",(req,res) => {
    res.send(`
    
    
        Document
    
    
        Http Cache Demo
        
    
    `)
})

app.get("/demo.js",(req, res)=>{
    let jsPath = path.resolve(__dirname,"./static/js/demo.js");
    let cont = fs.readFileSync(jsPath);
    res.end(cont)
})

app.listen(port,()=>{
    console.log(`listen on ${port}`)    
})

我們可以看到請求結果如下:

請求過程如下:

瀏覽器請求靜態資源demo.js

服務器讀取磁盤文件demo.js,返給瀏覽器

瀏覽器再次請求,服務器又重新讀取磁盤文件 demo.js,返給瀏覽器。

循環請求。。

??看得出來這種請求方式的流量與請求次數有關,同時,缺點也很明顯:

浪費用戶流量

浪費服務器資源,服務器要讀磁盤文件,然后發送文件到瀏覽器

瀏覽器要等待js下載并且執行后才能渲染頁面,影響用戶體驗

緩存規則

為了方便理解,我們認為瀏覽器存在一個緩存數據庫,用于存儲緩存信息(實際上靜態資源是被緩存到了內存和磁盤中),在瀏覽器第一次請求數據時,此時緩存數據庫沒有對應的緩存數據,則需要請求服務器,服務器會將緩存規則和數據返回,瀏覽器將緩存規則和數據存儲進緩存數據庫。

當瀏覽器地址欄輸入地址后請求的 index.html 是不會被緩存的,但 index.html 內部請求的其他資源會遵循緩存策略,HTTP 緩存有多種規則,根據是否需要向服務器發送請求主要分為兩大類,強制緩存和協商緩存。

Http緩存的分類

Http緩存可以分為兩大類,強制緩存(也稱強緩存)和協商緩存。兩類緩存規則不同,強制緩存在緩存數據未失效的情況下,不需要再和服務器發生交互;而協商緩存,顧名思義,需要進行比較判斷是否可以使用緩存。
??兩類緩存規則可以同時存在,強制緩存優先級高于協商緩存,也就是說,當執行強制緩存的規則時,如果緩存生效,直接使用緩存,不再執行協商緩存規則。

強制緩存

強制緩存是第一次訪問服務器獲取數據后,在有效時間內不會再請求服務器,而是直接使用緩存數據,強制緩存的流程如下:

強制緩存分為兩種情況,Expires和Cache-Control。

Expires

Expires的值是服務器告訴瀏覽器的緩存過期時間(值為GMT時間,即格林尼治時間),即下一次請求時,如果瀏覽器端的當前時間還沒有到達過期時間,則直接使用緩存數據。下面通過我們的Express服務器來設置一下Expires響應頭信息。

//其他代碼...
const moment = require("moment");

app.get("/demo.js",(req, res)=>{
    let jsPath = path.resolve(__dirname,"./static/js/demo.js");
    let cont = fs.readFileSync(jsPath);
    res.setHeader("Expires", getGLNZ()) //2分鐘
    res.end(cont)
})

function getGLNZ(){
    return moment().utc().add(2,"m").format("ffffd, DD MMM YYYY HH:mm:ss")+" GMT";
}
//其他代碼...

我們在demo.js中添加了一個Expires響應頭,不過由于是格林尼治時間,所以通過momentjs轉換一下。第一次請求的時候還是會向服務器發起請求,同時會把過期時間和文件一起返回給我們;但是當我們刷新的時候,才是見證奇跡的時刻:

可以看出文件是直接從緩存(memory cache)中讀取的,并沒有發起請求。我們在這邊設置過期時間為兩分鐘,兩分鐘過后可以刷新一下頁面看到瀏覽器再次發送請求了。

??雖然這種方式添加了緩存控制,節省流量,但是還是有以下幾個問題的:

由于瀏覽器時間和服務器時間不同步,如果瀏覽器設置了一個很后的時間,過期時間一直沒有用

緩存過期后,不管文件有沒有發生變化,服務器都會再次讀取文件返回給瀏覽器

不過Expires 是HTTP 1.0的東西,現在默認瀏覽器均默認使用HTTP 1.1,所以它的作用基本忽略。

Cache-Control

針對瀏覽器和服務器時間不同步,加入了新的緩存方案;這次服務器不是直接告訴瀏覽器過期時間,而是告訴一個相對時間Cache-Control=10秒,意思是10秒內,直接使用瀏覽器緩存。

Cache-Control各個值的含義:

**private**:客戶端可以緩存;
**public**:客戶端和代理服務器都可以緩存(對于前端而言,可以認為與 private 效果相同);
**max-age=xxx**:緩存的內容將在 xxx 秒后過期(相對時間,秒為單位);
**no-cache**:需要使用協商緩存(后面介紹)來驗證數據是否過期;
**no-store**:所有內容都不會緩存,強制緩存和協商緩存都不會觸發。

app.get("/demo.js",(req, res)=>{
    let jsPath = path.resolve(__dirname,"./static/js/demo.js");
    let cont = fs.readFileSync(jsPath);
    res.setHeader("Cache-Control", "public,max-age=120") //2分鐘
    res.end(cont)
})

其實緩存的儲存是內存和磁盤兩個位置,由當前瀏覽器本身的策略決定,比較隨機,從內存的緩存中取出的數據會顯示 (from memory cache),從磁盤的緩存中取出的數據會顯示 (from disk cache)。

協商緩存

強制緩存的弊端很明顯,即每次都是根據時間來判斷緩存是否過期;但是當到達過期時間后,如果文件沒有改動,再次去獲取文件就有點浪費服務器的資源了。

協商緩存又叫對比緩存,設置協商緩存后,第一次訪問服務器獲取數據時,服務器會將數據和緩存標識一起返回給瀏覽器,客戶端會將數據和標識存入緩存數據庫中,下一次請求時,會先去緩存中取出緩存標識發送給服務器進行詢問,當服務器數據更改時會更新標識,所以服務器拿到瀏覽器發來的標識進行對比,相同代表數據未更改,響應瀏覽器通知數據未更改,瀏覽器會去緩存中獲取數據,如果標識不同,代表服務器更改過數據,所以會將新的數據和新的標識返回瀏覽器,瀏覽器會將新的數據和標識存入緩存中,協商緩存的流程如下:

協商緩存和強制緩存不同的是,協商緩存每次請求都需要跟服務器通信,而且命中緩存服務器返回狀態碼不再是 200,而是 304。

協商緩存有兩組報文結合使用:

Last-Modified和If-Modified-Since

ETag和If-None-Match

Last-Modified

HTTP 1.0 版本中:
為了節省服務器的資源,再次改進方案。瀏覽器和服務器協商,服務器每次返回文件的同時,告訴瀏覽器文件在服務器上最近的修改時間。請求過程如下:

瀏覽器請求靜態資源demo.js

服務器讀取磁盤文件demo.js,返給瀏覽器,同時帶上文件上次修改時間 Last-Modified(GMT標準格式)

當瀏覽器上的緩存文件過期時,瀏覽器帶上請求頭If-Modified-Since(等于上一次請求的Last-Modified)請求服務器

服務器比較請求頭里的If-Modified-Since和文件的上次修改時間。如果果一致就繼續使用本地緩存(304),如果不一致就再次返回文件內容和Last-Modified。

循環請求。。

代碼實現過程如下:

app.get("/demo.js",(req, res)=>{
    let jsPath = path.resolve(__dirname,"./static/js/demo.js")
    let cont = fs.readFileSync(jsPath);
    let status = fs.statSync(jsPath)

    let lastModified = status.mtime.toUTCString()
    if(lastModified === req.headers["if-modified-since"]){
        res.writeHead(304, "Not Modified")
        res.end()
    } else {
        res.setHeader("Cache-Control", "public,max-age=5")
        res.setHeader("Last-Modified", lastModified)
        res.writeHead(200, "OK")
        res.end(cont)
    }
})

雖然這個方案比前面三個方案有了進一步的優化,瀏覽器檢測文件是否有修改,如果沒有變化就不再發送文件;但是還是有以下缺點:

由于Last-Modified修改時間是GMT時間,只能精確到秒,如果文件在1秒內有多次改動,服務器并不知道文件有改動,瀏覽器拿不到最新的文件

如果服務器上文件被多次修改了但是內容卻沒有發生改變,服務器需要再次重新返回文件。

ETag

HTTP 1.1 版本中:
為了解決文件修改時間不精確帶來的問題,服務器和瀏覽器再次協商,這次不返回時間,返回文件的唯一標識ETag。只有當文件內容改變時,ETag才改變。請求過程如下:

瀏覽器請求靜態資源demo.js

服務器讀取磁盤文件demo.js,返給瀏覽器,同時帶上文件的唯一標識ETag

當瀏覽器上的緩存文件過期時,瀏覽器帶上請求頭If-None-Match(等于上一次請求的ETag)請求服務器

服務器比較請求頭里的If-None-Match和文件的ETag。如果一致就繼續使用本地緩存(304),如果不一致就再次返回文件內容和ETag。

循環請求。。

const md5 = require("md5");

app.get("/demo.js",(req, res)=>{
    let jsPath = path.resolve(__dirname,"./static/js/demo.js");
    let cont = fs.readFileSync(jsPath);
    let etag = md5(cont);

    if(req.headers["if-none-match"] === etag){
        res.writeHead(304, "Not Modified");
        res.end();
    } else {
        res.setHeader("ETag", etag);
        res.writeHead(200, "OK");
        res.end(cont);
    }
})

請求結果如下:

總結

為了使緩存策略更加健壯、靈活,HTTP 1.0 版本 和 HTTP 1.1 版本的緩存策略會同時使用,甚至強制緩存和協商緩存也會同時使用,對于強制緩存,服務器通知瀏覽器一個緩存時間,在緩存時間內,下次請求,直接使用緩存,超出有效時間,執行協商緩存策略,對于協商緩存,將緩存信息中的 Etag 和 Last-Modified 通過請求頭 If-None-Match 和 If-Modified-Since 發送給服務器,由服務器校驗同時設置新的強制緩存,校驗通過并返回 304 狀態碼時,瀏覽器直接使用緩存,如果協商緩存也未命中,則服務器重新設置協商緩存的標識。

關于Pragma

當該字段值為no-cache的時候,會告訴瀏覽器不要對該資源緩存,即每次都得向服務器發一次請求才行:

res.setHeader("Pragma", "no-cache") //禁止緩存
res.setHeader("Cache-Control", "public,max-age=120") //2分鐘

通過Pragma來禁止緩存,通過Cache-Control設置兩分鐘緩存,但是重新訪問我們會發現瀏覽器會再次發起一次請求,說明了Pragma的優先級高于Cache-Control

緩存的優先級
Pragma > Cache-Control > Expires > ETag > Last-Modified

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/62037.html

相關文章

  • Web緩存相關知識整理

    摘要:緩存緩存,也叫網關緩存反向代理緩存。瀏覽器先向網關發起請求,網關服務器后面對應著一臺或多臺負載均衡源服務器,會根據它們的負載請求,動態將請求轉發到合適的源服務器上。雖然這種架構負載均衡源服務器之間的緩存沒法共享,但卻擁有更好的處擴展性。 一、前言? 工作上遇到一個這樣的需求,一個H5頁面在APP端,如果勾選已讀狀態,則下次打開該鏈接,會跳過此頁面。用到了HTML5 的本地存儲 API ...

    rickchen 評論0 收藏0
  • 瀏覽器緩存是什么?它的機制又是什么?

    摘要:對于瀏覽器緩存,相信很多開發者對它真的是又愛又恨。那么瀏覽器緩存究竟是個什么樣的神奇玩意呢什么是瀏覽器緩存簡單來說,瀏覽器緩存就是把一個已經請求過的資源如頁面,圖片,,數據等拷貝一份副本儲存在瀏覽器中。 對于瀏覽器緩存,相信很多開發者對它真的是又愛又恨。一方面極大地提升了用戶體驗,而另一方面有時會因為讀取了緩存而展示了錯誤的東西,而在開發過程中千方百計地想把緩存禁掉。那么瀏覽器緩存究竟...

    jsummer 評論0 收藏0
  • 瀏覽器緩存是什么?它的機制又是什么?

    摘要:對于瀏覽器緩存,相信很多開發者對它真的是又愛又恨。那么瀏覽器緩存究竟是個什么樣的神奇玩意呢什么是瀏覽器緩存簡單來說,瀏覽器緩存就是把一個已經請求過的資源如頁面,圖片,,數據等拷貝一份副本儲存在瀏覽器中。 對于瀏覽器緩存,相信很多開發者對它真的是又愛又恨。一方面極大地提升了用戶體驗,而另一方面有時會因為讀取了緩存而展示了錯誤的東西,而在開發過程中千方百計地想把緩存禁掉。那么瀏覽器緩存究竟...

    godruoyi 評論0 收藏0
  • HTTP緩存機制

    摘要:緩存機制緩存機制主要由以下三部分組成緩存存儲策略這個策略的作用只有一個,用于決定響應內容是否可緩存到客戶端。如果判斷標識無效,則返回,用新數據替換客戶端緩存。表示文件在本地應該緩存,且有效時長是秒從發出請求算起。 HTTP緩存機制 HTTP緩存機制主要由以下三部分組成 緩存存儲策略 這個策略的作用只有一個,用于決定 Http 響應內容是否可緩存到客戶端。主要通過Cache-Contro...

    huangjinnan 評論0 收藏0
  • 瀏覽器緩存機制學習總結

    瀏覽器緩存機制學習總結 最近在做一個考試系統時,由于經常加載試卷或圖片等等靜態資源,抽空學習了一下緩存機制,在此記錄 為什么要使用緩存 1、通過HTTP協議,在客戶端和瀏覽器建立連接時需要消耗時間,而大的響應需要在客戶端和服務器之間進行多次往返通信才能獲得完整的響應,這拖延了瀏覽器可以使用和處理內容的時間。這就增加了訪問服務器的數據和資源的成本,因此利用瀏覽器的緩存機制重用以前獲取的數據就變成了性...

    JiaXinYi 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<