当前位置: 首页 > 后端技术 > Node.js

http缓存简介

时间:2023-04-03 11:07:47 Node.js

1.缓存的作用是减少网络流量传输,提高页面渲染速度,减轻服务器负担,提高网站性能可以提高网站加载速度,提高网站性能。服务器将资源内容和缓存ID返回给客户端,客户端将它们备份到缓存数据库中。以后每次使用资源,都需要用缓存ID去请求服务器。服务器根据请求中携带的缓存标识判断资源是否过期。如果过期,则直接返回资源内容和新的缓存标识。如果没有过期,则返回状态码304,通知客户端缓存数据库中的数据如果没有失效就可以使用。与缓存相比,缓存与缓存失效相比并不失效。当服务器响应缓存标识符的最后修改时间时,在响应头中添加Last-Modified,告诉客户端这个资源的最后修改时间。If-Modified-Since:在浏览器中再次发起当请求发现资源有Last-Modified属性时,会自动在请求头中添加If-Modified-Since。如果服务器在收到请求后找到头部If-Modified-Since,则将Last-Modified的值与请求资源的最后修改时间进行比较。如果上次修改时间较新,说明该资源又被修改过,响应最新的资源内容,返回200状态码;如果最后修改时间与If-Modified-Since相同,表示资源没有被修改,则响应304表示没有更新。告诉浏览器继续使用保存的缓存文件。Last-Modified的问题有些服务器无法准确获取资源的最后修改时间,因此无法通过最后修改时间进行更新。对于频繁修改的资源,更新时间在秒级以下,Last-Modified的更新时间只能是准确的。到了秒,有些文件的最后修改时间发生了变化,但内容没有。我们不希望客户认为此文件已被修改。如果同一个文件位于多个CDN服务器上,虽然内容相同,但修改时间不同。代码实现lethttp=require('http');letfs=require('fs');letpath=require('path');letmime=require('mime');http.createServer(function(req,res){letfile=path.join(__dirname,req.url);fs.stat(file,(err,stat)=>{if(err){sendError(err,req,res,file,stat);}else{letifModifiedSince=req.headers['if-modified-since'];if(ifModifiedSince){if(ifModifiedSince==stat.ctime.toGMTString()){res.writeHead(304);res.end();}}else{send(req,res,file,stat);}}else{send(req,res,file,stat);}}});}).listen(8080);functionsend(req,res,file,stat){res.setHeader('Last-Modified',stat.ctime.toGMTString());res.writeHead(200,{'Content-Type':mime.getType(file)});fs.createReadStream(file).pipe(res);}函数sendError(err,req,res,file,stat){res.writeHead(400,{"Content-Type":'text/html'});res.end(err?err.toString():"NotFound");}ETagETag是根据实体内容生成的哈希字符串,可以作为资源内容的唯一表示。当资源改变时,ETag也会改变。ETag由Web服务器生成并发送给浏览器客户端。如果客户端要判断缓存是否可用,可以先获取缓存中文档的ETag,然后通过If-None-Match向Web服务器发送请求,询问缓存是否可用。服务器收到请求,将服务器中这个文件的ETag与请求头中的If-None-Match进行比较。如果值相同,说明缓存还是最新的,web服务器会发送一个304NotModified响应码给客户端,表示缓存没有被修改,可以使用.如果不相同,Web服务器将把最新版本的文档发送给浏览器客户端。Etag的缺点是服务器每次都需要计算资源的hash值,消耗服务器资源代码实现lethttp=require('http');让fs=require('fs');让path=require('path');让mime=require('mime');让crypto=require('crypto');http.createServer(function(req,res){letfile=path.join(__dirname,req.url);fs.stat(file,(err,stat)=>{if(err){sendError(err,req,res,file,stat);}else{让ifNoneMatch=req.headers['if-none-match'];让etag=crypto.createHash('sha1').update(stat.ctime.toGMTString()+stat.size).digest('hex');if(ifNoneMatch){if(ifNoneMatch==etag){res.writeHead(304);res.end();}else{send(req,res,file,etag);}}else{send(req,res,文件,etag);}}});}).listen(8080);functionsend(req,res,file,etag){res.setHeader('ETag',etag);res.writeHead(200,{'Content-Type':mime.lookup(file)});fs.createReadStream(file).pipe(res);}functionsendError(err,req,res,file,etag){res.writeHead(400,{"Content-Type":'text/html'});res.end(err?err.toString():"NotFound");}forcecaching强制缓存,当本地缓存不失效时,直接使用本地缓存,不与服务器交互缓存未过期,缓存已过期,缓存标志表示浏览器会将文件缓存到Cache目录。当第二次请求时,浏览器会先检查该文件是否包含在Cache目录中。如果没有过期,那么此时浏览器会直接从Cache目录中读取文件,不再发送请求。Expires是服务器响应消息的头字段。当响应一个http请求时,它告诉浏览器在过期时间之前,浏览器可以直接从浏览器读取文件。这是HTTP1.0的内容。现在浏览器默认使用HTTP1.1,所以基本上可以忽略Cache-Control和Expires的作用。它们都表示当前资源的有效期,控制浏览。浏览器是直接从浏览器缓存中取数据,还是重新向服务器发送请求取数据。如果同时设置,则其优先级高于Expiresprivate。客户端可以缓存公共客户端和代理服务器。max-age=6060秒后缓存的内容将是Invalidno-cache需要使用比对缓存来校验数据,强制源服务器再次校验no-store所有内容都不会被缓存,也不会强制缓存和对比缓存都会触发Cache-Control:private,max-age=60,无缓存代码实现lethttp=require('http');letfs=require('fs');letpath=require('path');letmime=require('mime');letcrypto=require('crypto');http.createServer(function(req,res){letfile=path.join(__dirname,req.url);console.log(file);fs.stat(file,(err,stat)=>{if(err){sendError(err,req,res,file,stat);}else{send(req,res,file);}});}).listen(8080);functionsend(req,res,file){让前pires=newDate(Date.now()+60*1000);res.setHeader('Expires',expires.toUTCString());res.setHeader('Cache-Control','max-age=60');res.writeHead(200,{'Content-Type':mime.lookup(file)});fs.createReadStream(file).pipe(res);}functionsendError(err,req,res,file,etag){res.writeHead(400,{"Content-Type":'text/html'});res.end(错误?err.toString():“未找到”);}