node.js的学习(三) http缓存原理

http 缓存

浏览器缓存的做用

合理使用浏览器的缓存,能够有效的减小请求的访问次数,一个是减少服务器压力,更重要的是可以下降页面的加载时间。html

搭建缓存基本测试环境

function updateTime() {
    setInterval(()=>{
        this.time = new Date().toUTCString()
    },1000)
    return this.time 
}

const http = require('http')
http.createServer((req,res)=>{
 const {url} = req
 if('/'===url){
     console.log('111')
     res.end(`
     <html>
     html update ${updateTime()}
     <script src='main.js'></script>
     </html>
     `)
 }else if(url==='/main.js'){
     console.log('222')
     const content = ` 
        document.writeln('<br> JS update time : ${updateTime()}')
     `
     res.statusCode = 200
     res.end(content)
 }else if(url==='/favicon.ico'){
    res.end('')
 }
}).listen(3000,()=>{
    console.log("服务建立成功")
})
复制代码

强缓存

  1. http1.0中 Expires 字段。控制多少秒后资源过时
function updateTime() {
    setInterval(()=>{
        this.time = new Date().toUTCString()
    },1000)
    return this.time 
}

const http = require('http')
http.createServer((req,res)=>{
 const {url} = req
 if('/'===url){
     res.end(`
     <html>
     html update ${updateTime()}
     <script src='main.js'></script>
     </html>
     `)
 }else if(url==='/main.js'){
     res.setHeader('Expires',new Date(Date.now()+10*1000).toUTCString())
     const content = ` 
        document.writeln('<br> JS update time : ${updateTime()}')
     `
     res.statusCode = 200
     res.end(content)
 }else if(url==='/favicon.ico'){
    res.end('')
 }
}).listen(3000,()=>{
    console.log("服务建立成功")
})
复制代码

当请求资源的时候,会把客户端的时间和expires的时间进行对比,若是大于该时间,就过时,不然就直接使用该缓存资源
可是存在一个问题。客户端的时间是能够自行修改的,或者存在客户端的时间和服务端的时间不一致,因此不必定知足预期的效果后端

针对上述问题 2. 在http1.1 中 使用 Cache-Control浏览器

function updateTime() {
    setInterval(()=>{
        this.time = new Date().toUTCString()
    },1000)
    return this.time 
}

const http = require('http')
http.createServer((req,res)=>{
 const {url} = req
 if('/'===url){
     res.end(`
     <html>
     html update ${updateTime()}
     <script src='main.js'></script>
     </html>
     `)
 }else if(url==='/main.js'){
     res.setHeader('Expires',new Date(Date.now()+10*1000).toUTCString())
     res.setHeader('Cache-Control','max-age=20')
     const content = ` 
        document.writeln('<br> JS update time : ${updateTime()}')
     `
     res.statusCode = 200
     res.end(content)
 }else if(url==='/favicon.ico'){
    res.end('')
 }
}).listen(3000,()=>{
    console.log("服务建立成功")
})
复制代码

Cache-Control 是优先级别高于 Expires缓存

协商缓存

上述的expires和cache-control都会访问本地缓存直接验证看是否过时,若是没过时就走缓存,而且返回200。
可是若是设置了no-cache和no-store就会忽略本地缓存,会去请求服务器资源是否更新,若是没有更新就继续使用本地缓存,此时返回304,着就是协商缓存,协商缓存的主要包括last-modified和etag
协商缓存就是在浏览器和服务器中是否作缓存进行协商,若是协商的结果是须要更新,就会返回200并更新内容,若是不须要,就返回304,不返回内容,虽而后端仍然要应答,可是不用生成内容,也不用传输内容。服务器

  1. 根据时间
function updateTime() {
    setInterval(()=>{
        this.time = new Date().toUTCString()
    },1000)
    return this.time 
}

const http = require('http')
http.createServer((req,res)=>{
 const {url} = req
 if('/'===url){
     res.end(`
     <html>
     html update ${updateTime()}
     <script src='main.js'></script>
     </html>
     `)
 }else if(url==='/main.js'){
    //  res.setHeader('Expires',new Date(Date.now()+10*1000).toUTCString())
    //  res.setHeader('Cache-Control','max-age=20')
    res.setHeader('Cache-Control','no-cache')  // 不走强缓存
    res.setHeader('last-modified',new Date().toUTCString())
    if( new Date(req.headers['if-modified-since']).getTime()+3*1000>Date.now()){
        console.log("协商缓存命中")
        res.statusCode=304
        res.end()
        return 
    }

     const content = ` 
        document.writeln('<br> JS update time : ${updateTime()}')
     `
     res.statusCode = 200
     res.end(content)
 }else if(url==='/favicon.ico'){
    res.end('')
 }
}).listen(3000,()=>{
    console.log("服务建立成功")
})
复制代码
  1. 根据内容hash 利用Etag
function updateTime() {
  this.timer=this.timer||  setInterval(()=>{
        this.time = new Date().toUTCString()
    },5000)
    return this.time 
}

const http = require('http')
http.createServer((req,res)=>{
 const {url} = req
 if('/'===url){
     res.end(`
     <html>
     html update ${updateTime()}
     <script src='main.js'></script>
     </html>
     `)
 }else if(url==='/main.js'){
    const content = ` 
    document.writeln('<br> JS update time : ${updateTime()}')
 `
    res.setHeader('Cache-Control','no-cache')  // 不走强缓存
   const crypto = require('crypto')
   const hash = crypto.createHash('sha1').update(content).digest('hex')
   res.setHeader('Etag',hash)
   if(req.headers['if-none-match']===hash){
       console.log('缓存命中')
       res.statusCode = 304
       res.end()
       return 
   }

    
     res.statusCode = 200
     res.end(content)
 }else if(url==='/favicon.ico'){
    res.end('')
 }
}).listen(3000,()=>{
    console.log("服务建立成功")
})
复制代码
相关文章
相关标签/搜索