HTTP缓存
一、为什么要有缓存?
假设我们对服务器进行一次请求,HTTP请求头大小1K,HTTP响应头大小1K,请求的文件大小10K,那么一次请求完毕后总的流量大小就是12K,那么n次请求就有n*12K的流量,实际上一次请求消耗的流量会更多,访问一个页面时需要加载如css、js、图片等静态资源,如果没有缓存,那么每次重新访问该页面,就要去请求一次服务器,浪费很多流量,客户端每次请求完,又得重新进行页面渲染,用户体验也也不好,对于服务器,如果需要提供文件查找、下载服务,请求基数过大时,对服务器也会造成很大的压力
——所以就有了HTTP缓存:HTTP缓存主要针对更新频率不高的一些静态文件如CSS样式、JS脚本、图片等,而不是缓存某一个HTTP响应
二、HTTP缓存工作原理
HTTP协议里一般通过请求头、响应头来实现缓存
与缓存有关的头部字段
1.Cache-Control
——请求、响应头的缓存控制字段
值 | 描述 |
---|
no-store | 所有内容都不缓存 | no-cache | 缓存,但是浏览器使用缓存前,都会请求服务器判断缓存资源是否更新 | max-age=x(单位:秒) | 请求缓存后的x秒都不需要再发起请求 | s-maxage=x(单位:秒) | 代理服务器请求原始服务器缓存后的x秒不需要再发起请求,只对CDN缓存有效 | public | 客户端和代理服务器(CDN)都可缓存 | private | 只有客户端可以缓存 |
2.Expires
——响应头字段,代表资源过期时间,由服务器返回提供,是http1.0的属性,与max-age共存时,优先级要更低
工作原理:服务器与客户端约定一个文件过期时间——Expires,服务器返回资源的同时,通过响应头返回一个约定时间Expires,客户端后续请求时,会先对比当前时间是否大于Expires,若没过期,则直接使用本地缓存的该资源,若已过期,则重新向服务器请求该资源,服务器返回资源同时返回刷新后的Expires
缺陷:若Expires过期时间到了,但资源文件实际上并没有更新,这样再次请求也就多余了,怎样避免呢?看下面if-Modified-Since与Last-Modified
3.if-Modified-Since与Last-Modified
——if-Modified-Since是请求头的字段,资源的最新修改时间,由客户端告诉服务器(即上一次服务器给的资源修改时间) ——Last-Modified是响应头的字段,资源的最新修改时间,由服务器告诉客户端 它俩是一对,配合工作,会进行对比
工作原理:在服务器提供Expires过期时间的基础上,服务器再提供一个Last-Modified(资源的最新修改时间),即客户端请求资源时,会保存服务器返回的Expires与Last-Modified(客户端保存后将该字段命名为if-Modified-Since),后续请求时,客户端首先会根据Expires过期时间来判断是否重新发起请求,若过期了,则客户端重新发起请求并通过请求头带上if-Modified-Since,服务器先对比if-Modified-Since与Last-Modified,若不相等,则服务器重新返回最新的资源文件,同时通过响应头返回刷新后的Expires与刷新后的Last-Modified,若相等,则服务器返回304状态码,告诉客户端可以继续使用自己之前的本地缓存资源
缺陷:首先,客户端可以随意修改Expires,这个字段不太稳定,同时,Last-Modified只能精确到秒,这在一些比较极端的情况下,文件的修改可能在毫秒级发生(如淘宝,每一秒甚至毫秒都有不同的人在访问),这时候,文件在任意时间被修改,Last-Modified就无法感知资源文件的变化,这样就会使总有一部分客户端永远无法获取到最新的资源文件(因为文件修改在毫秒内发生,Last-Modified没有精确到毫秒,所以一对比发现if-Modified-Since与Last-Modified相等) 怎样解决呢?看下面if-None-Match与Etag
4.if-None-Match与Etag ——if-None-Match是请求头的字段,缓存资源标识,由客户端告诉服务器(即上一次服务器给的Etag) ——Etag是响应头的字段,资源标识,由服务器告诉客户端 它俩也是一对,配合工作,会进行对比
工作原理:在Expires、Last-Modified的机制基础上,再加上一对标记if-None-Match与Etag(资源内容唯一标记),由于Expires的不稳定,使用max-age代替之(Cache-Control字段中的一个值,优先级比Expires高),即客户端请求后,服务器会返回如max-age=60秒、Last-Modified以及Etag,客户端保存为if-Modified-Since、if-None-Match,60秒内,客户端不会再发起对该资源的请求,60秒后,这时候,服务器不会再对比if-Modified-Since与Last-Modified,只会对比if-None-Match与Etag是否相等(因为if-None-Match与Etag更精准、优先级更高),若相等则服务器返回304,若不相等,则服务器会返回刷新后的max-age、Etag、Expires、Last-Modified(Expires与Last-Modified虽然不用了,但也会返回)
三、HTTP缓存的缺陷及改进
以上HTTP协议通过头部字段控制缓存都有一个缺陷,那就是Expires、max-age过期时间内,若文件发送修改,都无法感知到
解决方案:
md5/hash标识资源
HTTP请求资源时,都是通过文件路径全名来请求的,即假如资源名发生变化了,就会认为是请求了另一个不同的资源,所以每一次资源发生迭代、修改,都添加md5或者hash标识,这样再次请求时,服务器会认为是请求了不同资源,会直接将该资源返回,也就不存在判断缓存是否需要更新这些环节了,就可以跳过Expires、max-age过期时间的限制
四、CDN缓存
CDN是构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户可以就近获取所需资源,降低网络拥塞,提供用户访问响应速度和命中率
CDN即是一种代理服务器,可以理解为浏览器与服务器之间的临时站点,会替服务器阻挡(处理)一部分浏览器的请求,减轻原始服务器的压力,CDN代理服务器上缓存了浏览器请求的一些静态资源(前面Cache-Control头部字段值为public的资源),浏览器就可以就近请求,以达到分流、加速响应的目的
CDN工作方式:客户端请求资源时,请求会先到CDN节点,CDN判断自己缓存的文件是否过期,若没过期,则返回304给客户端,若过期了,则向原始服务器请求最新资源,再返回最新资源给客户端
缺陷:CDN缓存问题与HTTP缓存问题是一样的,过期时间内资源发生了修改,浏览器始终被拦截,无法获取最新资源
优点:虽然有以上缓存问题,但是缓存主要针对的是更新频率不高的资源,同时它提供了分流、访问响应加速的优点,它是一个平台,可以登录后手动修改缓存的资源,变相解决了浏览器缓存无法手动控制的问题
五、浏览器操作对HTTP缓存的影响
用户操作 | Expires/Cache-Control:max-age=x | Last-Modified/Etag |
---|
地址栏回车 | 有效 | 有效 | 页面链接跳转 | 有效 | 有效 | 新开窗口 | 有效 | 有效 | 浏览器的前进、后退按钮 | 有效 | 有效 | F5刷新/浏览器刷新按钮 | 无效 | 有效 | Ctrl+F5刷新 | 无效 | 无效 |
有效:表示客户端请求资源时,Expires/Cache-Control:max-age=x 、 Last-Modified/Etag缓存机制会起作用,判断缓存是否过期,考虑是否向服务器发起请求、服务器是否重新返回资源
无效:表示忽略该机制,F5刷新/浏览器刷新按钮会忽略缓存时间是否到期,但是浏览器还是会判断Last-Modified/Etag考虑是否重新返回资源,Ctrl+F5刷新为强制请求,所有缓存资源都不使用,全部重新加载
|