带你10分钟了解http的cache设置

cache

http的cache是以URL为key的,因此不想用之前的缓存,则能够更换URL,例如加不一样的query、改文件名(如加上MD5或版本号)等。URL是忽略锚点的。git

浏览器检验vs服务器检验

Expires、 Cache-Control、Last-Modified、ETag是RFC2616(HTTP/1.1)协议中和网页缓存相关的几个字段。 前两个用来控制缓存的失效日期,浏览器可经过它来断定,需不须要发出HTTP请求; 后两个用来验证网页的有效性,服务器端利用它来验证这个文件是否须要从新返回。github

Last-Modified VS Etag

若是服务器端同时设置了Etag和Expires时,Etag原理一样,即与Last-Modified/Etag对应的HttpRequestHeader:If-Modified-Since和If-None-Match。咱们能够看到这两个Header的值和WebServer发出的Last-Modified,Etag值彻底同样;在彻底匹配If-Modified-Since和If-None-Match即检查完修改时间和Etag以后,服务器才能返回304.算法

既然有了Last-Modified,为何还要用ETag字段呢?由于若是在一秒钟以内对一个文件进行两次更改,Last-Modified就会不正确。所以,HTTP/1.1利用Entity Tag头提供了更加严格的验证。浏览器

注意:分布式系统里多台机器间文件的last-modified必须保持一致,以避免负载均衡到不一样机器致使比对失败缓存

分布式系统尽可能关闭掉Etag(每台机器生成的etag都会不同)服务器

Last-Modified vs Expires

Last-Modified标识可以节省一点带宽,可是仍是逃不掉发一个HTTP请求出去,并且要和Expires一块儿用。而Expires标识却使得浏览器干脆连HTTP请求都不用发,好比当用户F5或者点击Refresh按钮的时候就算对于有Expires的URI,同样也会发一个HTTP请求出去,因此,Last-Modified仍是要用的,并且要和Expires一块儿用。网络

304 vs 200(from cache)

  • 304由last-modified/etag控制,内容为空负载均衡

  • 200(from cache)由expires/cache-control控制,浏览器本身的内存分布式

    • expires,http1.0有效,是绝对时间,客户端时间
    • cache-control,1.1有效,相对时间,会覆盖expires,只要有效,浏览器访问本身的缓存

Cache-Control: max-age=秒 vs Expires

Expires = 时间,HTTP 1.0 版本,缓存的载止时间,容许客户端在这个时间以前不去检查(发请求) max-age = 秒,HTTP 1.1版本,资源在本地缓存多少秒。 若是max-age和Expires同时存在,则被Cache-Control的max-age覆盖。ui

Expires 的一个缺点就是,返回的到期时间是服务器端的时间,这样存在一个问题,若是客户端的时间与服务器的时间相差很大,那么偏差就很大,因此在HTTP 1.1版开始,使用Cache-Control: max-age=秒替代。

Expires =max-age +   “每次下载时的当前的request时间”

因此一旦从新下载的页面后,expires就从新计算一次,但last-modified不会变化

应用 HTTP/1.1 版本的缓存服务器遇到同时存在 Expires 首部字段的情 况时,会优先处理 max-age 指令,而忽略掉 Expires 首部字段。而 HTTP/1.0 版本的缓存服务器的状况却相反,max-age 指令会被忽略

cache-control

  • no-cache

    并不表明彻底的禁用缓存,而是表明会每次去核对服务端的 Etag,若是相同,那么就不会去服务端下载完整的资源,返回一个 304 Not Modified。(最长缓存 3 年)

  • no-store

    才是真正的禁用缓存,它表示每次服务端都会去下载最新的资源。(固然,一般彷佛都用不上)。

  • max-age

    最大缓存时长,max-age不要大于2^31,以避免大于int32而变成负数。

    在Response中设置max-age的时间信息,能够在客户端生成缓存文件,在缓存不过时的状况下,客户端不会直接向服务器请求数据,在缓存过时的状况下,客户端会向服务器直接请求生成新的缓存。

    若是同时设置了Response和Request中的max-age 缓存时间,若是Request中的max-age时间小于Response中的max-age时间,客户端会根据Request中max-age时间周期去直接进行网络请求,若是碰到断网或者网络请求不通的状况,即便缓存还在有效期内(Response中设置的max-age时间足够大),在Request设置的max-age过时以后,APP也会直接去进行网络请求。

    所以能够考虑在客户端的设计中一个和好的网络缓存场景,用Response的max-age控制缓存的时间,用Request中max-age控制刷新的时间和机制

  • max-stale

    缓存时长过时之后,还能够有效。好比如今max-age:60秒,那么max-stale:60秒,如今的缓存时长就是120秒,

  • min-fresh

    客户机能够接收响应时间小于当前时间加上指定时间的响应。   

    设定可以容忍的最小新鲜度(缓存时长)。min-fresh标示了客户端不肯意接受新鲜度很少于当前的age加上min-fresh设定的时间之和的响应。

  • no-transfrom

    使用 no-transform 指令规定不管是在请求仍是响应中,缓存都不能改 变实体主体的媒体类型。

  • only-if-cache

    使用 only-if-cached 指令表示客户端仅在缓存服务器本地缓存目标资源的状况下,才会要求其返回。换言之,该指令要求缓存服务器不从新加载响应,也不会再次确认资源有效性。若发生请求缓存服务器的本地缓存无响应,则返回状态码 504 Gateway Timeout。

  • cache-extension

    经过 cache-extension 标记(token),能够扩展 Cache-Control 首部字 段内的指令。

  • public 和 private 的差异

    主要在于若是是有用户认证环节的页面,设置为private 就只有终端浏览器会缓存,中间 CDN 并不会缓存,而设置为 public,则会在每个环节缓存。默认不须要设置 public,由于 max-age 已经代表能够由各个环节缓存了(单位为秒)。此刻若是命中缓存,则不会再去请求服务器核对 Etag,而是直接返回 200(from disk)。

    因为 public 会在每个环节缓存,若是对修改更新预览又强需求的网页,那么最好不要使用这一缓存策略,不然还须要刷新 CDN 源

  • s-max-age

    和max-age相似,它们的不一样点是 s- maxage 指令只适用于供多位用户使用的公共缓存服务器

  • must-revalidate

    使用 must-revalidate 指令,代理会向源服务器再次验证即将返回的响应缓存目前是否仍然有效。若代理没法连通源服务器再次获取有效资源的话,缓存必须给客户端 一条 504(Gateway Timeout)状态码。另外,使用 must-revalidate 指令会忽略请求的 max-stale 指令(即便已 经在首部使用了 max-stale,也不会再有效果)。

  • proxy-revalidate

    proxy-revalidate 指令要求全部的缓存服务器在接收到客户端带有该指 令的请求返回响应以前,必须再次验证缓存的有效性。

Expires

表明何时过时,时间与客户端时间比较
复制代码

Last-Modified

上次修改时间,注:若是If-Modified-Since的时间比服务器当前时间(当前的请求时间request_time)还晚,会认为是个非法请求。
复制代码

Etag

被请求变量的实体标记,标识,等于告诉Client端,你拿到的这个的资源有表示ID:5d8c72a5edda8d6a:3239。当下次须要发Request索要同一个URI的时候,浏览器同时发出一个If-None-Match报头(Http RequestHeader)此时包头中信息包含上次访问获得的Etag:“5d8c72a5edda8d6a:3239″标识。

Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后获得的

容量

容量是以总体计算的,不区分Domain。

Android WebView是20MB。iOS WebView也多是20MB(根据https://github.com/gnustep/base/blob/master/Source/NSURLCache.m,不肯定GNUstep是否也是Apple的源码)。

PC上的Chromium是以80MB为基准结合磁盘可用空间来考虑的,最大是320MB。算法是:

if (可用空间 < 100MB)
  容量 = 80%的可用空间  // < 80MB
else if (可用空间 < 800MB)
  容量 = 80MB
else if (可用空间 < 2000MB)  // 约2GB
  容量 = 10%的可用空间  // < 200MB
else if (可用空间 < 20000MB)  // 约20GB
  容量 = 200MB
else  // >= 20000MB
  容量 = Math.min(1%的可用空间, 320MB)  // 200MB <= 容量 <= 320MB

复制代码

淘汰

淘汰算法是通常是LRU,

浏览器须要对缓存的文件进行索引,若是这个索引损坏,浏览器会删除全部的缓存。用户也能够经过设置界面来删除。此外,第三方程序也会作清理。

请求时缓存指令

  • no-cache

  • If-Modified-Since

    值是上次请求的last-modified值,询问服务器

  • If-None-Match

    值是客户端查询的etag的值,询问服务器是否变化

  • no-store

  • max-age

  • max-stale

  • min-fresh

  • only-if-cached

响应消息中的指令

  • public

  • private

  • no-cache

  • Last-Modified

    此文件在服务期端最后被修改的时间

  • Etag

    服务器响应时给请求URL标记,并在HTTP响应头中将其传送到客户端。Etag:“5d8c72a5edda8d6a:3239″

  • no- store

  • no-transform

  • must-revalidate

  • proxy-revalidate

  • max-age

相关文章
相关标签/搜索