精华内容
下载资源
问答
  • HTTP系列之:HTTP缓存

    万次阅读 2021-09-01 22:10:56
    为了提高网站的访问速度和效率,我们需要设计各种各样的缓存,通过缓存可以避免不必要的额外数据传输和请求,从而提升...对于HTTP协议来说,本身就自带有HTTP缓存。 今天我们就深入探讨一下HTTP中的缓存机制和使用。

    简介

    为了提高网站的访问速度和效率,我们需要设计各种各样的缓存,通过缓存可以避免不必要的额外数据传输和请求,从而提升网站的请求速度。对于HTTP协议来说,本身就自带有HTTP缓存。

    今天我们就深入探讨一下HTTP中的缓存机制和使用。

    HTTP中的缓存种类

    缓存就是将请求的资源在本地保存一份拷贝,从而在下一次请求的时候,直接返回该拷贝,不用再从服务器下载资源,从而减少了资源的传输提升了效率。

    除了直接访问和返回资源之外,HTTP中的缓存可以分成两类,一种是共享cache,也就是说不同的客户端都可以从该共享cache中获取资源,并且这些资源是多个客户端可以访问的。还有一种是私有cache,这意味着该cache只能用户或者客户端私有访问,其他用户是无权访问的。

    私有cache很好理解,我们常用的浏览器中的cache基本上就是私有cache,这些cache是浏览器独有的,并不会共享给其他的浏览器。

    共享cache主要用在一些web代理上,比如web代理服务器,因为web代理服务器可能会为众多的用户提供资源服务,对于这些用户共同访问的资源就不必要每个用户保存一份了,只需要在web代理服务器中保存一份即可,这样可以减少资源的无效拷贝。

    HTTP中缓存响应的状态

    对于HTTP缓存来说,一般缓存的是GET请求,因为GET请求除了URI之外,并没有其他多余的参数,并且其表示的意义是从服务器获取资源。

    不同的GET请求,会返回不同的状态码。

    如果是成功返回资源,则会返回200表示OK。

    如果是重定向,则返回301。如果是异常,则返回404。如果是不完全的结果,则会返回206。

    HTTP中的缓存控制

    HTTP中的缓存控制是通过HTTP头来表示的。在HTTP1.1中加入了Cache-Control,我们可以通过Cache-Control来控制请求和响应的缓存情况。

    如果不需要缓存,则使用:

    Cache-Control: no-store
    

    如果需要对客户端的缓存进行验证,则使用:

    Cache-Control: no-cache
    

    如果要强制进行验证,则可以使用:

    Cache-Control: must-revalidate
    

    在这种情况下,过期的资源将不会被允许使用。

    对于服务器来说,可以通过Cache-Control来控制缓存是private或者public的:

    Cache-Control: private
    Cache-Control: public
    

    还有一个非常重要的缓存控制就是过期时间:

    Cache-Control: max-age=31536000
    

    通过设置max-age,可以覆盖Expires头,表示在这个时间区间范围之类,该资源可以看做是最新的,不需要重新从服务器获取。

    Cache-Control是HTTP1.1中定义的header字段,在HTTP1.0中也有一个类似的字段叫做Pragma。通过设置 Pragma: no-cache可以得到类似Cache-Control: no-cache的效果。也就是强制客户端重新提交缓存到服务器端进行校验。

    但是对于服务器端的响应来说,并不包含Pragma,所以Pragma并不能完全替代Cache-Control。

    缓存刷新

    缓存存放在客户端之后,就可以在请求的时候被使用了。但是为了安全起见,我们需要给缓存设置一个过期时间,只有在过期时间之前的时间范围,缓存才是有效的,如果超过了过期时间,则需要从服务器重新获取。

    这样的机制能够保证客户端获取到的资源始终是最新的。并且能够保证服务器端对资源的更新能够及时到达客户端。

    如果客户端的资源在过期时间之类,那么这个资源的状态就是fresh,否则资源的状态就是stale。

    如果资源是stale状态的,该资源并不会立即从客户端清理出去,而是在下一次的请求中,向服务器发送一个If-None-Match的请求,判断该资源在服务器端是否仍然是fresh状态的,如果该资源并没有发生变化,则返回304 (Not Modified),表示该资源仍然有效。

    而这个fresh的持续时间就是通过"Cache-Control: max-age=N" 来判断的。

    如果响应中并没有这个头,则会去判断 Expires header 是否存在,如果存在那么fresh的时间就可以使用Expires - Date 来进行计算。

    如果响应中连Expires header都没有,那么怎么去判断资源的fresh时间呢?

    这种情况下会去查找Last-Modified header,如果这个header存在的话,那么fresh时间就是(Date - Last-modified )/ 10 。

    revving

    为了提升HTTP请求的效率,我们当然希望缓存时间越长越好,但是前面我们也提到了,缓存时间过长会导致服务器资源更新困难的问题。怎么解决呢?

    对于那些不经常更新的文件,请求他们的URL可以由文件名+版本号来决定。同一个版本号表示该资源内容是固定不变的,我们可以对其缓存一个非常长的时间。

    当服务器资源内容发生变化之后,只需要在请求的时候更新版本号即可。

    虽然这样的操作会造成服务器资源的修改同时要修改客户端请求的版本,但是在现代前端打包工具的帮助下,这并不是一个很大的问题。

    缓存校验

    当缓存的资源过期之后,有两种处理方式,一种是重新从服务器请求资源,一种是对缓存资源进行再次校验。

    当然再次校验需要服务器的支持,并需要设置"Cache-Control: must-revalidate"请求头。

    那么客户端怎么去校验资源是否有效呢?很明显我们不能把资源从客户端发送到服务器端进行校验,这样的操作方式太过复杂,并且在文件比较大的请求下,会造成资源的浪费。

    我们很容易想到的一种方法是对资源文件进行hash运行,只要发送这个hash运算的结果进行对比即可。

    当然,在HTTP中,提供了一个ETags header,这header可以看做是资源的唯一标记,用来在客户端和服务器端进行校验。这样客户端就可以请求一个If-None-Match,让服务器判断该资源是否match。这种判断被称为强校验。

    还有一种弱校验的方式,如果响应中带有Last-Modified,则客户端可以请求一个If-Modified-Since,来向服务器询问该文件是否发生了变化。

    对于服务器端来说,它可以选择是否进行文件的校验,如果不进行校验,则可以直接返回一个200 OK状态码,并直接返回资源。如果进行校验,则返回一个304 Not Modified,表示客户端可以继续使用缓存的资源,同时还可返回一些其他的header字段,比如更新缓存的过期时间等。

    Vary响应

    在服务器响应的时候,可以带上Vary header。这个Vary header的值是响应头中的某个key,比如Content-Encoding,表示对某个encoding的资源进行缓存。

    比如客户端首先请求:

    GET /resource HTTP/1.1
    Accept-Encoding: * 
    

    服务器端返回:

    HTTP/1.1 200 OK
    Content-Encoding: gzip
    Vary: Content-Encoding
    

    则将会把资源和gzip类型的Content-Encoding一起缓存起来。

    当客户再次请求:

    GET /resource HTTP/1.1
    Accept-Encoding: br
    

    因为当前缓存的资源encoding方式是gzip,和客户端接受的encoding方式并不一样,所以重新需要从服务器获取:

    HTTP/1.1 200 OK
    Content-Encoding: br
    Vary: Content-Encoding
    

    这时候,客户端又缓存了一个br格式的资源。

    下次客户端再次请求br类型的资源,就可以命中缓存了。

    总结一下,Vary的意思是将资源再通过其他的类型比如encoding进行区分和缓存。

    但是这样也会造成资源重复存储的问题,同一个资源因为编码格式的不同被缓存了很多份。为了解决这个问题,就需要对资源请求进行标准化。

    所谓标准化,就是在请求之前对请求的encoding方式进行校验,只选择其中的一种编码方式进行请求,从而避免资源多次缓存的情况。

    总结

    到此,HTTP缓存就介绍完毕了,大家可以在实际的应用中对HTTP缓存加深理解。

    本文已收录于 http://www.flydean.com/04-http-cache/

    最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

    欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

    展开全文
  • [Route("api/[controller]")] [ApiController] ... [HttpPut] public ActionResult Put() { var person = new Person { Id = 2, Name = "李四" }; Persons.Add(person); return Ok(); } }
  • http缓存策略之强缓存与协商缓存

    千次阅读 2020-04-11 16:45:25
    前言: web中有些场景下很多内容是不需要更改的,如果每次请求都向服务器请求那些一段时间内不会变动的内容数据,会造成不必要的带宽浪费。...http缓存指的是:当客户端向服务器请求资源时,会先查...

    前言:

    web中有些场景下很多内容是不需要更改的,如果每次请求都向服务器请求那些一段时间内不会变动的内容数据,会造成不必要的带宽浪费。

    有时候网络较差时,请求这些内容就需要花费很长时间来打开页面。

    因此通过浏览器的缓存机制,协同服务器让浏览器缓存那些不需要频繁变动的资源就可以有效地降低流量消耗和响应时间。

    一、什么是http缓存

    http缓存指的是:当客户端向服务器请求资源时,会先查看浏览器缓存,如果浏览器有“要请求资源”的副本,就可以直接从浏览器缓存中提取,而不需要从服务器中请求这个资源。

    需要注意的是,常见的http缓存只能缓存GET请求的资源,所以下面说的请求缓存皆是指GET请求。

    http缓存分类:根据是否需要向服务器发起请求把http缓存分为两个大类,强缓存协商缓存

    http缓存都是从第二次请求开始的:

    • 第一次请求资源时,客户端向服务器请求资源,服务器返回响应资源,并在response header中回传资源的缓存参数;
    • 第二次请求资源时,浏览器判断这些请求参数,命中强缓存就返回200,使用磁盘缓存中的资源,不请求服务器,否则就把请求参数加到request header中传给服务器,看是否命中协商缓存,命中则返回304,使用缓存资源,若都没命中则服务器会返回新的资源。

    二、强缓存

    强缓存是通过设置缓存的到期时间 expires 或者有效时间 max-age ,在有效时间内,缓存不会失效,浏览器直接从浏览器缓存中读取资源。当缓存数据库中没有所请求的资源,或所请求的资源已失效时,才会从服务端请求资源。

    与强制缓存相关的请求响应头: 

    • Expires

    响应头,代表该资源的过期时间。但由于服务端时间和客户端时间可能有误差,这也将导致缓存命中可能有误差,另一方面,Expires是HTTP1.0的产物,故现在大多数使用Cache-Control替代。

    • Cache-Control(优先级高于Expires)

    请求/响应头,缓存控制字段,精确控制缓存策略。 Cache-Control有很多属性,不同的属性代表的意义也不同。

    1. private:客户端可以缓存
    2. public:客户端和代理服务器都可以缓存
    3. max-age=x:缓存内容将在x秒后失效
    4. no-cache:不能直接使用缓存,要求向服务器发起请求
    5. no-store:所有内容都不会缓存
    • pragma 

    pragma 是一个在 HTTP/1.0 中规定的通用首部。设置为no-cache与 Cache-Control: no-cache 效果一致,优先级高于cache-control和expires,即三者同时出现时,先看pragma -> cache-control -> expires。

    三、协商缓存

    协商缓存需要在服务器端对比资源是否修改,来判断是否可以使用缓存。若未改动,则返回304状态码,浏览器拿到此状态码就可以直接使用缓存数据了。否则服务器返回新资源。

    由此可见,在协商缓存中,如何判断资源是否改动就尤为重要啦,现在主要有两种策略:Last-Modified 和 Etag 

    • Last-Modified

    服务器在响应请求时,会告诉浏览器资源GMT格式的最后修改时间。

    浏览器非第一次请求服务器时,请求头会包含 if-Modified-Since 字段,后面跟着在缓存中获得的最后修改时间。服务端收到此请求头发现有if-Modified-Since,则与被请求资源的最后修改时间进行对比,如果一致则返回304和响应报文头,此时浏览器只需要从缓存中获取资源即可。 

    • 如果真的被修改:那么开始传输响应一个整体,服务器返回:200 OK
    • 如果没有被修改:那么只需传输响应header,服务器返回:304 Not Modified

    Last-Modified 其实用起来不一定完全准确:

    1. Last-Modified标注的最后修改只能精确到秒级,如果某文件在1秒钟以内被修改多次的话,它将不能准确标注文件的修改时间
    2. 如果某些文件被修改了,但是内容并没有任何变化,而Last-Modified却改变了,导致文件没法使用缓存
    3. 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形

    因此,HTTP1.1推出了Etag,改进了这些问题。

    • Etag(优先级高于Last-Modified)

    服务器响应请求时,通过此字段告诉浏览器当前资源在服务器生成的唯一标识(生成规则由服务器决定)。

    非第一次请求服务器时,浏览器的请求报文头部(Request Headers)会包含 If-None-Match 字段,后面的值为在缓存中获取的标识。服务器接收到此报文后就用 If-None-Match 的值与被请求资源的唯一标识进行对比。

    • 不同,则说明资源被改动,则返回状态码200,服务器返回新资源。
    • 相同,说明资源未修改,则返回状态码304,浏览器直接从缓存中获取数据资源。

    不过etag也存在缺点,就是每次生成表示字符串会增加服务器的开销。所以要如何使用last-modified和etag还需要根据具体需求进行权衡。

    四、动动手

    好了,理论部分说完了,下面我们自己动手尝试一下

    我用nodejs开了一个服务器,用来获取get请求的响应,并在其中设置http缓存的相关属性,网页部分就是一个简单的加载图片,初学nodejs写接口,没有很完善,只是为了弄明白缓存怎么用,仅供参考。

    强缓存:

    nodejs中get请求部分的代码:

    app.get("/api/getPic", (req, res) => {
      res.setHeader("Cache-Control", "public,max-age=120");  //max-age设置的2分钟
      let date = new Date(Date.now() + 5000).toUTCString(); //Expires过期时间设置了5分钟后
      res.setHeader("Expires", date);
      let data = JSON.stringify({
        msg: "请求成功",
        result: [
          {
            url:
              "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=350525183,1430160676&fm=11&gp=0.jpg"
          }
        ]
      });
      res.send(data);
    });

    发送一次请求,可以看到强缓存的配置已经设置好了(默认带了协商缓存的etag,但是我也不知道为什么。。。。。。):

    之后我立即刷新页面,此时变成酱紫了,status Code是200,后边显示from disk cache,此时的图片资源即从磁盘缓存中获取,不请求服务器:

     两分钟后,再次刷新页面,此时status code显示304,即请求的服务器,请求的资源没有被更改,命中的协商缓存:

    由于默认带了 Etag协商缓存,所以协商缓存部分就没有手写,感兴趣的小伙伴可自行编写设置 Last-Modified 和 Etag 属性值。

    补充:

    网络请求的size会出现三种情况

    1. from memory cache (内存缓存)
    2. from disk cache (磁盘缓存)
    3. 资源数值大小

    1. 显示数值的状态码为200, 直接从服务器下载最新资源
    2. from memory cache 不请求网络资源,资源在内存当中,一般js脚本,字体,图片会存放在内存当中
    3. from disk cache 不请求网络资源,在磁盘当中,一般非脚本会存在内存当中,如css

    五、不同的网页刷新操作

    我们将访问和刷新分为以下三种情况:

    • 标签进入、输入url回车进入:按照指定的缓存策略去操作
    • 按刷新按钮、F5刷新、网页右键“重新加载”:强缓存失效,直接判断协商缓存
    • ctrl+F5强制刷新:所有缓存失效,重新请求服务器数据
    展开全文
  • 在工作之余阅读缓存相关的书籍时,看到了http缓存相关的知识,HTTP 缓存机制是一个 web 性能优化的重要手段,无论是做前端还是做web后台,都可能会用得到它,应该是知识体系库中的一个基础环节,以前这一块学的不是...

    介绍

    在工作之余阅读缓存相关的书籍时,看到了http缓存相关的知识,HTTP 缓存机制是一个 web 性能优化的重要手段,无论是做前端还是做web后台,都可能会用得到它,应该是知识体系库中的一个基础环节,以前这一块学的不是很扎实,现在整理资料巩固巩固。

    HTTP缓存可以说是浏览器缓存的其中一种,浏览器缓存也包含很多内容: HTTP 缓存、indexDB、cookie、localstorage 等等。这里我们只讨论 HTTP 缓存相关内容。

    浏览器主要分为Last-Modified/EtagCache-Control/Expires
    其中Cache-Control/Expires属于强缓存,Last-Modified/Etag属于协商(比较)缓存

    cache-control

    在这里插入图片描述
    cache-control字段位于这里,像这样设置的cache-control是没有缓存的

    在请求中使用Cache-Control 时,它可选的值有:
    在这里插入图片描述
    在响应中使用Cache-Control 时,它可选的值有:
    在这里插入图片描述
    在Cache-Control 中,这些值可以自由组合,多个值如果冲突时,也是有优先级的,而no-store优先级最高

    cache-control这种强缓存是性能高的,它不需要请求服务器,就直接从本地加载文件了,后面的Last-Modified/Etag是需要请求服务器来验证文件的。

    在实际使用中,浏览器会先验证强缓存,所以对于js、css、img文件的过期时间可以设置非常长,因为前端构建工具打包出来的文件是有利于缓存的,比如可以配置webpack打包后的js文件跟个hash值,就可以根据hash来判断文件是否发生变化。在打包出来的文件名上加上文件内容的hash是目前最常见的有效使用浏览器强缓存的方法,js文件如果有内容更新,hash就会更新,浏览器请求路径变化所以更新缓存,如果js内容不变,hash不变,直接用缓存,下面的etag也有类似的思想。
    如果对于变化频繁的文件就不要加cache-control了,如果配置cache-control的过期时间比较长的话,由于cache-control优先级比Last-Modified/Etag高,所以会在过期时间内不会更新文件。

    Expires

    关于Expires:

    1. Expires 是以前用来控制缓存的http头,Cache-Control是新版的API。
    2. 现在首选 Cache-Control。
    3. 如果在Cache-Control响应头设置了 “max-age” 或者 “s-max-age” 指令,那么 Expires 头会被忽略。
    4. 响应头设置方式: Expires: Wed, 21 Oct 2015 07:28:00 GMT
    5. Expires 响应头包含日期/时间, 即在此时候之后,响应过期。

    注意: 因为过期标准的时间用的是本地时间,所以不靠谱,所以要使用Cache-Control代替Expires。

    关于第三点:一般会把Cache-Control和Expires都设置上,因为 Expires 是 HTTP 1.0 定义的字段,而 Cache-Control 是 HTTP 1.1 的字段,万一客户端只支持 HTTP 1.0,那么 Cache-Control 有可能就会不工作,所以一般为了兼容会都写上。
    在这里插入图片描述
    Cache-Control设置时间长度、Expires 设置时间点

    Last-Modify/If-Modify-Since

    浏览器第一次请求一个资源的时候,服务器返回的 header中会加上Last-Modify,Last-modify是一个时间标识该资源的最后修改时间。
    在这里插入图片描述
    当浏览器再次请求该资源时,发送的请求头中会包含If-Modify-Since该值为缓存之前返回的Last-Modify。服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存。
    在这里插入图片描述
    如果命中缓存,则返回http304,并且不会返回资源内容,并且不会返回Last-Modify。由于对比的服务端时间,所以客户端与服务端时间差距不会导致问题。但是有时候通过最后修改时间来判断资源是否修改还是不太准确(资源变化了最后修改时间也可以一致)。于是出现了ETag/If-None-Match。

    Etag/If-None-Match

    经过上面的缓存后,若未命中强缓存,则浏览器会将请求发送至服务器。服务器根据http头信息中的Last-Modify/If-Modify-Since或Etag/If-None-Match来判断是否命中协商缓存。如果命中,则http返回码为304,浏览器从缓存中加载资源。

    与Last-Modify/If-Modify-Since不同的是,Etag/If-None-Match返回的是一个校验码(ETag: entity tag)。ETag可以保证每一个资源是唯一的,资源变化都会导致ETag变化。ETag值的变更则说明资源状态已经被修改。服务器根据浏览器上发送的If-None-Match值来判断是否命中缓存。
    在这里插入图片描述
    ETag是HTTP1.1中才加入的一个属性,用来帮助服务器控制Web端的缓存验证。它的原理是这样的,当浏览器请求服务器的某项资源(A)时, 服务器根据A算出一个哈希值(3f80f-1b6-3e1cb03b)并通过 ETag 返回给浏览器,浏览器把"3f80f-1b6-3e1cb03b" 和 A 同时缓存在本地,当下次再次向服务器请求A时,会通过类似 If-None-Match: “3f80f-1b6-3e1cb03b” 的请求头把ETag发送给服务器,服务器再次计算A的哈希值并和浏览器返回的值做比较,如果发现A发生了变化就把A返回给浏览器(200),如果发现A没有变化就给浏览器返回一个304未修改。这样通过控制浏览器端的缓存,可以节省服务器的带宽,因为服务器不需要每次都把全量数据返回给客户端。
    HTTP中并没有指定如何生成Etag,可以自己定义一种好的方式来生成Etag
    通过etag,实际上还是要向服务器发送一次请求,但是把资源文件缓存下来了,减少服务器带宽。

    总结

    Last-Modified与 Etag对比
    你可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag(实体标识)呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:

    1. Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间。
    2. 如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存。
    3. 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形。

    Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。
    在这里插入图片描述
    在这里插入图片描述
    浏览器第一次和第二次请求对比,这张图反映出优先级:ETag优先级 > Last-Modified优先级、cache-control优先级 > expires优先级

    用户操作与缓存
    在这里插入图片描述

    在spring boot中开启http缓存

    本地测试环境:
    Spring boot版本: 2.1.3.RELEASE
    项目前后端通过ajax交互,前端文件全部放在src/main/resources/static目录下,跟后台一起部署。

    实操:

    配置Cache-Control

    在spring boot中,发现没有经过http缓存相关的配置默认是这样子的,response带有不使用缓存的http头,导致每次加载都要从服务端获取数据,而有些静态资源文件是不必要每次从服务器去获取的,像常用的js库、css库什么的。
    在这里插入图片描述
    Spring boot配置cache-control和expires可以通过WebMvcConfigurationSupport来配置,也可通过修改配置文件的方式,这里使用配置类的方式。

    这里需要注意的是,使用WebMvcConfigurationSupport会使WebMvcAutoConfiguration的自动配置不生效,因为WebMvcAutoConfiguration里面有个@ConditionalOnMissingBean(WebMvcConfigurationSupport.class),表现为默认的一些映射路径无法访问,如果想保留默认的配置,那就使用implements WebMvcConfigurer的方式来配置

    @Configuration
    public class WebConfigConfigurer extends WebMvcConfigurationSupport {
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/static/**")
                    .addResourceLocations("classpath:/static/")
                    .setCacheControl(CacheControl.maxAge(604800, TimeUnit.SECONDS));
        }
    }
    

    这里将src/main/resources/static目录映射到/static的url下,然后setCacheControl就可以了。

    spring.resources.cache.cachecontrol.cache-private= # Indicate that the response message is intended for a single user and must not be stored by a shared cache.
    spring.resources.cache.cachecontrol.cache-public= # Indicate that any cache may store the response.
    spring.resources.cache.cachecontrol.max-age= # Maximum time the response should be cached, in seconds if no duration suffix is not specified.
    spring.resources.cache.cachecontrol.must-revalidate= # Indicate that once it has become stale, a cache must not use the response without re-validating it with the server.
    spring.resources.cache.cachecontrol.no-cache= # Indicate that the cached response can be reused only if re-validated with the server.
    spring.resources.cache.cachecontrol.no-store= # Indicate to not cache the response in any case.
    spring.resources.cache.cachecontrol.no-transform= # Indicate intermediaries (caches and others) that they should not transform the response content.
    spring.resources.cache.cachecontrol.proxy-revalidate= # Same meaning as the "must-revalidate" directive, except that it does not apply to private caches.
    spring.resources.cache.cachecontrol.s-max-age= # Maximum time the response should be cached by shared caches, in seconds if no duration suffix is not specified.
    spring.resources.cache.cachecontrol.stale-if-error= # Maximum time the response may be used when errors are encountered, in seconds if no duration suffix is not specified.
    spring.resources.cache.cachecontrol.stale-while-revalidate= # Maximum time the response can be served after it becomes stale, in seconds if no duration suffix is not specified.
    
    

    如果要使用配置的方式也很简单,上面这些是关于cache的配置,在spring boot官方文档最后的附录里面有。
    在这里插入图片描述
    再来测试,首先把缓存开启,它这个选项就是通过request headers里的CacheControl实现的。
    在这里插入图片描述
    然后刷新发现已经使用了http缓存。
    在这里插入图片描述
    发现已经不是之前默认的no-store了,而是变为我们自己设置的缓存过期时间了,说明已经在使用http的强缓存了!

    小提示:这个addResourceHandler和addResourceLocations不要弄反了,addResourceHandler的参数是URL path patterns,addResourceLocations的参数是本地资源路径

        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/**")
                    .addResourceLocations("classpath:/static/")
                    .setCacheControl(CacheControl.maxAge(0, TimeUnit.SECONDS)
                            .cachePublic());
        }
    

    像这种的,就是将src/main/resources/static目录映射到/的url下
    在这里插入图片描述
    如果遇到问题,那么就debug ResourceHandlerRegistry的AbstractHandlerMapping getHandlerMapping()方法,在urlMap变量中看到url与handler的映射关系

    配置Last-Modified缓存

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**")
                .addResourceLocations("classpath:/static/")
                .setCacheControl(
                        CacheControl.maxAge(0, TimeUnit.SECONDS)
                        .cachePublic());
    }
    
    

    先一步一步的来,把cacheControl过期时间设置0,并设置为public,根据之前的流程图,因为过期时间为0,判断已过期,进入etag判断,而这里没有设置etag,那就进入Last-Modified判断。
    需要注意的就是no-cache与max-age=0的区别,no-cache是压根都不用缓存,直接请求服务器200,过期时间为0就会走Etag/Last-Modified缓存的判断
    在这里插入图片描述
    发现已经变成了304,设置成功了。
    在这里插入图片描述
    现在就是通过对比If-Modified-SinceLast-Modified,就是文件修改时间来判断缓存的。

    配置ETag缓存

    @Bean
    public FilterRegistrationBean filterRegistrationBean () {
        ShallowEtagHeaderFilter eTagFilter = new ShallowEtagHeaderFilter();
        //设置为weakETag,默认为false
        // eTagFilter.setWriteWeakETag(true);
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(eTagFilter);
        registration.addUrlPatterns("/static/*");
        return registration;
    }
    
    

    如果想开启Etag可以使用这个过滤器,把static下文件的设置上etag
    这个过滤器是通过生成MD5值来校验的,也可以自定义一个生成Etag的规则
    在这里插入图片描述
    第一次请求,服务器会返回一个Etag标签,200状态码
    在这里插入图片描述
    第二次请求,浏览器携带这个etag带去后台验证,然后返回304

    在这里插入图片描述
    修改这个文件,发现返回了一个新的Etag,再次请求也是304,说明缓存成功了

    展开全文
  • HTTP 缓存详解

    千次阅读 多人点赞 2018-04-29 01:40:42
    HTTP缓存主要用在对一些实时性要求不高的静态文件进行的缓存,往往都是存在浏览器端,防止这些“多余”的请求重复的访问服务器,对服务器造成压力,从而提高网站的性能。 原理 现有两端,浏览器C和服务器端S。 ...

    用途

    HTTP缓存主要用在对一些实时性要求不高的静态文件进行的缓存,往往都是存在浏览器端,防止这些“多余”的请求重复的访问服务器,对服务器造成压力,从而提高网站的性能。

    原理

    现有两端,浏览器C和服务器端S。

    这里写图片描述

    浏览器向服务器发送请求,获取一个文件f

    这里写图片描述

    服务器就把f给返回浏览器

    这里写图片描述

    假如这个文件的内容变化不是那么快,一两周更新一次,浏览器每次请求服务器都返回相同的文件,岂不是对服务器资源的一种浪费?

    如何解决呢?

    浏览器把请求后拿到的文件存到本地,等下次请求的时候,看看本地是否有缓存文件,如果有,直接拿本地的文件,岂不是就不用请求服务器了?这其实就是http缓存的最最根本的原理。

    C端浏览器端把请求来的文件缓存到如图下f的小方格内
    这里写图片描述

    等到下次C端再次请求此文件时,就直接从浏览器缓存的文件中拿,而不再向S服务器端发起请求了

    这里写图片描述

    以下浏览器截图中标红的部分,就是没有发起请求,直接从浏览器缓存中获取的数据

    这里写图片描述

    两种缓存方式

    浏览器端有了缓存之后,不能一直有效吧,如果文件更新了,我们还继续使用浏览器缓存中的数据,虽说时效性不强,但长期使用旧文件也不算合理吧。

    http协议提供了两种维度来让缓存失效:时间和文件的修改。

    利用时间来让缓存失效

    时间维度很简单,就是设定一个缓存时间段,过了这个时间段,缓存就自动失效了,浏览器就会发起请求获取文件。这个设定时间的http字段就是cache-control字段。

    cache-control 可设置的字段值有:

    • private :客户端可以缓存
    • public :客户端和代理服务器都可缓存,大部分情况可以认为public和private是一样的
    • max-age=xxx : 缓存的内容将在 xxx 秒后失效 (时间就是在这儿设置的)
    • no-cache :需要使用另外一种http缓存策略来验证缓存数据
    • no-store :所有缓存策略都不会进行(这里指的是两种缓存策略都不会进行)

    cache-control 缓存原理

    第一次访问请求,客户端C向服务端S发起一个文件请求,服务器返回文件并在response中加了响应头"Cache-Control:max-age=60",这样一来,这个f文件只能在浏览器端存
    60秒

    这里写图片描述

    在这60秒钟,客户端请求服务器的f文件会直接从缓存中拿取

    这里写图片描述

    60秒过后,缓存失效,浏览器再次请求文件需要重新向服务器发起请求。

    这里写图片描述

    注意:假如说请求中包含“Cache-Control:max-age=0”或者“Cache-Control:no-store”无论响应中返回的"max-age"值是多少,都不会缓存到服务器。浏览器中对于地址栏中直接输入文件地址的请求做了优化处理,加上了“Cache-Control:max-age=0”,也就是说,如果这个css、js或者其他静态文件是通过你在浏览器上直接输入获得的,将会每时每刻都是获取最新的。

    通过查看文件的修改来让缓存失效

    这种维度比较的科学:浏览器先请求服务获得文件后,服务器会返回该文件的最后修改时间Last-Modified,作为文件的一个标识,下次浏览器请求的时候,会带着这个标识去请求(此时为If-Modified-Since),然后服务器做校验,如果说时间标识If-Modified-Since等于服务器的文件修改时间,则说明没有修改,返回304状态码,浏览器从缓存中获取文件,但是如果浏览器保存的时间标识If-Modified-Since小于服务器端的文件修改时间,那么,说明文件发生了修改,浏览器就会重新获取新的文件。
    If-Modified-Since的时间如果大于服务器端文件的时间,会被认为是错误的请求)

    如图,浏览器C向服务器发S起请求,服务器S返回文件的同时还会返回文件的最后修改时间Last-Modified作为文件时间标识,浏览器会将文件和文件时间标识都缓存起来。

    这里写图片描述

    假如服务器端的文件f并没有被修改,服务器通过判断请求头带的时间标识If-Modified-Since得出结论后,都会返回状态码304告诉浏览器文件没有被修改,让浏览器使用缓存。

    这里写图片描述

    假如服务器端的文件f修改了,那么,浏览器将重新获取文件,并缓存到浏览器中。

    这里写图片描述

    虽然通过文件最后修改时间作为标识已经很完美了,但是,还是可能存在一个问题:就是有可能服务器端的文件修改后,又改回原来的样子,这样,虽然文件最后修改时间变了,但是,文件内容并没有改变。这样还是会有多余的请求到达服务器,该如何处理呢?
    可以将文件内容作为一个唯一标识,例如可以对文件内容取MD5值作为字段(etag)也传给浏览器端,假如这个文件内容没变化,那么MD5值也不会改变。那么,处理流程就变成了这样:服务器端先判断文件修改时间是否发生了变化,如果发生了变化,那么再对比浏览器传来的If-None-Match即浏览器端保留的E-tag值,如果发生了变化,则证明文件修改了,需要浏览器重新下载文件,如果没有,则证明文件内容没变化,返回304状态码。

    如图,浏览器C要访问服务器S的f文件,服务器S返回了文件最后修改时间Last-Modified和文件的内容标识E-tag,浏览器将这两个字段及其文件缓存了起来

    这里写图片描述

    当文件最后修改时间没变,文件内容也没变的时候,返回304,让浏览器从缓存中拿取文件。

    这里写图片描述

    当文件最后修改时间变了,文件内容没变的时候,返回304,让浏览器从缓存中拿取文件。

    这里写图片描述

    当文件修改时间变了,文件内容也变了的时候,服务器会重新下发新的文件给浏览器。

    这里写图片描述

    此维度让缓存失效牵扯的http字段有点多,我们最后整理一下:
    文件最后修改时间字段:

    • Response:Last-Modified
    • Request:If-Modified-Since

    文件内容标识字段:

    • Response:E-tag
    • Request:If-None-Match

    更多精彩内容,请关注我的微信公众号 互联网技术窝 或者加微信共同探讨交流:

    展开全文
  • HTTP缓存过程详解

    千次阅读 2020-02-25 11:37:00
    HTTP缓存过程详解 http缓存作为面试常考题目,我们必须理解他的详细过程,接下来请大家务必理解并牢记这篇博客的所有内容,大家也不要闲内容多,因为http不管是在面试还是在工作中,真的很重要。而且在面试中,我们...
  • http 缓存分为客户端缓存和服务端缓存 1. 客户端缓存 客户端缓存指的是浏览器缓存, 浏览器缓存是最快的缓存, 因为它直接从本地获取(但有可能需要发送一个请求), 它的优势是可以减少网络流量, 加快请求速度 ...
  • 前端缓存之HTTP缓存

    千次阅读 2019-02-02 15:13:15
    说真的,当自己还很小白的时候,明明修改了JS的内容了,但是就是没有加载成功,那时候感觉好神奇,好没道理。后来知道了这是因为缓存的原因。 说实话,现在基于各种框架的开发,基本...前端分为HTTP缓存和浏览器缓存...
  • Http缓存机制

    千次阅读 2016-07-10 15:07:30
    什么是Http缓存缓存缓存,就是把需要的东西存起来,不需要每次都去请求。主要目的减小服务器压力,放到客户端上来讲,还利于节省流量,还能流畅的把UI显示出来,提高了用户体验。对于Http缓存来讲,主要的就是校验...
  • HTTP缓存机制--客户端缓存

    千次阅读 2017-03-11 17:05:19
    HTTP缓存机制分为两种,客户端缓存和服务端缓存,本文主要对客户端缓存进行简单的分析。 服务端缓存服务端缓存又分为 代理服务器缓存 和 反向代理服务器缓存(也叫网关缓存,比如 Nginx反向代理、Squid等),其实...
  • HTTP缓存详解

    千次阅读 2016-08-21 18:24:20
    原文地址:HTTP缓存详解 本文对我目前所了解的HTTP缓存知识做一个分享,希望能通过本文能让大家对HTTP缓存的基础知识有所了解。 使用缓存有如下几个好处: 缓存减少了冗余的数据传输, 节省了你的网络费用。 ...
  • 浏览器缓存之http缓存和service worker

    千次阅读 2020-06-27 14:10:43
    一、什么是浏览器缓存 以往谈起性能优化,大部分时候都是从后端聊起,数据库的设计,缓存的使用等。... 所以缓存可以带来:减少网络带宽消耗、降低服务器...1、http缓存是基于HTTP协议的浏览器文件级缓存机制。 2、w...
  • 前端基础-浏览器缓存/HTTP缓存机制(面试常考)

    千次阅读 多人点赞 2021-03-28 15:07:55
    浏览器缓存/HTTP缓存机制(面试常考) HTTP报文 HTTP请求(Request)报文 HTTP响应(Response)报文 缓存过程分析 缓存规则 1.强制缓存 1.1Expires 1.2 Cache-Control 2. 缓存存储 3.协商缓存 3.1 Last-Modified / If-...
  • http缓存与cdn缓存配置指南

    千次阅读 2018-11-08 08:33:50
    合理的http缓存与cdn缓存配置可以起到减轻服务器压力,缓解网络瓶颈,提升用户体验等作用,不当的缓存配置却会导致资源无法及时更新,用户体验差异,甚至流程出错等问题。本文主要讲解http缓存与cdn缓存的原理和配置...
  • 浏览器缓存机制、http缓存

    千次阅读 2017-10-21 01:35:56
    借助 HTTP 缓存,Web 站点变得更具有响应性。 缓存作为加快页面加载速度的方法,可以说是必不可少的一个方法,如何能更好地运用缓存来服务客户,首先我们就得了解清楚缓存缓存流程图先上一张从SegmentFault搬运来...
  • Volley HTTP 缓存机制

    千次阅读 2016-05-30 20:05:46
    Volley HTTP 缓存规则在介绍Volley的HTTP缓存机制之前,我们首先来看一下HTTP HEADER中和缓存有关的字段有: 规则 字段 示例值 类型 作用 新鲜度 Expires Sat, 23 Jul 2016 03:34:17 GMT 响应 告诉客户端在...
  • Http缓存机制与原理

    万次阅读 多人点赞 2018-04-21 19:01:00
    Http缓存基本概念 1.1 Http报文 在浏览器和服务器进行Http通信时发送的数据即为Http报文,其中分为两部分: 1. header - 报文的首部或头部,其中保存着各类请求的属性字段,关于Http的缓存相关规则信息均...
  • 浏览器的缓存机制也就是我们说的HTTP缓存机制,其机制是根据HTTP报文的缓存标识进行的,所以在分析浏览器缓存机制之前,我们先使用图文简单介绍一下HTTP报文,HTTP报文分为两种: 同步sau交流学习社区(首发):...
  • HTTP缓存机制与原理详解

    千次阅读 2019-11-24 17:46:11
    借助 HTTP 缓存,Web 站点变得更具有响应性。 缓存分为两点:强制缓存和协商缓存 1.2 - 强制缓存 概念 强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程。 简单...
  • html设置http缓存代码

    万次阅读 2018-06-30 22:16:22
    前端设置http缓存,前端设置html页面缓存方法:静态的html页面想要设置使用缓存需要通过HTTP的META设置expires和cache-control 设置如下网页元信息: <meta http-equiv="Cache-Control" content=&...
  • HTTP缓存机制与CDN

    千次阅读 2019-08-26 16:46:04
    前提:周末看视频了解到一个关键词,http缓存,然后顺带这了解了一下cdn web应用程序的缓存大致分为数据库缓存,服务器端缓存(redis以及CDN 等缓存)、本地缓存。 本地缓存还包含很多内容:http缓存,indexdb,...
  • 面试常见:http缓存机制,浏览器缓存到底是什么?

    千次阅读 多人点赞 2018-12-01 19:53:40
    面试的时候被人问到了这个,实在是答不出来,自己只...所谓的http缓存,就是浏览器自己给你的一个功能,一个缓存数据库,夹在服务端和客户端中间,你只需要设置一些参数即可实现 缓存/不缓存/时效内缓存/时效外缓...
  • 目录三、HTTP 缓存不同种类的缓存(私有)浏览器...通过使用 HTTP缓存,变得更加响应性。 不同种类的缓存 缓存是一种保存资源副本并在下次请求时直接使用该副本的技术。当 web 缓存发现请求的资源已经被存储,它会拦截
  • 彻底理解浏览器的Http缓存机制

    千次阅读 2020-08-01 17:55:56
    浏览器的缓存机制也就是我们说的HTTP缓存机制,其机制是根据HTTP报文的缓存标识进行的,所以在分析浏览器缓存机制之前,我们先使用图文简单介绍一下HTTP报文,HTTP报文分为两种:HTTP请求(Request)报文,报文格式为...
  • HTTP缓存机制 一、缓存是什么 缓存是一种保存资源副本并在下次请求时直接使用该副本的技术 缓存需要合理配置,并不是所有的资源都是永久不变的,他是有生命周期的(不能缓存过期的资源) 1、无缓存机制 对互联网...
  • 摸鱼前端的自检(五)深入HTTP缓存机制及原理

    千次阅读 多人点赞 2019-11-15 11:44:25
    深入HTTP缓存机制及原理 身为一个web开发者,必要的http缓存机制还是要去深入了解,因为在这上面可以做很多的web性能优化。要想成为一个好的架构师,这一环节必不可少。 有兴趣的同学可以去我的github,里面有我的...
  • 彻底弄懂HTTP缓存机制及原理

    千次阅读 2018-10-12 08:45:23
    彻底弄懂HTTP缓存机制及原理 前言 Http 缓存机制作为 web 性能优化的重要手段,对于从事 Web 开发的同学们来说,应该是知识体系库中的一个基础环节,同时对于有志成为前端架构师的同学来说是必备的知识技能。 但是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,003,347
精华内容 401,338
关键字:

http缓存