为什么使用浏览器缓存
互联网应用系统,在高并发的情况下,都会使用缓存,例如:浏览器缓存,CDN缓存,Nginx反向代理缓存,应用多级缓存,以及数据库缓存等等,如下

缓存的目的是为了让数据离用户更近,使用户能够以最快的速度获取到数据同时降低对后端系统压力,今天我们将介绍,离用户最近的缓存,浏览器缓存的使用,浏览器缓存依赖于,Http协议规范,可在响应头(Reponse Header)声明缓存策略
缓存请求
浏览器缓存请求到本地,需要解决一个问题,即缓存如何更新,因为内容是由web服务器更新,却存在于本地浏览器,所以他们之间必须建立起一种沟通机制,即HTTP“缓存协商”
浏览器如何协商缓存?首先服务端响应头(Reponse Header)会返回Last-Modified,如下:
Last-Modified:Sun, 07 May 2017 07:34:12 GMT
浏览器下次请求,请求头(Request Header)将带上
If-Modified-Since:Sun, 07 May 2017 07:34:12 GMT
这样浏览器根据返回的时间,确认请求内容是否更新,如果没有更新则返回状态码HTTP 304,告诉浏览器Not Modified可直接使用本地缓存,下面以java代码来实现如下
@RequestMapping("/cache")
public ResponseEntity cache(@RequestHeader(value = "If-Modified-Since", required = false) Date modifiedSence, HttpServletResponse response) {
//缓存1天
long nowTime = new Date().getTime();
if(modifiedSence!=null) {
long expireTime = modifiedSence.getTime() + 24 * 3600 * 1000;
//未过期
if (nowTime<expireTime) {
return new ResponseEntity("cached", HttpStatus.NOT_MODIFIED);
}
}
response.setDateHeader("Last-Modified", nowTime);
return new ResponseEntity("not cache", HttpStatus.OK);
}
还有一种协商策略基于请求头的ETag,如:ETag:W/"590ecdf4-1a6",服务器端比对资源的Etag,确定资源是否变更
消灭请求
跟据上节所讲,浏览器会发送请求到服务器检查缓存是否有更新,在大多数场景下面,这样依然能够提高服务器的性能以及吞吐率,能否彻底消灭不必要的请求呢?答案是可以的,只需要标记Expires过期时间,下面将以nginx(1.10+版本),chrome(测试浏览器)作为示例
# 针对url http://localhost:8080/hello/ 下面所有文件做缓存处理,缓存两天
location ^~ /hello/ {
expires 20d;
}
访问则浏览器会响应头(Reponse Header),会携带如下信息
Cache-Control:max-age=1728000
ETag:W/"590ecfcb-fb"
Expires:Sat, 27 May 2017 07:43:20 GMT # 日期可能不同
Last-Modified:Sun, 07 May 2017 07:42:03 GMT #日期可能不同
Expires说明,缓存起作用了,但是Expires会存在一个问题,即来自于web服务器的时间可能和本地时间不一致,会影响到本地缓存的有效性检查
Cache-Control可弥补Expires的不足,max-age直接指定了缓存过期的相对时间,这个时间是相对于浏览器本地的时间
再次请求点击浏览器刷新按钮,监视到请求返回到状态码是
Status Code:304 Not Modified
缓存没有起作用,还是发起了请求,这里表示很奇怪,网上查找资料,发现其实浏览器针对刷新请求响应行为如下

知道了浏览器的属性,我们可以模拟常用场景,从一个页面B跳转到我们需要测试页面A的,发现成功了,浏览器没有发起请求,如下
Status Code:200 OK (from disk cache)
如何使用浏览器缓存
一般情况下针对不同的场景,采取不同的缓存策略
1、站点的静态资源请求最适合使用浏览器缓存,这样能减轻服务器的压力,降低出口带宽压力
2、动态请求一般依据策略区分,写请求自然不会缓存,针对读请求,则看场景是否对一致性要求比较高,例如:页面上的新闻列表,可缓存下来,每隔n分钟刷新一次
参考文档
[1] 构建高性能web站点 郭欣著
[2] Spring官方文档
示例
[1] http-cache
网友评论