透视HTTP协议
罗剑锋(Chrono)
奇虎360技术专家,Nginx/OpenResty开源项目贡献者
立即订阅
6077 人已学习
课程目录
已完结 44 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词|To Be a HTTP Hero
免费
破冰篇 (7讲)
01 | 时势与英雄:HTTP的前世今生
02 | HTTP是什么?HTTP又不是什么?
03 | HTTP世界全览(上):与HTTP相关的各种概念
04 | HTTP世界全览(下):与HTTP相关的各种协议
05 | 常说的“四层”和“七层”到底是什么?“五层”“六层”哪去了?
06 | 域名里有哪些门道?
07 | 自己动手,搭建HTTP实验环境
基础篇 (7讲)
08 | 键入网址再按下回车,后面究竟发生了什么?
09 | HTTP报文是什么样子的?
10 | 应该如何理解请求方法?
11 | 你能写出正确的网址吗?
12 | 响应状态码该怎么用?
13 | HTTP有哪些特点?
14 | HTTP有哪些优点?又有哪些缺点?
进阶篇 (8讲)
15 | 海纳百川:HTTP的实体数据
16 | 把大象装进冰箱:HTTP传输大文件的方法
17 | 排队也要讲效率:HTTP的连接管理
18 | 四通八达:HTTP的重定向和跳转
19 | 让我知道你是谁:HTTP的Cookie机制
20 | 生鲜速递:HTTP的缓存控制
21 | 良心中间商:HTTP的代理服务
22 | 冷链周转:HTTP的缓存代理
安全篇 (7讲)
23 | HTTPS是什么?SSL/TLS又是什么?
24 | 固若金汤的根本(上):对称加密与非对称加密
25 | 固若金汤的根本(下):数字签名与证书
26 | 信任始于握手:TLS1.2连接过程解析
27 | 更好更快的握手:TLS1.3特性解析
28 | 连接太慢该怎么办:HTTPS的优化
29 | 我应该迁移到HTTPS吗?
飞翔篇 (4讲)
30 | 时代之风(上):HTTP/2特性概览
31 | 时代之风(下):HTTP/2内核剖析
32 | 未来之路:HTTP/3展望
33 | 我应该迁移到HTTP/2吗?
探索篇 (5讲)
34 | Nginx:高性能的Web服务器
35 | OpenResty:更灵活的Web服务器
36 | WAF:保护我们的网络服务
37 | CDN:加速我们的网络服务
38 | WebSocket:沙盒里的TCP
总结篇 (2讲)
39 | HTTP性能优化面面观(上)
40 | HTTP性能优化面面观(下)
答疑篇 (2讲)
41 | Linux/Mac实验环境搭建与URI查询参数
42 | DHE/ECDHE算法的原理
结束语 (1讲)
结束语 | 做兴趣使然的Hero
透视HTTP协议
登录|注册

20 | 生鲜速递:HTTP的缓存控制

Chrono 2019-07-12
缓存(Cache)是计算机领域里的一个重要概念,是优化系统性能的利器。
由于链路漫长,网络时延不可控,浏览器使用 HTTP 获取资源的成本较高。所以,非常有必要把“来之不易”的数据缓存起来,下次再请求的时候尽可能地复用。这样,就可以避免多次请求 - 应答的通信成本,节约网络带宽,也可以加快响应速度。
试想一下,如果有几十 K 甚至几十 M 的数据,不是从网络而是从本地磁盘获取,那将是多么大的一笔节省,免去多少等待的时间。
实际上,HTTP 传输的每一个环节基本上都会有缓存,非常复杂。
基于“请求 - 应答”模式的特点,可以大致分为客户端缓存和服务器端缓存,因为服务器端缓存经常与代理服务“混搭”在一起,所以今天我先讲客户端——也就是浏览器的缓存。

服务器的缓存控制

为了更好地说明缓存的运行机制,下面我用“生鲜速递”作为比喻,看看缓存是如何工作的。
夏天到了,天气很热。你想吃西瓜消暑,于是打开冰箱,但很不巧,冰箱是空的。不过没事,现在物流很发达,给生鲜超市打个电话,不一会儿,就给你送来一个 8 斤的沙瓤大西瓜,上面还贴着标签:“保鲜期 5 天”。好了,你把它放进冰箱,想吃的时候随时拿出来。
在这个场景里,“生鲜超市”就是 Web 服务器,“你”就是浏览器,“冰箱”就是浏览器内部的缓存。整个流程翻译成 HTTP 就是:
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《透视HTTP协议》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(31)

  • Fstar
    Cache 和 Cookie 的相同点是:都会保存到浏览器中,并可以设置过期时间。
    不同点:
    1. Cookie 会随请求报文发送到服务器,而 Cache 不会,但可能会携带 if-Modified-Since(保存资源的最后修改时间)和 If-None-Match(保存资源唯一标识) 字段来验证资源是否过期。
    2. Cookie 在浏览器可以通过脚本获取(如果 cookie 没有设置 HttpOnly),Cache 则无法在浏览器中获取(出于安全原因)。
    3. Cookie 通过响应报文的 Set-Cookie 字段获得,Cache 则是位于 body 中。
    4. 用途不同。Cookie 常用于身份识别,Cache 则是由浏览器管理,用于节省带宽和加快响应速度。
    5. Cookie 的 max-age 是从浏览器拿到响应报文时开始计算的,而 Cache 的 max-age 是从响应报文的生成时间(Date 头字段)开始计算。

    作者回复: 总结的非常好。

    第三点感觉有点问题,cache缓存的是完整的报文,不单单是body。

    2019-07-13
    1
    15
  • 一步
    对于第二个问题:发现强制刷新后请求头中 没有了 If-None-Match ,而且 Cache-Control: no-cache

    是这个原因吗?

    作者回复: 对,没有条件请求头,那么服务器就无法处理缓存,就只能返回最新的数据。

    2019-07-13
    4
  • Leon📷
    小贴士的nginx计算etag我贴下测试logngx_sprintf(etag->value.data, ""%xT-%xO"", r->headers_out.last_modified_time,
    r->headers_out.content_length_n)相信大家看到这里更清晰明了

    作者回复: great。

    2019-07-21
    3
  • 院长。
    老师我有几个问题想问一下:
    1. F5刷新的时候,请求头加上"Cache-Control: max-age=0",您文章里说,服务器用一个最新生成的报文回应浏览器,那这时候响应返回的应该是"200 OK"吗?为什么我在极客网页版的这个页面刷新后,有个叫"106804"的资源返回的是"304",但是强制刷新是"200 ok",产生的效果好像不同呀。这里是不是应该换一种方式说?感觉强制刷新说的有些简单了。
    2. F5刷新发送的请求头是固定的吗?还是会根据浏览器不同而产生变化?
    3. 200(from memory cache)和200(from disk cache)是针对内存和硬盘的,他们出现的场景分别是什么呢?
    4. HTTP缓存有标准性的流程吗?比如说从我输入URL开始,到后续刷新或者强制刷新等?
    5.对于"must-revalidate"我有疑问,本身存储机制不就是如果不过期的话可以继续使用,过期的话去请求服务器吗?那这个属性还有什么意义呢?
    6. no-cache,no-store,max-age等属性可以共存吗?
    问题有点多,因为网上资料质量参差不齐,解释有些也不全相同,所以在这里咨询下老师,希望老师可以解答一下,或者有推荐的讲述HTTP缓存的文章也可以,谢谢老师

    作者回复: 1.强制刷新请求最新的资源,没有条件请求,所以不会有304,都是200。

    2.每个浏览器可能会有不同,但基本的字段是一样的。

    3.缓存的位置不一样,浏览器会分别存放到内存或者硬盘上,所以会显示来源不同。

    4.http只规定了缓存的用法,具体如何存放如何使用就是客户端自己灵活实现了,怎么方便怎么来。

    5.过期后去验证,如果服务器返回304,那么就可以继续重用缓存,而不用下载整个资源。

    6.可以看一下流程图,不是所以的属性都能共存的。当然如果你要是都写上也不是不可以,那浏览器就会“精神错乱”了。

    2019-07-15
    3
  • Reco
    1. cookie是方便进行身份识,cache是为了减少网络请求。
    2. 强制刷新是因为请求头里的 If-Modified-Since 和 If-None-Match 会被清空所以会返回最新数据

    作者回复: 回答正确,之前是我弄错了。

    2019-07-12
    3
  • Marvin
    我有一个问题,就拿咱们极客时间的网页来说,会请求一个Id-00001.ts的文件,响应头中指示了cache-control: max-age= 7200, 要一个小时才过期,那么为什么每次刷新都是304, 像这种情况不应该直接200 cacahe from disk才对么?为什么明明没有过期还要去服务器协商呢?

    作者回复: 刷新时发的是条件请求,不是普通的请求,所以就必须返回304,告诉浏览器内容没有过期,可以继续用缓存。

    普通请求才会直接检查缓存,然后是200 cacahe from disk。

    2019-08-04
    2
  • 来自地狱的勇士
    老师,既然Etag的算法比较复杂,需要占用服务器资源,那么,实际上服务器会使用Etag吗?看到有的资料说服务器很少会用到Etag,这个说法正确吗?

    作者回复: Nginx和Apache都有etag,但算法不同,但都不会用特别消耗计算资源的算法。

    其他的web服务器就不太清楚了。

    2019-07-12
    2
  • 啦啦啦
    老师,nocache,每次使用前都需要去浏览器问一下有没有过期,这不也是一次请求吗?那不和没有缓存一个意思吗

    作者回复: 不一样,如果服务器返回304,是一个很小的报文,这样浏览器就可以直接重用缓存里的数据,可以节约传输带宽。

    nostore每次都会传输完整的报文,成本高。

    2019-07-12
    2
  • Flourishing
    老师,您这里这么说的:“no-cache:它的字面含义容易与 no-store 搞混,实际的意思并不是不允许缓存,而是可以缓存,但在使用之前必须要去服务器验证是否过期,是否有最新的版本”。
    这个no-cache在这里浏览器请示服务器,如果服务器确定资源没有过期,没有新的版本,那么浏览器就是用缓存的数据了?感觉浏览器只要加上这个,就会获得最新的数据,没有走缓存吧?

    作者回复: 会获得最新的数据,但如果数据不变就直接走缓存,服务器返回304,省去了再次传输数据的成本。

    2019-12-07
    1
  • Khirye
    Hi, 我对缓存控制策略这张流程图有一些疑惑,must-revalidate是指缓存过期之后,必须要向服务器验证缓存,这一步应该是在图中”缓存最多x秒“这个判断之前的吧?
    因为只有缓存超过了max-age的期限,才会进入”must-revalidate的判断“这一步吧?
    烦请解惑,谢谢!

    作者回复: 这张图是“服务器”的缓存策略,也就是说服务器应该如何设置资源的缓存参数,并不是客户端判断缓存的流程。

    只要不是no-store就必然会设置max-age,所以must-revalidate是max-age的一个附加条件。

    2019-11-25
    1
  • walle
    cache-control 中的 private 是如何识别的呢?是根据session吗还是什么方式开识别是私有缓存呢

    作者回复: 缓存策略取决于服务器,它认为这个缓存只能存放在客户端,不能存放在代理上,就设置private。

    与session无关。

    2019-11-15
    1
  • walle
    max-age是不是只对文件请求有效?为什么我看到的例子都是请求文件?

    作者回复: 是的,缓存当然是只对获取文件有效,从服务器上拿到文件然后放入本地缓存。

    2019-11-11
    1
  • Been
    老师有文章说浏览器会在js和图片等文件解析执行后直接存入内存缓存中, 而css文件则会存入硬盘文件中。为什么? 存入内存还是硬盘 是怎么触发 的

    作者回复: http标准没有规定必须要存储在内存或磁盘,如何存储都是由客户端(浏览器)自己决定的。

    我觉得这种说法不准确,其实缓存都会落盘存储,但有的可能会在内存里也放一份,加快访问速度。

    2019-09-04
    1
  • blackjuly
    请问老师,有看到您说的一个ETag解决的问题: 一个文件在一秒内改变多次,可以用ETag来解决文件修改无法被感知到的情况;这个有场景可以举例吗?因为总感觉修改这么频繁的东西应该就不需要缓存了吧

    作者回复: 实际的应用场景我也暂时没见到,但last-modified从运行机制上是存在这个问题的。

    举个不恰当的例子,比如说某个应用的log,开放http接口获取在web上展示,如果log更新频繁,那么就应该用etag。

    2019-08-06
    1
  • 信信
    Cache-Control只是用来决定是否需要验证,而条件参数才是真正决定怎样验证的。如果没有条件参数,就当验证失败处理,返回新数据。

    作者回复: cache-control是管理缓存,不是决定验证的。

    验证的条件是modified-date和etag,由条件请求发起验证。

    2019-07-30
    1
  • WL
    请问老师弱ETag是服务器更新时自己判断本次的更新有没有语义的变化,如果语义有变化就重新生成一个ETag,如果没有变化不重新生成直接使用原来的,请问是这样的流程吗?

    作者回复: 强etag和etag的流程都是一样的,只是计算的方式不同,(即判断是否发生变化的方式不同)。

    你的理解正确。

    2019-07-12
    1
  • 昆虫捕手
    老师,max-age控制的是缓存的生存周期,那么过了这个时长,缓存是否会被浏览器自动清理掉?如果会,那么must-revalidate又是如何使用过期的缓存呢?

    作者回复: http协议里没有对缓存过期后如何处理作出规定,但一般浏览器在过期后还可以再保存更长的时间,这个时候缓存就出于stale(陈旧)状态。

    浏览器也可以按照某种策略清理缓存,例如LRU,或者显得缓存的总大小。

    如果本地缓存没有了,浏览器显然就不需要考虑缓存特性了,直接向服务器获取最新的数据。

    2019-11-26
  • walle
    我的返回头部是有max-age=60的,但是我点击按钮请求数据确实还是200

    作者回复: 看发送的请求

    2019-11-08
  • walle
    我还是不太明白,比如说我想发送一个ajax请求一个json数据,想在60s内下次请求直接返回缓存中的内容应该怎么操作呢?我在后台设置了max-age=60。可以每次返回的还是200,并不是从cache或者disk返回的。

    作者回复: 可以用开发者工具观察一下http请求和响应,看看请求里是否有max-age=0这样的强制刷新字段。

    2019-11-08
  • walle
    no-cache:可以放进冰箱,但吃之前必须问超市有没有更新鲜的,有就吃超市里的;
    那如果没有新鲜的怎么办?

    作者回复: “超市”就是服务器,它必定有资源的最新版本。

    还是不能完全用生活来类别http协议,这个比喻可能会让你有些误解,抱歉。

    2019-11-08
    2
收起评论
31
返回
顶部