Java web

你真的懂HTTP的缓存机制?

2019-11-06  本文已影响0人  蛙哇

前言

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

客户端缓存

缓存不仅可以存在于缓存服务器内,还可以存在客户端浏览器中。通常把客户端缓存称为临时网络文件。浏览器缓存如果有效,就不必再向服务器请求相同的资源了,可以直接从本地磁盘内读取。另外,和缓存服务器相同的一点是,当判定缓存过期后,会向源服务器确认资源的有效性。若判断浏览器缓存失效,浏览器会再次请求新的资源。

ps:对于前端开发来说,我们只需要关注客户端缓存即可

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

强缓存

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

协商缓存

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

HTTP报文组成

首先,在了解HTTP缓存之前,我们有必要先了解HTTP报文的主要组成部分。

1、HTTP请求报文是由方法、URL、HTTP版本、HTTP首部字段等部分构成。

image

2、HTTP响应报文由HTTP版本、状态码、HTTP首部组成。

image

在报文众多字段中,HTTP首部字段包含的信息最为丰富的,它是构成HTTP报文的要素之一。跟缓存有关的属性也包含在这里面。

首部字段

首先,我们的先了解首部字段有哪些?一般可以分为通用首部字段、请求首部字段、响应请求字段、实体首部字段,由于本文谈论的是缓存相关的,所以在这里只列举了中跟缓存相关的字段名。

通用首部字段

请求报文和响应报文都会使用的首部,主要的缓存相关字段:

Cache-Control:控制缓存的行为。

通过指定首部字段Cache-Control的指令,就能操作缓存的工作机制,一般可以分为缓存请求指令和缓存响应指令。

1、缓存请求指令

2、缓存响应指令

请求首部字段(Request Header

从客户端向服务端发送请求报文时使用的首部,主要的缓存相关字段:

响应首部字段(Response Header

从服务器向客户端发送请求报文时使用的首部,主要的缓存相关字段:

实体首部字段

针对请求报文和响应报文的实体部分使用的首部,用于补充内容的更新时间等与实体信息有关的内容,主要的缓存相关字段:

Expires和Cache-Control

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

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

ps:所有的首部字段都是基于HTTP/1.1的

资源验证

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

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

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

last-modified是web服务器认为文件的最后修改时间,last-modified是第一次请求文件的时候,服务器返回的一个属性。

Last-Modified: Sat, 09 Jun 2018 08:13:56 GMT 

第二次请求这个文件时,浏览器把If-Modified-Since发送给服务器,询问该时间之后文件是否被修改过。

If-Modified-Since: Sat, 09 Jun 2018 08:13:56 GMT //  跟Last-Modified的值一样

2、Etag: 数据签名

配合If-Match或者If-Non-Match使用
对比资源的签名判断是否使用缓存
ETag也是首次请求的时候,服务器返回的:

ETag: "8F759D4F67D66A7244638AD249675BE2" // 长这样

If-None-Match也是浏览器发送到服务器验证,文件是否改变的:

    If-None-Match: "8F759D4F67D66A7244638AD249675BE2" // 跟ETag的值一样

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

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

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

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

缓存状态码

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

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

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

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

上一篇 下一篇

猜你喜欢

热点阅读