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

資訊專欄INFORMATION COLUMN

Http緩存機(jī)制

keke / 2069人閱讀

摘要:請(qǐng)求過(guò)程如下瀏覽器請(qǐng)求靜態(tài)資源服務(wù)器讀取磁盤(pán)文件,返給瀏覽器,同時(shí)帶上文件的唯一標(biāo)識(shí)當(dāng)瀏覽器上的緩存文件過(guò)期時(shí),瀏覽器帶上請(qǐng)求頭等于上一次請(qǐng)求的請(qǐng)求服務(wù)器服務(wù)器比較請(qǐng)求頭里的和文件的。

前言 Http簡(jiǎn)介

瀏覽器和服務(wù)器之間通信是通過(guò)HTTP協(xié)議,HTTP協(xié)議永遠(yuǎn)都是客戶端發(fā)起請(qǐng)求,服務(wù)器回送響應(yīng)。模型如下:

HTTP報(bào)文就是瀏覽器和服務(wù)器間通信時(shí)發(fā)送及響應(yīng)的數(shù)據(jù)塊。瀏覽器向服務(wù)器請(qǐng)求數(shù)據(jù),發(fā)送請(qǐng)求(request)報(bào)文;服務(wù)器向?yàn)g覽器返回?cái)?shù)據(jù),返回響應(yīng)(response)報(bào)文。報(bào)文信息主要分為兩部分:

報(bào)文頭部:一些附加信息(cookie,緩存信息等),與緩存相關(guān)的規(guī)則信息,均包含在頭部中
數(shù)據(jù)主體部分:HTTP請(qǐng)求真正想要傳輸?shù)臄?shù)據(jù)內(nèi)容

緩存的作用

我們?yōu)槭裁词褂镁彺妫且驗(yàn)榫彺婵梢越o我們的 Web 項(xiàng)目帶來(lái)以下好處,以提高性能和用戶體驗(yàn)。

加快了瀏覽器加載網(wǎng)頁(yè)的速度;
減少了冗余的數(shù)據(jù)傳輸,節(jié)省網(wǎng)絡(luò)流量和帶寬;
減少服務(wù)器的負(fù)擔(dān),大大提高了網(wǎng)站的性能。

由于從本地緩存讀取靜態(tài)資源,加快瀏覽器的網(wǎng)頁(yè)加載速度是一定的,也確實(shí)的減少了數(shù)據(jù)傳輸,就提高網(wǎng)站性能來(lái)說(shuō),可能一兩個(gè)用戶的訪問(wèn)對(duì)于減小服務(wù)器的負(fù)擔(dān)沒(méi)有明顯效果,但如果這個(gè)網(wǎng)站在高并發(fā)的情況下,使用緩存對(duì)于減小服務(wù)器壓力和整個(gè)網(wǎng)站的性能都會(huì)發(fā)生質(zhì)的變化。

原始模型(不是用緩存)

搭建一個(gè)Express的服務(wù)器,不加任何緩存信息頭:

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}`)    
})

我們可以看到請(qǐng)求結(jié)果如下:

請(qǐng)求過(guò)程如下:

瀏覽器請(qǐng)求靜態(tài)資源demo.js

服務(wù)器讀取磁盤(pán)文件demo.js,返給瀏覽器

瀏覽器再次請(qǐng)求,服務(wù)器又重新讀取磁盤(pán)文件 demo.js,返給瀏覽器。

循環(huán)請(qǐng)求。。

??看得出來(lái)這種請(qǐng)求方式的流量與請(qǐng)求次數(shù)有關(guān),同時(shí),缺點(diǎn)也很明顯:

浪費(fèi)用戶流量

浪費(fèi)服務(wù)器資源,服務(wù)器要讀磁盤(pán)文件,然后發(fā)送文件到瀏覽器

瀏覽器要等待js下載并且執(zhí)行后才能渲染頁(yè)面,影響用戶體驗(yàn)

緩存規(guī)則

為了方便理解,我們認(rèn)為瀏覽器存在一個(gè)緩存數(shù)據(jù)庫(kù),用于存儲(chǔ)緩存信息(實(shí)際上靜態(tài)資源是被緩存到了內(nèi)存和磁盤(pán)中),在瀏覽器第一次請(qǐng)求數(shù)據(jù)時(shí),此時(shí)緩存數(shù)據(jù)庫(kù)沒(méi)有對(duì)應(yīng)的緩存數(shù)據(jù),則需要請(qǐng)求服務(wù)器,服務(wù)器會(huì)將緩存規(guī)則和數(shù)據(jù)返回,瀏覽器將緩存規(guī)則和數(shù)據(jù)存儲(chǔ)進(jìn)緩存數(shù)據(jù)庫(kù)。

當(dāng)瀏覽器地址欄輸入地址后請(qǐng)求的 index.html 是不會(huì)被緩存的,但 index.html 內(nèi)部請(qǐng)求的其他資源會(huì)遵循緩存策略,HTTP 緩存有多種規(guī)則,根據(jù)是否需要向服務(wù)器發(fā)送請(qǐng)求主要分為兩大類,強(qiáng)制緩存和協(xié)商緩存。

Http緩存的分類

Http緩存可以分為兩大類,強(qiáng)制緩存(也稱強(qiáng)緩存)和協(xié)商緩存。兩類緩存規(guī)則不同,強(qiáng)制緩存在緩存數(shù)據(jù)未失效的情況下,不需要再和服務(wù)器發(fā)生交互;而協(xié)商緩存,顧名思義,需要進(jìn)行比較判斷是否可以使用緩存。
??兩類緩存規(guī)則可以同時(shí)存在,強(qiáng)制緩存優(yōu)先級(jí)高于協(xié)商緩存,也就是說(shuō),當(dāng)執(zhí)行強(qiáng)制緩存的規(guī)則時(shí),如果緩存生效,直接使用緩存,不再執(zhí)行協(xié)商緩存規(guī)則。

強(qiáng)制緩存

強(qiáng)制緩存是第一次訪問(wèn)服務(wù)器獲取數(shù)據(jù)后,在有效時(shí)間內(nèi)不會(huì)再請(qǐng)求服務(wù)器,而是直接使用緩存數(shù)據(jù),強(qiáng)制緩存的流程如下:

強(qiáng)制緩存分為兩種情況,Expires和Cache-Control。

Expires

Expires的值是服務(wù)器告訴瀏覽器的緩存過(guò)期時(shí)間(值為GMT時(shí)間,即格林尼治時(shí)間),即下一次請(qǐng)求時(shí),如果瀏覽器端的當(dāng)前時(shí)間還沒(méi)有到達(dá)過(guò)期時(shí)間,則直接使用緩存數(shù)據(jù)。下面通過(guò)我們的Express服務(wù)器來(lái)設(shè)置一下Expires響應(yīng)頭信息。

//其他代碼...
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";
}
//其他代碼...

我們?cè)赿emo.js中添加了一個(gè)Expires響應(yīng)頭,不過(guò)由于是格林尼治時(shí)間,所以通過(guò)momentjs轉(zhuǎn)換一下。第一次請(qǐng)求的時(shí)候還是會(huì)向服務(wù)器發(fā)起請(qǐng)求,同時(shí)會(huì)把過(guò)期時(shí)間和文件一起返回給我們;但是當(dāng)我們刷新的時(shí)候,才是見(jiàn)證奇跡的時(shí)刻:

可以看出文件是直接從緩存(memory cache)中讀取的,并沒(méi)有發(fā)起請(qǐng)求。我們?cè)谶@邊設(shè)置過(guò)期時(shí)間為兩分鐘,兩分鐘過(guò)后可以刷新一下頁(yè)面看到瀏覽器再次發(fā)送請(qǐng)求了。

??雖然這種方式添加了緩存控制,節(jié)省流量,但是還是有以下幾個(gè)問(wèn)題的:

由于瀏覽器時(shí)間和服務(wù)器時(shí)間不同步,如果瀏覽器設(shè)置了一個(gè)很后的時(shí)間,過(guò)期時(shí)間一直沒(méi)有用

緩存過(guò)期后,不管文件有沒(méi)有發(fā)生變化,服務(wù)器都會(huì)再次讀取文件返回給瀏覽器

不過(guò)Expires 是HTTP 1.0的東西,現(xiàn)在默認(rèn)瀏覽器均默認(rèn)使用HTTP 1.1,所以它的作用基本忽略。

Cache-Control

針對(duì)瀏覽器和服務(wù)器時(shí)間不同步,加入了新的緩存方案;這次服務(wù)器不是直接告訴瀏覽器過(guò)期時(shí)間,而是告訴一個(gè)相對(duì)時(shí)間Cache-Control=10秒,意思是10秒內(nèi),直接使用瀏覽器緩存。

Cache-Control各個(gè)值的含義:

**private**:客戶端可以緩存;
**public**:客戶端和代理服務(wù)器都可以緩存(對(duì)于前端而言,可以認(rèn)為與 private 效果相同);
**max-age=xxx**:緩存的內(nèi)容將在 xxx 秒后過(guò)期(相對(duì)時(shí)間,秒為單位);
**no-cache**:需要使用協(xié)商緩存(后面介紹)來(lái)驗(yàn)證數(shù)據(jù)是否過(guò)期;
**no-store**:所有內(nèi)容都不會(huì)緩存,強(qiáng)制緩存和協(xié)商緩存都不會(huì)觸發(fā)。

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)
})

其實(shí)緩存的儲(chǔ)存是內(nèi)存和磁盤(pán)兩個(gè)位置,由當(dāng)前瀏覽器本身的策略決定,比較隨機(jī),從內(nèi)存的緩存中取出的數(shù)據(jù)會(huì)顯示 (from memory cache),從磁盤(pán)的緩存中取出的數(shù)據(jù)會(huì)顯示 (from disk cache)。

協(xié)商緩存

強(qiáng)制緩存的弊端很明顯,即每次都是根據(jù)時(shí)間來(lái)判斷緩存是否過(guò)期;但是當(dāng)?shù)竭_(dá)過(guò)期時(shí)間后,如果文件沒(méi)有改動(dòng),再次去獲取文件就有點(diǎn)浪費(fèi)服務(wù)器的資源了。

協(xié)商緩存又叫對(duì)比緩存,設(shè)置協(xié)商緩存后,第一次訪問(wèn)服務(wù)器獲取數(shù)據(jù)時(shí),服務(wù)器會(huì)將數(shù)據(jù)和緩存標(biāo)識(shí)一起返回給瀏覽器,客戶端會(huì)將數(shù)據(jù)和標(biāo)識(shí)存入緩存數(shù)據(jù)庫(kù)中,下一次請(qǐng)求時(shí),會(huì)先去緩存中取出緩存標(biāo)識(shí)發(fā)送給服務(wù)器進(jìn)行詢問(wèn),當(dāng)服務(wù)器數(shù)據(jù)更改時(shí)會(huì)更新標(biāo)識(shí),所以服務(wù)器拿到瀏覽器發(fā)來(lái)的標(biāo)識(shí)進(jìn)行對(duì)比,相同代表數(shù)據(jù)未更改,響應(yīng)瀏覽器通知數(shù)據(jù)未更改,瀏覽器會(huì)去緩存中獲取數(shù)據(jù),如果標(biāo)識(shí)不同,代表服務(wù)器更改過(guò)數(shù)據(jù),所以會(huì)將新的數(shù)據(jù)和新的標(biāo)識(shí)返回瀏覽器,瀏覽器會(huì)將新的數(shù)據(jù)和標(biāo)識(shí)存入緩存中,協(xié)商緩存的流程如下:

協(xié)商緩存和強(qiáng)制緩存不同的是,協(xié)商緩存每次請(qǐng)求都需要跟服務(wù)器通信,而且命中緩存服務(wù)器返回狀態(tài)碼不再是 200,而是 304。

協(xié)商緩存有兩組報(bào)文結(jié)合使用:

Last-Modified和If-Modified-Since

ETag和If-None-Match

Last-Modified

HTTP 1.0 版本中:
為了節(jié)省服務(wù)器的資源,再次改進(jìn)方案。瀏覽器和服務(wù)器協(xié)商,服務(wù)器每次返回文件的同時(shí),告訴瀏覽器文件在服務(wù)器上最近的修改時(shí)間。請(qǐng)求過(guò)程如下:

瀏覽器請(qǐng)求靜態(tài)資源demo.js

服務(wù)器讀取磁盤(pán)文件demo.js,返給瀏覽器,同時(shí)帶上文件上次修改時(shí)間 Last-Modified(GMT標(biāo)準(zhǔn)格式)

當(dāng)瀏覽器上的緩存文件過(guò)期時(shí),瀏覽器帶上請(qǐng)求頭If-Modified-Since(等于上一次請(qǐng)求的Last-Modified)請(qǐng)求服務(wù)器

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

循環(huán)請(qǐng)求。。

代碼實(shí)現(xiàn)過(guò)程如下:

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)
    }
})

雖然這個(gè)方案比前面三個(gè)方案有了進(jìn)一步的優(yōu)化,瀏覽器檢測(cè)文件是否有修改,如果沒(méi)有變化就不再發(fā)送文件;但是還是有以下缺點(diǎn):

由于Last-Modified修改時(shí)間是GMT時(shí)間,只能精確到秒,如果文件在1秒內(nèi)有多次改動(dòng),服務(wù)器并不知道文件有改動(dòng),瀏覽器拿不到最新的文件

如果服務(wù)器上文件被多次修改了但是內(nèi)容卻沒(méi)有發(fā)生改變,服務(wù)器需要再次重新返回文件。

ETag

HTTP 1.1 版本中:
為了解決文件修改時(shí)間不精確帶來(lái)的問(wèn)題,服務(wù)器和瀏覽器再次協(xié)商,這次不返回時(shí)間,返回文件的唯一標(biāo)識(shí)ETag。只有當(dāng)文件內(nèi)容改變時(shí),ETag才改變。請(qǐng)求過(guò)程如下:

瀏覽器請(qǐng)求靜態(tài)資源demo.js

服務(wù)器讀取磁盤(pán)文件demo.js,返給瀏覽器,同時(shí)帶上文件的唯一標(biāo)識(shí)ETag

當(dāng)瀏覽器上的緩存文件過(guò)期時(shí),瀏覽器帶上請(qǐng)求頭If-None-Match(等于上一次請(qǐng)求的ETag)請(qǐng)求服務(wù)器

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

循環(huán)請(qǐng)求。。

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);
    }
})

請(qǐng)求結(jié)果如下:

總結(jié)

為了使緩存策略更加健壯、靈活,HTTP 1.0 版本 和 HTTP 1.1 版本的緩存策略會(huì)同時(shí)使用,甚至強(qiáng)制緩存和協(xié)商緩存也會(huì)同時(shí)使用,對(duì)于強(qiáng)制緩存,服務(wù)器通知瀏覽器一個(gè)緩存時(shí)間,在緩存時(shí)間內(nèi),下次請(qǐng)求,直接使用緩存,超出有效時(shí)間,執(zhí)行協(xié)商緩存策略,對(duì)于協(xié)商緩存,將緩存信息中的 Etag 和 Last-Modified 通過(guò)請(qǐng)求頭 If-None-Match 和 If-Modified-Since 發(fā)送給服務(wù)器,由服務(wù)器校驗(yàn)同時(shí)設(shè)置新的強(qiáng)制緩存,校驗(yàn)通過(guò)并返回 304 狀態(tài)碼時(shí),瀏覽器直接使用緩存,如果協(xié)商緩存也未命中,則服務(wù)器重新設(shè)置協(xié)商緩存的標(biāo)識(shí)。

關(guān)于Pragma

當(dāng)該字段值為no-cache的時(shí)候,會(huì)告訴瀏覽器不要對(duì)該資源緩存,即每次都得向服務(wù)器發(fā)一次請(qǐng)求才行:

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

通過(guò)Pragma來(lái)禁止緩存,通過(guò)Cache-Control設(shè)置兩分鐘緩存,但是重新訪問(wèn)我們會(huì)發(fā)現(xiàn)瀏覽器會(huì)再次發(fā)起一次請(qǐng)求,說(shuō)明了Pragma的優(yōu)先級(jí)高于Cache-Control

緩存的優(yōu)先級(jí)
Pragma > Cache-Control > Expires > ETag > Last-Modified

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/62037.html

相關(guān)文章

  • Web緩存相關(guān)知識(shí)整理

    摘要:緩存緩存,也叫網(wǎng)關(guān)緩存反向代理緩存。瀏覽器先向網(wǎng)關(guān)發(fā)起請(qǐng)求,網(wǎng)關(guān)服務(wù)器后面對(duì)應(yīng)著一臺(tái)或多臺(tái)負(fù)載均衡源服務(wù)器,會(huì)根據(jù)它們的負(fù)載請(qǐng)求,動(dòng)態(tài)將請(qǐng)求轉(zhuǎn)發(fā)到合適的源服務(wù)器上。雖然這種架構(gòu)負(fù)載均衡源服務(wù)器之間的緩存沒(méi)法共享,但卻擁有更好的處擴(kuò)展性。 一、前言? 工作上遇到一個(gè)這樣的需求,一個(gè)H5頁(yè)面在APP端,如果勾選已讀狀態(tài),則下次打開(kāi)該鏈接,會(huì)跳過(guò)此頁(yè)面。用到了HTML5 的本地存儲(chǔ) API ...

    rickchen 評(píng)論0 收藏0
  • 瀏覽器緩存是什么?它的機(jī)制又是什么?

    摘要:對(duì)于瀏覽器緩存,相信很多開(kāi)發(fā)者對(duì)它真的是又愛(ài)又恨。那么瀏覽器緩存究竟是個(gè)什么樣的神奇玩意呢什么是瀏覽器緩存簡(jiǎn)單來(lái)說(shuō),瀏覽器緩存就是把一個(gè)已經(jīng)請(qǐng)求過(guò)的資源如頁(yè)面,圖片,,數(shù)據(jù)等拷貝一份副本儲(chǔ)存在瀏覽器中。 對(duì)于瀏覽器緩存,相信很多開(kāi)發(fā)者對(duì)它真的是又愛(ài)又恨。一方面極大地提升了用戶體驗(yàn),而另一方面有時(shí)會(huì)因?yàn)樽x取了緩存而展示了錯(cuò)誤的東西,而在開(kāi)發(fā)過(guò)程中千方百計(jì)地想把緩存禁掉。那么瀏覽器緩存究竟...

    jsummer 評(píng)論0 收藏0
  • 瀏覽器緩存是什么?它的機(jī)制又是什么?

    摘要:對(duì)于瀏覽器緩存,相信很多開(kāi)發(fā)者對(duì)它真的是又愛(ài)又恨。那么瀏覽器緩存究竟是個(gè)什么樣的神奇玩意呢什么是瀏覽器緩存簡(jiǎn)單來(lái)說(shuō),瀏覽器緩存就是把一個(gè)已經(jīng)請(qǐng)求過(guò)的資源如頁(yè)面,圖片,,數(shù)據(jù)等拷貝一份副本儲(chǔ)存在瀏覽器中。 對(duì)于瀏覽器緩存,相信很多開(kāi)發(fā)者對(duì)它真的是又愛(ài)又恨。一方面極大地提升了用戶體驗(yàn),而另一方面有時(shí)會(huì)因?yàn)樽x取了緩存而展示了錯(cuò)誤的東西,而在開(kāi)發(fā)過(guò)程中千方百計(jì)地想把緩存禁掉。那么瀏覽器緩存究竟...

    godruoyi 評(píng)論0 收藏0
  • HTTP緩存機(jī)制

    摘要:緩存機(jī)制緩存機(jī)制主要由以下三部分組成緩存存儲(chǔ)策略這個(gè)策略的作用只有一個(gè),用于決定響應(yīng)內(nèi)容是否可緩存到客戶端。如果判斷標(biāo)識(shí)無(wú)效,則返回,用新數(shù)據(jù)替換客戶端緩存。表示文件在本地應(yīng)該緩存,且有效時(shí)長(zhǎng)是秒從發(fā)出請(qǐng)求算起。 HTTP緩存機(jī)制 HTTP緩存機(jī)制主要由以下三部分組成 緩存存儲(chǔ)策略 這個(gè)策略的作用只有一個(gè),用于決定 Http 響應(yīng)內(nèi)容是否可緩存到客戶端。主要通過(guò)Cache-Contro...

    huangjinnan 評(píng)論0 收藏0
  • 瀏覽器緩存機(jī)制學(xué)習(xí)總結(jié)

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

    JiaXinYi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<