关于HTTP协议中的缓存概念

关于HTTP协议中的缓存概念

一、HTTP协议缓存的概念
当我们通过浏览器向一个WEB服务器发起请求时,服务器会有一个较复杂的处理过程。为了降低服务器的负载,服务器并不是每次都会按我们的请求从磁盘上读取页面内容,然后将这些内容返回给浏览器供我们浏览。那么服务器如何在并发请求特别大时还能保持响应水准呢?为了解决这一问题,http协议引进了缓存标准,而apache httpd服务器实现了http协议的缓存标准。 缓存不仅仅是在服务器端,也包括请求客户端 。目前的主流浏览器也都实现了客户端缓存这一功能。当浏览器输入网址时大致可能流程是:如果服务器页面的内容没有更新,浏览器将把本地缓存的内容给用户,根本就不用请求服务器。如果客户端缓存内容过期了,浏览器发送了一个请求给服务器,这时,服务器还可以进一步判断请求的页面内容是否有更改,如果没有更改,也不用进行磁盘操作去读取页面内容,而是直接返回一个特殊的状态码给客户端,客户端收到这个状态码后就直接取本地的缓存展现给用户浏览。总之,如上所述客户端与服务器端对页面进行的一系列处理,为的就是减少请求量,减少数据传输量,达到降低服务器负载,加快响应速度的目的。下面我将通过服务器缓存和浏览器缓存两方面来进行阐述。
二、服务端缓存
        服务端缓存建立在磁盘和内存上,它可以在用户请求动态页面(如 http://eggs.cn/cgi.php?arg= 123)时,这可以为用户省下代码逻辑处理的时间。同时因为服务器端也可以把文件存储在内存中,当用户频繁的请求同一页面时,其实服务器也是通过内存直接将内容取出供用户浏览的。
在httpd.conf配置文件内增加以下内容,就可实现简单的服务器缓存控制。
CacheEnable disk /
CacheRoot '/var/apache/cache'
CacheDirLevels 2
CacheDirLength 1
其中:
CacheRoot表示缓存文件的根目录,所有的缓存文件都将在此目录下;
CacheDirLevels表示缓存文件根目录下的子目录深度,这里为2代表/var/ apache/cache 下有2级子目录,2级子目录下才是缓存文件;
CacheDirLength表示缓存子目录名字长度,这里为1;
所以我们的缓存子目录将有可能为/var/apache/cache/Y/x这样,那/var/apache/cache/Y/x这里面就是我们的缓存文件了。每一个类似/var/apache/cache/Y/x这种目录就对应一个URL的缓存文件,缓存文件的命名由22个字符组成,通常后缀为.data与.header,.data里存储的就是页面的内容,比如"hello world",.header里存储的为此url的请求头与响应头内容。
服务器的缓存时间是通过Cache-Control标记里的max-age值来比较的,当客户端请求的间隔时间超过了上一次服务器返回头信息中的max-age值时,服务器将不会从缓存目录内取缓存内容给客户端。如 Cache-Control: max-age 这个标记是服务器缓存有效期时间,如果客户端在30秒内再次请求同一页面,服务器将使用缓存数据响应客户端。
二、浏览器缓存
浏览器的缓存主要包括两种缓存:强缓存、验证缓存。
1. 强缓存
强缓存是指浏览器不与服务器进行任何交互请求,直接将浏览器的缓存数据(包括缓存数据的 Response 头信息)返回给用户。这种缓存给用户的响应是最快的,但同时也是风险性较高的。因为该类缓存没有进行任何的校验即直接反馈给用户,是可能存在有历史的脏数据。当浏览器的请求出现如下现象时该次请求就是强缓存:
(1)浏览器返回200 (From Cache);   
(2)请求 Response 头中的 Date 字段所表示的时间小于当前时间:                                
强缓存主要是受 Cache-Control:max-age 和 Expires 头两个 Http 响应头控制的。 Cache-Control 头和 Expires 头都是都是缓存数据的有效期的信息。只不过 HTTP/1.0+ 的 Expires 头是采用的绝对 GMT 时间,而 HTTP/1.1 的 Cache-Control:max-age 则是采用的相对时间进行存储。如: Cache-Control: max-age=30 这个标记是服务器缓存有效期时间,如果客户端在30秒内再次请求同一页面,服务器将使用缓存数据响应客户端。
在实际使用中我们更倾向于使用 Cache-Control:max-age 头,因为 Expires 头记录的是服务器端设置的绝对时间;如果客户端与服务器之间的时间差别较大的话可能会导致有偏差;并且当 Cache-Control:max-age 和 Expires 头同时存在的情况下, Cache-Control 头将覆盖 Expires 头。当请求发起的时间仍然在 Cache-Control 或者 Expires 设置的有效期内的话则将直接读取缓存数据。
2. 验证缓存
验证缓存(又叫协商缓存)是指浏览器根据缓存资源的 Last-Modified 字段和 Etag 字段得到 If-Modified-Since 和 If-None-Match 字段加入 Request 头中向服务器进行验证源站服务器的资源是否有更新过,如果服务器端收到该请求并且发现服务器端资源没有进行变更即会返回 304 Not Modified 响应头。如下所示为一次标准的304请求:
- 请求标头
Request Headers
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
If-Modified-Since: Sat, 24 Feb 2018 16:05:16 GMT
If-None-Match: "30686be-13d-565f77150c700"
-响应标头
Response Headers
Request URL: http://www.xyz.com/js/common/systemDate_global.js
Request Method: GET
Status Code: 304 Not Modified
Remote Address: 222.73.229.73:80
Connection: Keep-Alive
Date: Sun, 25 Feb 2018 08:00:07 GMT
ETag: "30686be-13d-565f77150c700"
Keep-Alive: timeout=10, max=99
Server: IBM_HTTP_Server
下面着重介绍一下Last-Modifed、If-Modifed-Since、ETag等几个重点请求参数:
Last-Modified / If-Modified-Since :在客户端第一次向服务器端发起请求时,服务器返回数据并置状态码为200,同时将该文件最后修改的 GMT 时间记录在 Last-Modified 头中返回客户端。下次客户端请求验证缓存数据时就会将缓存数据中的 Last-Modified 字段作为请求头中的 If-Modified-Since 字段向服务器端询问在该时间点后服务器的文件是否有做过更新,如果没有更新即返回 304 Not Modified 响应头并读取缓存数据,而如果服务器文件该时间点后更新过则需要重新将服务器的文件传输给客户端并返回200状态码,同时该文件的 Last-Modified 时间也将是服务器文件现在更新的时间。
Etag / If-None-Match : HTTP 协议规格说明定义 ETag 为“被请求变量的实体值”。另一种解释是, ETag 是一个可以与 Web 资源关联的记号(token)。 HTTP/1.1 并没有要求具体 ETag 中间需要存放什么内容或者实现方法,有一些 ETag 是通过文件资源的 MD5 值来进行标识的,与 Last-Modified 一样也是判断服务器文件是否有做过更新,其验证过程也是将上次缓存数据中的 ETag作为请求头中的 If-None-Match 头向服务器验证服务器文件的 ETag 是否更新过。 ETag 验证主要解决以下几点 Last-Modified 无法解决的问题:
  1. 网站文件周期性更新但并不改变文件内容(仅修改 Last-Modified 时间),对于这些文件仍然希望可以使用缓存数据;
  2. 网站文件更新频率较快,小于秒级的更新频率通过 Last-Modified 无法识别;
  3. 服务器无法准确得到 Last-Modified 时间,需要 ETag 标识文件。
简单总结一下验证缓存,验证缓存304 是将本地缓存的 Last-Modified 和 ETag 与服务器端进行校验,因此验证缓存相比于强缓存不会出现读取本地脏数据的情况,而验证缓存的请求时间相比于强缓存较慢,而相比于完整获取服务器端的文件是较小的,因此比直接获取源文件更高效。
三、浏览器行为对缓存的影响
浏览器有多种刷新行为可以影响下次请求对缓存数据的行为,并且不同的浏览器对于同样的刷新操作也有不同的情况。究其根本原因都是浏览器在发起请求的时候所带的 Catch-Control 的头信息来决定的。如浏览器下列请求头的含义如下:
Cache-Control:max-age=0,表示浏览器将忽略强缓存的数据而直接获取验证缓存的数据,对应Chrome浏览器的刷新请求操作。
Cache-Control:no-cache ,表示浏览器将忽略强缓存和验证缓存直接获取服务器的数据,对应chrome浏览器的ctrl+F5。
四、浏览器发送请求时使用缓存的过程总结
(1)当浏览器向服务器端发送请求的时候首先查看本地浏览器缓存数据中是否有缓存数据,如果没有缓存数据则会向 Web 服务器(这里的 Web 服务器是广义的概念,有可能是 CDN 等缓存数据)请求对应的数据并将获取的响应数据以及一些对应的 Response 头信息缓存到本地(包括 Expires 、Cache-Control 等头信息),如果有缓存数据则执行(2);
(2)当本地有缓存数据并且 Request 头中没有设置 Cache-Control:no-cache 和 Cache-Control:max-age=0 头信息的话就需要查看该缓存的 Cache-Control 头和 Expires 头查看该缓存数据是否新鲜,如果没有过期则直接读取强缓存数据返回给浏览器,返回状态码 200(From Cache) 。如果有设置上述的两个 Cache-Control 头或者强缓存数据已经过期则执行(3);
(3)如果请求头中没有 Cache-Control:no-cache 头信息的话则客户端带着 If-Modified-Since 和 If-None-Match 参数向服务器发起验证,如果服务器端验证发现没有进行更新的话则直接返回 304 Not Modified 头和本地的缓存数据返回给客户端。如果请求头带了 Cache-Control:no-cache 或者源站做了更新则执行(4);
(4)如果请求头中有 Cache-Control:no-cache 或者验证缓存校验发现源站数据更新了,则需要从服务器重新获取数据并将其存入浏览器缓存并返回200状态码。
示意图如下:

五、CDN加速对缓存的可能影响                        
  1. 添加CDN 加速源站后,客户端访问出现历史脏数据。由于添加 CDN 后浏览器到服务器端可能出现缓存的就是浏览器缓存、CDN 缓存,因此需要清楚两处的缓存后测试是否正常,如果仍然获取到脏数据有可能出现劫持的情况导致的,用户可以通过查看响应头中是否有出现 301 或者 302 的状态码查看。
  2. CDN 可以设置响应 HTTP 头中的 Cache-Control 和 Expires 头,这两个头与 HTTP 标准协议一致的设置方法: Cache-Control 可以设置相对时间,而 Expires 仅能够设置绝对 GMT 时间。在 CDN 上设置的 Cache-Control 和 Expires 头将仅影响浏览器缓存,并不影响 CDN 缓存策略。 CDN 的缓存策略需要源站的 Cache-Control 和 Expires 头决定。
  3. 当源站响应头中设置了如下的缓存策略 CDN 和浏览器都将认为是源站不允许缓存而不进行缓存:
  • Cache-Control为no-cache,no-store,private
  • Cache-Control为max-age=0
  • Pragma为no-cache             
六:参考
[1]Hypertext Transfer Protocol HTTP/1.1:  https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
[2]缓存系列——浏览器缓存协商 :  http://blog.csdn.net/chosen0ne/article/details/7344189
[3]http协商缓存VS强缓存:  http://www.cnblogs.com/wonyun/p/5524617.html
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值