今天遇到一个的同事问为什么文件改了,但是浏览器的响应并没有改变,我说,清一下缓存。后来我想想,我还是写一个来专门描述HTTP的缓存原理
1. 简介
简单点说,就是当Web请求抵达缓存时, 如果本地有已缓存的副本,就可以从本地存储设备而不是从原始服务器中提取这个文档。这样设计的好处有:
- 减少了冗余的数据传输,节省了网络流量。
- 减少了服务器的负担, 大大提高了网站的性能
- 加快了客户端加载网页的速度
总之,就是减少请求
2. 如何判断缓存是否需要更新
Web服务器通过2种方式来判断浏览器缓存是否是最新的。
-
浏览器把缓存文件的最后修改时间Last-Modified 通过 header ”If-Modified-Since“来告诉Web服务器。
-
浏览器把缓存文件的ETag, 通过header “If-None-Match”, 来告诉Web服务器。
Last-Modified/If-Modified-Since
Last-Modified/If-Modified-Since要配合Cache-Control使用。
Last-Modified:标示这个响应资源的最后修改时间。web服务器在响应请求时,告诉浏览器资源的最后修改时间。
If-Modified-Since:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Last-Modified声明,则再次向web服务器请求时带上头 If-Modified-Since,表示请求时间。web服务器收到请求后发现有头If-Modified-Since 则与被请求资源的最后修改时间进行比对。若最后修改时间较新,说明资源又被改动过,则响应整片资源内容(写在响应消息包体内),HTTP 200;若最后修改时间较旧,说明资源无新修改,则响应HTTP 304 (无需包体,节省浏览),告知浏览器继续使用所保存的cache。
Etag/If-None-Match
Etag/If-None-Match也要配合Cache-Control使用。
Etag:web服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器觉得)。Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。
If-None-Match:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Etage声明,则再次向web服务器请求时带上头If-None-Match (Etag的值)。web服务器收到请求后发现有头If-None-Match 则与被请求资源的相应校验串进行比对,决定返回200或304。
为什么使用ETag呢?
主要是为了解决Last-Modified 无法解决的一些问题。
-
某些服务器不能精确得到文件的最后修改时间, 这样就无法通过最后修改时间来判断文件是否更新了。
-
某些文件的修改非常频繁,在秒以下的时间内进行修改. Last-Modified只能精确到秒。
-
一些文件的最后修改时间改变了,但是内容并未改变。 我们不希望客户端认为这个文件修改了。
与缓存有关的header
-
request
- Cache-Control: max-age=0 以秒为单位
- If-Modified-Since: Mon, 19 Nov 2012 08:38:01 GMT 缓存文件的最后修改时间。
- If-None-Match: “0693f67a67cc1:0” 缓存文件的Etag值
- Cache-Control: no-cache 不使用缓存
- Pragma: no-cache 不使用缓存
-
response
- Cache-Control: public 响应被缓存,并且在多用户间共享
- Cache-Control: private 响应只能作为私有缓存,不能在用户之间共享
- Cache-Control:no-cache 提醒浏览器要从服务器提取文档进行验证
- Cache-Control:no-store 绝对禁止缓存(用于机密,敏感文件)
- Cache-Control: max-age=60 60秒之后缓存过期(相对时间)
- Date: Mon, 19 Nov 2012 08:39:00 GMT 当前response发送的时间
- Expires: Mon, 19 Nov 2012 08:40:01 GMT 缓存过期的时间(绝对时间)
- Last-Modified: Mon, 19 Nov 2012 08:38:01 GMT 服务器端文件的最后修改时间
- ETag: “20b1add7ec1cd1:0” 服务器端文件的Etag值
网友评论