前段时间去面试移动端的H5开发工程师,在最后面试的时候被问到了max-age Expires Etag有什么不同,在什么情况下应用,当时乱编了一通,自我感觉良好,结果…… 大家懂得,现在讲他们几个的区别以及如何应用进行一下总结,方便后续查看。
Expires
http/1.0中定义的header,是最基础的浏览器缓存处理,表示资源在一定时间内从浏览器的缓存中获取资源,不需要请求服务器获取资源,从而达到快速获取资源,缓解服务器压力的目的。
在response的header中的格式为:Expires: Thu, 01 Dec 1994 16:00:00 GMT (必须是GMT格式)
应用:
1、可以在html页面中添加<meta http-equiv="Expires" content="Thu, 01 Dec 1994 16:00:00"/> 来给页面设置缓存时间。
2、对于图片、css等文件则需要在IIS或者apache等运行容器中进行规则配置来让容器在请求资源的时候添加在responese的header中。
Last-modified
望文知义,根据这个词条的直译应该是上次修改(时间),通过修改服务器端的文件后再请求,发现response的header中的Last-modified改变了
更新原理:
1、在浏览器首次请求某个资源时,服务器端返回的状态码是200 (ok),内容是你请求的资源,同时有一个Last-Modified的属性标记(Reponse Header),标识此文件在服务期端最后被修改的时间,格式:Last-Modified:Tue, 24 Feb 2009 08:01:04 GMT
2、浏览器第二次请求该资源时,根据HTTP协议的规定,浏览器会向服务器传送If-Modified-Since报头(Request Header),询问该文件是否在指定时间之后有被修改过,格式为:If-Modified-Since:Tue, 24 Feb 2009 08:01:04 GMT
3、如果服务器端的资源没有变化,则服务器返回304状态码(Not Modified),内容为空,这样就节省了传输数据量。当服务器端代码发生改变,则服务器返回200状态码(ok),内容为请求的资源,和第一次请求资源时类似。从而保证在资源没有修改时不向客户端重复发出资源,也保证当服务器有变化时,客户端能够及时得到最新的资源。
注:如果If-Modified-Since的时间比服务器当前时间(当前的请求时间request_time)还晚,会认为是个非法请求
ETag
http/1.1 中增加的header,HTTP协议规格说明定义ETag为“被请求变量的实体值” 。另一种说法是,ETag是一个可以与Web资源关联的记号(token)。典型的Web资源可以一个Web页,但也可能是JSON或XML文档。服务器单独负责判断记号是什么及其含义,并在HTTP响应头中将其传送到客户端。
ETag的格式
不同类型的Web服务器生成ETag的策略以及生成的格式是不同的:
1、apache1.3和2.x的Etag格式是:inode-size-timestamp。
2、IIS5.0和6.0的Etag格式为Filetimestamp:Changenumber。
更新原理:
1、当浏览器首次请求资源的时候,服务器会返回200的状态码(ok),内容为请求的资源,同时response header会有一个ETag标记,该标记是服务器端根据容器(IIS或者Apache等等)中配置的ETag生成策略生成的一串唯一标识资源的字符串,ETag格式为 ETag:"856247206"
2、当浏览器第2次请求该资源时,浏览器会在传递给服务器的request中添加If-None-Match报头,询问服务器改文件在上次获取后是否修改了,报头格式:If-None-Match:"856246825"
3、服务器在获取到浏览器的请求后,会根据请求的资源查找对应的ETag,将当前服务器端指定资源对应的Etag与request中的If-None-Match进行对比,如果相同,说明资源没有修改,服务器返回304状态码(Not Modified),内容为空;如果对比发现不相同,则返回200状态码,同时将新的Etag添加到返回浏览器的response中。
max-age
Cache-Control中设置资源在本地缓存时间的一个值,单位为:秒(s),其他值还有private、no-cache、must-revalidate等
几者之间的关系
Expires 与max-age
Expires存在HTTP 1.0 版本, 标识本地缓存的截止时间,允许浏览器在这个时间之前不去向服务器端发送请求验证资源是否有更新
max-age是HTTP 1.1版本新增的, 标识资源可以在本地缓存多少秒,存储的是更新间隔。
Expires 的一个缺点就是,返回的到期时间是服务器端的时间,这样存在一个问题,如果浏览器所在机器的时间与服务器的时间相差很大,那么误差就很大,所以在HTTP 1.1版开始,使用Cache-Control: max-age替代。
注: 如果max-age和Expires同时存在,则被Cache-Control的max-age覆盖。
Expires =max-age + “每次下载时的当前的request时间”
所以一旦重新下载的页面后,expires就重新计算一次,但last-modified不会变化
Last-Modified和Expires
使用Last-Modified标识由于在资源未修改时返回的response内容为空,可以节省一点带宽,但是还是逃不掉发一个HTTP请求出去,需要浏览器连接一次服务器端。
而Expires标识却使得浏览器干脆连HTTP请求都不用发,但是当用户使用F5或者点击Refresh按钮的时候,就算URI设置了Expires,浏览器一样也会发一个HTTP请求给服务器端,所以,Last-Modified还是要用的,而且要和Expires一起用。
Etag和Expires
和 Last-Modified和Expires的情况类似,需要Expires控制请求的频率,Etag在强制刷新时作为保障
Last-Modified和Etag
分布式系统里多台机器间文件的last-modified必须保持一致,以免负载均衡到不同机器导致比对失败,一般建议分布式系统尽量关闭掉Etag(每台机器生成的etag都会不一样)
Last-Modified和ETags请求的http报头一起使用,服务器首先产生Last-Modified/Etag标记,服务器可在稍后使用它来判断页面是否已经被修改,来决定文件是否继续缓存
过程如下:
1.客户端请求一个页面(A)。
2.服务器返回页面A,并在给A加上一个Last-Modified/ETag。
3.客户端展现该页面,并将页面连同Last-Modified/ETag一起缓存。
4.客户再次请求页面A,并将上次请求时服务器返回的Last-Modified/ETag一起传递给服务器。
5.服务器检查该Last-Modified或ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304和一个空的响应体。
从资源更新原理来看Last-Modified和Etag基本是类似的,那为什么http协议中要搞2个标识呢?
Last-Modified存在的问题:
1、在集群服务器上各个服务器上的文件时间可能不同。
2、如果用旧文件覆盖新文件,因为时间更前,浏览器不会请求这个更旧的文件。
3、时间精度为s级,对文件修改精度有严格要求的场景不能满足