乐趣区

浅谈HTTP缓存机制

前言

HTTP缓存不管是在面试中,还是实际开发中都是重中之重。了解 HTTP 缓存不仅可以轻松自如应对面试,而且也是在实际开发中对性能优化不可或缺的手段。

缓存分类

浏览器第一次请求资源时,必须请求所有的资源,然后根据响应的 header 内容来决定,如何缓存资源。一般而言缓存可以分为强缓存和协商缓存两种。

强缓存

当客户端缓存所要请求的数据时。客户端直接从缓存数据获取数据。当客户端没有缓存所请求的数据时,客户端的才会从服务端获取数据。

协商缓存

又称对比缓存,客户端会先从缓存数据中获取到一个缓存数据的标识,得到标识后请求服务端验证是否失效(新鲜),如果没有失效服务端会返回 304,此时客户端直接从缓存中获取所请求的数据,如果标识失效,服务端会返回更新后的数据。

缓存字段

服务器响应的 header 中会用两个缓存的字段:ExpiresCache-Control

1、Expires

指定缓存到期 GMT 的绝对时间,如果设了 max-agemax-age 就会覆盖 expires。如果expires 到期需要重新请求。

2、Cache-Control

Cache-Control: 这个是 http 1.1 中为了弥补 Expires 缺陷新加入的。

对已缓存的内容进行控制:

Cache-control: public表示缓存的版本可以被代理服务器或者其他中间服务器识别。

Cache-control: private意味着这个文件对不同的用户是不同的。只有用户自己的浏览器能够进行缓存,公共的代理服务器不允许缓存。

Cache-control: no-cache强制浏览器提交一个 http 请求到源服务器进行确认。http请求没有减少,会减少一个响应体(文件内容), 这种个选项类似弱缓存

其他相关控制字段:

max-age: 指定缓存过期的相对时间秒数,max-ag=0或者是 负值 ,浏览器会在对应的缓存中把Expires 设置为1970-01-01 08:00:00

no-store: 告诉浏览器在任何情况下都不要进行cache,不在本地保留拷贝。

must-revalidate: 强制浏览器严格遵守你设置的 cache 规则。

资源验证

验证是否能使用缓存(协商缓存策略)主要有两种方式:

1、Last-Modified:最后一次修改时间

配合 If-Modified-SinceIf-UnModified-Since使用
对比上次修改时间以验证资源是否需要重新修改

2、Etag: 数据签名

配合 If-Match 或者 If-Non-Match 使用
对比资源的签名判断是否使用缓存

而这里 Etag 主要为了解决 Last-Modified 无法解决的一些问题:

1、一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新 GET;

2、某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说 1s 内修改了 N 次),If-Modified-Since能检查到的粒度是 s 级的,这种修改无法判断 (或者说UNIX 记录 MTIME 只能精确到秒);

3、某些服务器不能精确的得到文件的最后修改时间。

缓存状态码

200 OK (from cache)是浏览器没有跟服务器确认,直接用了浏览器缓存;

304 Not Modified 是浏览器和服务器多确认了一次缓存有效性,再用的缓存。

304 Not Modified200 OK (from cache) 慢,指的是浏览器还向服务器确认了下 If-Not-Modified,才用的缓存。

浏览器中的操作对缓存的影响:

强制刷新 – 当按下 ctrl+F5 来刷新页面的时候, 浏览器将绕过各种缓存(本地缓存和协商缓存), 直接让服务器返回最新的资源;

普通刷新 – 当按下 F5 来刷新页面的时候, 浏览器将绕过本地缓蹲来发送请求到服务器, 此时, 协商缓存是有效的

回车或转向 – 当在地址栏上输入回车或者按下跳转按钮的时候, 所有缓存都生效

退出移动版