HTTP缓存是怎样的一种存在
原文:http://blog.poetries.top/2019/01/02/browser-cache/
情景再现
在某次接口测试中,发现这样一种情况:
产品功能需求是这样的:点击APP页面上的某个按钮,客户端会向服务端发送一个URL请求。
然而Charles抓包发现,第一次点击该按钮时可以正常发送请求,后来再多次点击时就不发送该请求了。
What?。。。不科学呀!
原因排查
首先查看了相关代码,的确是每次执行该点击操作都会发送请求的,没有任何问题。可是为什么后来不再发送请求了呢?
经过深入了解,原来是http缓存导致的。
下面跟着小编学习一下http缓存的相关知识,你就明白是怎么回事了~
知识科普
1. http缓存是怎样的一种存在
1)什么是缓存
我们平时说的缓存,通常指的是Web缓存,它存在于服务器和客户端之间,是一种保存资源副本并在下次请求时直接使用该副本的技术。当Web缓存发现请求的资源已经被存储,它会拦截请求,返回该资源的拷贝,而不会去源服务器重新下载。
2)为什么要使用缓存技术
这是因为,通常情况下通过网络获取内容速度慢成本高,有些响应需要在客户端和服务器之间进行多次往返通信,这就拖延了浏览器可以使用和处理内容的时间,同时也增加了访问者的数据成本。通过缓存,使用资源副本,大大减少获取资源时间,能够减少网络带宽消耗、减少延迟与网络阻塞,同时降低服务器压力,提高服务器性能。
3)http缓存又是怎么回事呢
Web缓存从实现方式大致可以分以下几种类型:
数据库数据缓存;服务器端缓存(包括代理服务器缓存和CDN缓存);
浏览器端缓存;Web应用层缓存。
http缓存就是Web缓存中的浏览器端缓存中的基于http协议实现的那一种,也是平时最常见的一种缓存。
2.http缓存是如何工作的
在这一小节我们先了解下http请求资源缓存的工作流程,然后对流程中细节进行解释说明,你就会对http缓存的工作原理有更深入的认识。
1)http请求资源的工作流程
第一次请求服务器资源时,没有缓存文件,直接向服务器发送请求。流程如下:
第一次请求流程图
第二次及以后再请求服务器资源时,本地已有缓存,请求端会进行资源是否过期及更新等相关判断,决定是否发送请求,或发送带哪些条件式判断字段的请求,服务端视判断结果决定返回的响应状态及是否返回资源。具体流程如下:
非第一次请求流程图
以上是http缓存请求资源的工作流程图,http缓存是通过 HTTP 协议头里的Cache-Control(或 Expires)和 Last-Modified(或 Etag)等字段来控制文件缓存的机制,下面对流程中的各个字段及过程进行详细说明:
1)控制缓存的相关字段
Pragma 设置页面是否缓存,为Pragma则缓存,no-cache则不缓存。它http1.0遗留的字段,当它和cache-control同时存在的时候,会被cache-control覆盖。
Expires 定义缓存过期时间,这个时间相对服务器上的时间而言的,它也是http1.0遗留的字段。如Expires:Thu, 30 Aug 2018 08:14:36 GMT。
Cache-Control 也是定义缓存过期时间,针对"Expires时间是相对服务器而言,无法保证和客户端时间统一"的问题而在http1.1协议中新增的,若报文中同时出现了Expires 和Cache-Control,则以Cache-Control 为准。Cache-Control字段的指令说明如下:
no-cache特别注意,这个不是不被缓存的意思!!是会被缓存的,只不过每次在向客户端提供响应数据时,缓存都要向服务器评估缓存响应的有效性;
no-store响应不被缓存;
max-age设置缓存的存在时间,相对于发送请求的时间,单位为s。在缓存时间内,如果有请求这个资源,浏览器不会发出 http请求,而是直接使用本地缓存的文件。如Cache-Control: max-age=604800。
2)控制协商缓存的字段
Last-Modified/If-Modified-Since
Last-Modified 标示这个响应资源的最后修改时间,如Last-Modified:Tue, 20 Dec 2016 05:01:10 GMT;
If-Modified-Since 当带着If-Modified-Since头访问服务器请求资源时,服务器会检查Last-Modified,如果Last-Modified的时间早于或等于If-Modified-Since则会返回一个不带主体的304响应,否则返回200并重新返回资源。
ETag/If-None-Match
ETag 是一个响应首部字段,它是根据实体内容生成的一段hash字符串,作为资源的唯一标识,由服务端产生,如:ETag:"0q9QPk4kQr2st/XMvRW8yqEt2iw=";
If-None-Match 是一个条件式的请求首部。web服务器收到请求后发现有头If-None-Match则与被请求资源的相应校验串Etag进行比对,如果匹配服务器才会返回带有所请求资源实体的200响应,否则服务器会返回不带实体的304响应,流程见下图。如:If-None-Match:"eOM1rC2lomM4oUbYNn0QD/Y4WLg="。
注:ETag优先级比Last-Modified高,同时存在时会以ETag为准。
协商缓存流程
学以致用
最后,回到文章开头的情景进行分析,根据下图中请求的Response 头部信息中Expires字段得知,http请求的资源有3个小时的缓存时间,而报文中同时也出现了Cache-Control: max-age=10800,也表示资源在本地缓存3个小时,此时无论二者时间是否一致,以Cache-Control为准。这也就解释了后来(3个小时以内)再次点击按钮时不再发送请求的原因。