ETag、Http缓存、304

1、HTTP的报文:浏览器和服务器间的数据传输

                     浏览器请求数据发送“请求报文”给服务器

                     服务器返回“响应报文”给服务器

                     报文:(1) 报头header【包含缓存相关的信息】

                               (2)包含数据的主体

2、缓存分为:根据是否需要重定向分为:强缓存(本地缓存)和协商缓存

                强缓存:如果生效,不经过服务器

                协商缓存:不管是否生效,经过服务器

                强缓存优先级大于协商缓存

3、缓存优点:1、减少了对数据库读操作,数据库降低压力。

                2、响应速度变快。

                3、能极大改善网页性能,提高用户体验

4、过程:客户端请求数据资源时,先获取header,判断是否为强缓存(cache-control或expires),如果是强缓存就直接从缓存取信息和资源,包括缓存header,本次请求不会与服务器通信。如果不是强缓存,浏览器会发送信息到服务器,由服务器对比header是否为协商缓存,如果是,则服务器返回新的header并且更新缓存中对应的header信息,但不返回资源内容,会告诉浏览器从缓存中取,如果不是协商缓存的话就直接返回资源内容。


5、强缓存

            expires:http1.0的规范,它的值是一个绝对时间格式的字符串,如果发送的请求时间为expires之前,本地缓存始终有效,否则从服务器获取资源。

          cache-control:http1.1的规范,主要是利用max-age来判断,他是一个相对值,资源第一次请求的事件和cache-control设定的有效值计算出一个过期时间,再用这个过期时间和当前请求时间比,过期之前就可以为强缓存,否则不是。

            cache-control优先级比expires高。Expires 表示存在时间,允许客户端在这个时间之前不去检查(发请求),等同max-age 效果。但是如果同时存在,则被Cache-Controlmax-age覆盖。 

还有其他比较常用的

     no-cache:不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。

      no-store: 直接禁止游览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。
        public:可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。
        private:只可被终端用户的浏览器缓存,不允许CDN等中继服务器对其缓存。

6、协商缓存

  last-modified过程:

  1. 客户端请求一个页面(A)。
  2. 服务器返回页面A,并在给A加上一个Last-Modified/ETag。
  3. 客户端展现该页面,并将页面连同Last-Modified/ETag一起缓存。
  4. 客户再次请求页面A,并将上次请求时服务器返回的Last-Modified/ETag一起传递给服务器。
  5. 服务器检查该Last-Modified或ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304和一个空的响应体。
强缓存               从缓存中取                       200(frome cache)               不到服务器

------------------------------------------------------------------------------------------------------

协商缓存           从缓存中取                        304(not modified)             从服务器来告知缓存是否可用


 两组header是成对出现的。协商缓存是由服务器来判断资源是否可用。

    Last-Modified/If-Modified-Since两个都是GMT事件字符串

            (1)浏览器第一次给服务器请求一个资源,服务器返回这个资源时,response上加一个last-Modified表示资源在服务器上最后的修改时间。

                   Last-Modified: Fri, 12 May 2006 18:53:33 GMT

            (2)浏览器再次和服务器资源请求时,在request上加一个if-Modified-Since的header,这个header的值就上一次请求返回的last-Modified的值。

            (3)服务器根据收到的第二次请求以后,根据浏览器传过来的If-Modified-Since和资源在服务器上最后修改时间判断资源是否有变化,如果没有变化返回304Not-Modified,但不返回资源内容,如果有变化,则返回资源内容。

             (4)浏览器收到304以后就会从缓存中加载资源。

            (5)如果不是协商缓存,浏览器会从服务器直接加载资源,这个时候last-Modified的header值会被更新,下次请求的时候,last-Modified-Since会启用上一次返回的last-Modified值。

       Etag/If-none-match

                这两个值是由服务器生成的每个资源的唯一标识符,只有资源变化的时候这个值就会改变,与last-Modified区别是,当服务器返回304 Not-Modified的时候由于Etag重新生成过,response还是会把Etag返回,即使Etag和之前的相比没有变化。


Etag的工作原理:

Etag由服务器端生成,客户端通过If-Match或者说If-None-Match这个条件判断请求来验证资源是否修改。常见的是使用If-None-Match.请求一个文件的流程可能如下:

====第一次请求===
1.客户端发起 HTTP GET 请求一个文件;

2.服务器处理请求,返回文件内容和一堆Header,当然包括Etag(例如"2e681a-6-5d044840")(假设服务器支持Etag生成和已经开启了Etag).状态码200

====第二次请求===
1.客户端发起 HTTP GET 请求一个文件,注意这个时候客户端同时发送一个If-None-Match头,这个头的内容就是第一次请求时服务器返回的Etag:2e681a-6-5d044840

2.服务器判断发送过来的Etag和计算出来的Etag匹配,因此If-None-Match为False,不返回200,返回304,客户端继续使用本地缓存;

问题是,如果服务器又设置了Cache-Control:max-age和Expires呢,怎么办?
答案是同时使用,也就是说在完全匹配If-Modified-Since和If-None-Match即检查完修改时间和Etag之后,服务器才能返回304.


7、Etag与Last-Modified的比较:

Etag的出现就是为了解决last-Modified不能解决的问题:

1、有的文件修改过于频繁,而last-Modified只能精确到秒。

2、一些文件周期性改变的文件内容并没有改变,只是时间改变了,此时我们并不希望服务器认为内容变化了,重新去get。

3、有些服务器不能精确到文件的具体最后的修改时间。(比如一串字符串不能正确识别,因为last-modified是绝对时间格式)


二、304

304:服务器拒绝访问(客户端有缓冲的文档并发出了一个条件性的请求。服务器告诉客户端,原来缓冲的文档还可以继续使用。

在第一次请求服务器的时候在获取资源之后是会先把该资源缓存在本地的,同时服务器response返回了一个响应头ETag,ETag全称Entity Tag,用来标识一个资源。在具体的实现中,ETag可以是资源的hash值,也可以是一个内部维护的版本号。但不管怎样,ETag应该能反映出资源内容的变化,这是Http缓存可以正常工作的基础。服务器对于hello world这个字符串使用上述返回的ETag来表示,只要hello world这个资源不变,这个Etag就不会变。

客户端第二次请求服务器的时候,利用请求头If-None-Match来告诉服务器自己已经有个ETag为xxx的资源。如果服务器上的资源没有变化,也就是说服务器上的资源的ETag也是xxx的话,服务器就不会再返回该资源的内容,而是返回一个304的响应,告诉浏览器该资源没有变化,缓存有效,浏览器将直接调用本地缓存

响应头Cache-Control

每个资源都可以通过Http头Cache-Control来定义自己的缓存策略,Cache-Control控制谁在什么条件下可以缓存响应以及可以缓存多久。 最快的请求是不必与服务器进行通信的请求:通过响应的本地副本,我们可以避免所有的网络延迟以及数据传输的数据成本。为此,HTTP 规范允许服务器返回一系列不同的 Cache-Control 指令,控制浏览器或者其他中继缓存如何缓存某个响应以及缓存多长时间。

Cache-Control 头在 HTTP/1.1 规范中定义,取代了之前用来定义响应缓存策略的头(例如 Expires)。当前的所有浏览器都支持 Cache-Control,因此,使用它就够了。

以下我来介绍可以再Cache-Control中设置的常用指令。

max-age 

该指令指定从当前请求开始,允许获取的响应被重用的最长时间(单位为秒。例如:Cache-Control:max-age=60表示响应可以再缓存和重用 60 秒。需要注意的是,在max-age指定的时间之内,浏览器不会向服务器发送任何请求,包括验证缓存是否有效的请求,也就是说,如果在这段时间之内,服务器上的资源发生了变化,那么浏览器将不能得到通知,而使用老版本的资源。所以在设置缓存时间的长度时,需要慎重。

public和private

如果设置了public,表示该响应可以再浏览器或者任何中继的Web代理中缓存,public是默认值,即Cache-Control:max-age=60等同于Cache-Control:public, max-age=60。

在服务器设置了private比如Cache-Control:private, max-age=60的情况下,表示只有用户的浏览器可以缓存private响应,不允许任何中继Web代理对其进行缓存 - 例如,用户浏览器可以缓存包含用户私人信息的 HTML 网页,但是 CDN 不能缓存。

no-cache

如果服务器在响应中设置了no-cache即Cache-Control:no-cache,那么浏览器在使用缓存的资源之前,必须先与服务器确认返回的响应是否被更改,如果资源未被更改,可以避免下载。这个验证之前的响应是否被修改,就是通过上面介绍的请求头If-None-match和响应头ETag来实现的。

需要注意的是,no-cache这个名字有一点误导。设置了no-cache之后,并不是说浏览器就不再缓存数据,只是浏览器在使用缓存数据时,需要先确认一下数据是否还跟服务器保持一致。如果设置了no-cache,而ETag的实现没有反应出资源的变化,那就会导致浏览器的缓存数据一直得不到更新的情况。

no-store

如果服务器在响应中设置了no-store即Cache-Control:no-store,那么浏览器和任何中继的Web代理,都不会存储这次相应的数据。当下次请求该资源时,浏览器只能重新请求服务器,重新从服务器读取资源。






















猜你喜欢

转载自blog.csdn.net/weixin_41143293/article/details/79784276