浏览器缓存策略是什么?请求头和响应头到底包含什么?|掘金征文

3,181 阅读14分钟

HTTP请求头和响应头含义

General-header(通用头部)

Request URL: https://*****.com.cn/index/****List?keyid=100000032&key1Id=2863&key2Id=150600 请求地址

Request Method: GET 请求方法

Status Code: 200 OK 状态码

Remote Address: 192.168.0.181:443 请求的远程地址

Referrer Policy: no-referrer-when-downgrade referrer策略(五种方法)

请求头(客户端->服务器[Request Header])

GET /landingpage/getDealerList?keyid=1000&key1Id=286&key2Id=150600  

HTTP/1.1(请求采用的协议和版本号)

Host: localhost:8080 (连接的目标主机和端口号)

Accept: application/json, text/javascript, */*; q=0.01 (客户端能接收的资源类型) [image/webp,image/apng,image/*,*/*;q=0.8 ]

Accept-Language: zh-CN,zh;q=0.8 (客户端接收的语言类型)

Accept-Encoding: gzip, deflate (客户端能接收的压缩数据的类型)

Connection: keep-alive (维护客户端和服务端的连接关系)

Referer: http://localhost/links.asp (从来于哪里)

User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 (客户端版本号的名字)

** If-Modified-Since: Tue, 22 May 2017 18:23:51 GMT(缓存时间)
Cookie: sensorsdasdkcro11ss=%7B%22distin322ct_id%22%3A%22NaN%22%2C%22first_id%22%3A%2217254cc2025400-3686400-17254cc2026450%22%2C%22props%22%3A%7B%22%24latest_traffic2_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A593%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%7DA%2217254cc202541-0649a2dd8253dd-30667d00-3686400-17254cc2026450%22%7D (客户端暂存服务端的信息)

Date: Tue, 11 Jul 2000 18:23:51 GMT (客户端请求服务端的时间)

响应头(服务端->客户端[Response Header])

HTTP/1.1(响应采用的协议和版本号) 200(状态码) OK(描述信息)
            302(客户端请求服务端,但服务端没有对应的资源,服务端要客户端再次请求找其它的服务端,即客户端二次请求,重定向) 会发送两个请求
            307(客户端请求服务端,但服务端没有对应的资源,服务端自行再次请求找其它的服务端,即客户端一次请求,转发)
            304(客户端请求服务端,此时客户端缓存中有,无需再从服务端下载新的内容,服务端叫客户端自行找缓存,优化)
            500(客户端请求的资源,服务端存在,但在执行时出错)
            
Location: http://www.baidu.com  (服务端需要客户端访问的页面路径)

Server:OpenResty 俺们公司用的平台

Refresh: 1;url=http://www.baidu.com (服务端要求客户端1秒钟后,刷新,然后访问指定的页面路径)

Transfer-Encoding: chunked (分块传递数据到客户端)

Set-Cookie:SS=Q0=5Lb_nQ; path=/search (服务端发送到客户端的暂存数据)

** Last-Modified: Mon, 22 May 2017 09:41:07 GMT (服务端对该资源最后修改的时间)

** Expires: -1//3种 (服务端禁止客户端缓存页面数据) 【Mon, 28 Sep 1970 05:00:00 GMT】

** Cache-Control: no-cache, no-store, must-revalidate (服务端禁止客户端缓存页面数据) 

** Pragma: no-cache (服务端禁止客户端缓存页面数据)

** etag: W/"5f017c5c-a8e"

Connection: close(1.0)/(1.1)Keep-Alive (维护客户端和服务端的连接关系) 

Content-Language: zh-cn  (服务端发送的语言类型)【图片没有】

Content-Type:application/json;charset=UTF-8 【image/gif】(服务端发送的类型及采用的编码方式)

Content-Encoding: gzip (服务端能够发送压缩编码类型)

Content-Length: 888 (服务端发送的压缩数据的长度)

Content-Disposition: attachment; filename=aaa.zip (服务端要求客户端以下载文件的方式打开该文件)

Date: Mon, 22 May 2017 18:41:07 GMT (服务端响应客户端的时间)

谈一下Content-Type

MediaType,即是Internet Media Type,互联网媒体类型;也叫做MIME类型,在Http协议消息头中,使用Content-Type来表示具体请求中的媒体类型信息 例如: Content-Type: text/html;charset:utf-8;

常见的媒体格式类型如下:

text/html : HTML格式
text/plain :纯文本格式
text/xml :XML格式
image/gif :gif图片格式
image/jpeg :jpg图片格式
image/png:png图片格式

以application开头的媒体格式类型:

application/xhtml+xml :XHTML格式
application/xml: XML数据格式
application/atom+xml:Atom XML聚合格式
application/json: JSON数据格式
application/pdf:pdf格式
application/msword: Word文档格式
application/octet-stream: 二进制流数据(如常见的文件下载)
application/x-www-form-urlencoded : <form encType=””>中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)

另外一种常见的媒体格式是上传文件之时使用的:

multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式

再谈一下响应头中的status

    1xx:接受,继续处理
    200:成功,并且返回数据
    201:接受请求,并且已经创建资源
    202:接受请求
    203:请求成功,但是未授权
    204:成功,但是没有内容
    205:成功,重置内容
    206:成功,部分内容
    301:永久移动,重定向
    302:临时重定向,原先url可用
    304:资源没变,可以继续使用缓存
    305:需代理访问
    400:请求语法错误
    401:要求身份验证
    403:拒绝请求
    404:资源不存在
    500:服务器错误

Query String Parameters 参数格式化

adtag: 123456

什么是浏览器缓存?

简单来说,浏览器缓存就是把一个已经请求过的Web资源(如htmlimgjsdata等)拷贝一份副本储存在浏览器中。缓存会根据进来的请求保存输出内容的副本。当下一个请求来到的时候,如果是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发送请求。比较常见的就是浏览器会缓存访问过网站的网页,当再次访问这个URL地址的时候,如果网页没有更新,就不会再次下载网页,而是直接使用本地缓存的网页。只有当网站明确标识资源已经更新,浏览器才会再次下载网页。至于浏览器和网站服务器是如何标识网站页面是否更新的机制,

第一次打开浏览器页面(全部都是从服务器第一次请求的数据)

第二次打开浏览器页面(from disk cache、from memory cache)

为什么使用浏浏览器缓存呢?


1、减少网络宽带的损耗
对于网络的运营者来说,流量和宽带都是金钱,特别是大型互联网公司。更是可以节省几十万上百万的支出。使用缓存只会有极小部分网络流量去请求服务器资源,降低运营成本。
2、降低服务器压力
网络资源设定有效期之后,用户可以重复使用本地的缓存,减少对源服务器的请求,间接降低服务器的压力。同时,搜索引擎的爬虫机器人也能根据过期机制降低爬取的频率,也能有效降低服务器的压力。
3、可以有效的减少网络延迟,加快页面的打开速度
带宽对于个人网站运营者来说是十分重要,而对于大型的互联网公司来说,可能有时因为钱多而真的不在乎。那Web缓存还有作用吗?答案是肯定的,对于最终用户,缓存的使用能够明显加快页面打开速度,达到更好的体验。

浏览器的缓存规则?


对于浏览器端的缓存来讲,这些规则是在HTTP协议头和HTML页面的Meta标签中定义的。他们分别从新鲜度和校验值两个维度来规定浏览器是否可以直接使用缓存中的副本,还是需要去源服务器获取更新的版本。
新鲜度(过期机制):也就是缓存副本有效期。一个缓存副本必须满足以下条件,浏览器会认为它是有效的,足够新的:
1. 含有完整的过期时间控制头信息(HTTP协议报头),并且仍在有效期内;
2. 浏览器已经使用过这个缓存副本,并且在一个会话中已经检查过新鲜度;
满足以上两个情况的一种,浏览器会直接从缓存中获取副本并渲染。
校验值(验证机制):服务器返回资源的时候有时在控制头信息带上这个资源的实体标签Etag(Entity Tag),它可以用来作为浏览器再次请求过程的校验标识。如过发现校验标识不匹配,说明资源已经被修改或过期,浏览器需求重新获取资源内容。

浏览器缓存的控制?

Expires策略ExpiresWeb服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。不过ExpiresHTTP 1.0的东西,现在默认浏览器均默认使用HTTP 1.1,所以它的作用基本忽略。Expires的一个缺点就是,返回的到期时间是服务器端的时间,这样存在一个问题,如果客户端的时间与服务器的时间相差很大(比如时钟不同步,或者跨时区),那么误差就很大,所以在HTTP 1.1版开始,使用Cache-Control: max-age=秒替代。

Cache-control策略(重点关注)Cache-ControlExpires的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。只不过Cache-Control的选择更多,设置更细致,如果同时设置的话,其优先级高于Expires

值可以是public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age
各个消息中的指令含义如下:

Public指示响应可被任何缓存区缓存。 Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效 no-cache指示请求或响应消息不能缓存,该选项并不是说可以设置”不缓存“,容易望文生义~ no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存,完全不存下來。 max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。 min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。 max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。

Last-Modified/If-Modified-Since:Last-Modified/If-Modified-Since要配合Cache-Control使用

Last-Modified:标示这个响应资源的最后修改时间。web服务器在响应请求时,告诉浏览器资源的最后修改时间。 If-Modified-Since:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Last-Modified声明,则再次向web服务器请求时带上头If-Modified-Since,表示请求时间。web服务器收到请求后发现有头If-Modified-Since则与被请求资源的最后修改时间进行比对。若最后修改时间较新,说明资源又被改动过,则响应整片资源内容(写在响应消息包体内),HTTP 200;若最后修改时间较旧,说明资源无新修改,则响应HTTP 304(无需包体,节省浏览),告知浏览器继续使用所保存的cache

Etag/If-None-Match:Etag/If-None-Match也要配合Cache-Control使用

Etagweb服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定)。Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。 If-None-Match:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Etage声明,则再次向web服务器请求时带上头If-None-MatchEtag的值)。web服务器收到请求后发现有头If-None-Match则与被请求资源的相应校验串进行比对,决定返回200304

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

Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间 如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形 Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-ModifiedETag一起使用时,服务器会优先验证ETag

yahooYslow法则中则提示谨慎设置Etag:需要注意的是分布式系统里多台机器间文件的last-modified必须保持一致,以免负载均衡到不同机器导致比对失败,Yahoo建议分布式系统尽量关闭掉Etag(每台机器生成的etag都会不一样,因为除了last-modified, inode也很难保持一致)。

Pragma行是为了兼容HTTP1.0,作用与Cache-Control: no-cache是一样的。

浏览器HTTP请求流程

第一次请求的时候

再次请求时候

不能缓存的请求:


当然并不是所有请求都能被缓存,无法被浏览器缓存的请求如下:
1. HTTP信息头中包含Cache-Control:no-cache,pragma:no-cache(HTTP1.0),或Cache-Control:max-age=0等告诉浏览器不用缓存的请求
2. 需要根据Cookie,认证信息等决定输入内容的动态请求是不能被缓存的
3. 经过HTTPS安全加密的请求(有人也经过测试发现,ie其实在头部加入Cache-Control:max-age信息,firefox在头部加入Cache-Control:Public之后,能够对HTTPS的资源进行缓存
4. POST请求无法被缓存
5. HTTP响应头中不包含Last-Modified/Etag,也不包含Cache-Control/Expires的请求无法被缓存

浏览器是根据什么决定「from disk cache」与「from memory cache」?

看了看知乎上大家都在纠结这个东西,找了两个比较靠谱的来回答:

1. 先去内存看,如果有,直接加载

2. 如果内存没有,择取硬盘获取,如果有直接加载

3. 如果硬盘也没有,那么就进行网络请求

4. 加载到的资源缓存到硬盘和内存

先来说说 内存缓存的特点 快(读取快) 时效性(进程死,他也死)

第一个现象(以图片为例):访问-> 200 -> 退出浏览器再进来-> 200(from disk cache) -> 刷新 -> 200(from memory cache)

第二个现象(以图片为例):只要图片是base64 我看都是from memroy cache

第三个现象(以js css为例):大型的js css文件都是直接disk cache

第四个现象:隐私模式下,几乎都是 from memroy cache