手记

学而时习之网络篇: 又是HTTP缓存的锅 !

前言

春来了, 万物复苏, 阳光明媚, 一处农家院子前的一块空地上, 小小的藤椅上挤着一个 葛优躺的胖子, 远远看过去他那像极了游泳圈的小肚子上还放着一台 MacBook Pro 笔记本, 凑近了看笔记本屏幕上开着一个叫 码云企业版 的网站, 上面满屏都是 一位叫 Yuki 的测试妹子 指给名为 张大胖的 bug。


大胖挠了挠头发了条语音给 Yuki:
"虽说哥这个假期 王者荣耀上分6到飞起, 但这几天不看代码, 我这bug怎么越改越多了"

看到消息的 Yuki 白了白眼说到:
"你的Bug全组第一多, 至今无人超越, 心里没点数吗?"

"头发长见识短, 你是没有看到我的交付时间,交付代码量还是全公司第一呢 !"
张大胖撅着嘴 嘴嘟嘟囔囔的回答道

Yuki 无语道:
"快去改Bug吧, 后天就到交付日期了 !"

张大胖听完埋头执行起了测试用例. 看着测试用例覆盖率 100%, 随后陷入了沉思. 良久后说道:
"我这边单元测试没问题啊, 前端也没有改啊. 是不是又是 HTTP缓存的问题 ?"

"我天天用 360 给电脑清理缓存, 那还有什么 HTTP缓存 !"
Yuki 疑惑的摸摸头道:

张大胖一听知道 套(chui)近(niou)乎的机会来了道:
"登一下 TeamViewer 哥远程讲给你听 !"

春日 【朝代】宋

胜日寻芳泗水滨,无边光景一时新。

等闲识得东风面,万紫千红总是春。

奠定互联网时代的基石

1946年2月14日 随着世界上第一台通用计算机的诞生, 摩尔定律见证着 计算机从神秘不可近的庞然大物变成多数人赖以生存的工具,改变人们生活的IT 技术从学术界走向工业界从而进入无数个普通家庭。

NetWork 信息互联解决了世界上的信息不对称, 人们逐渐从对立中消除矛盾走向 世界人民大团结万岁 !

2019年1月30日 We Are Social&Hootsuite联合发布了2019年数字报告,报告显示,全球人口数76.76亿人,其中手机用户51.1亿人,网民43.9亿人,有34.8亿人活跃在社交媒体上。

报告还显示,全球互联网用户平均每天上网时间为6小时42分钟,也就是人们生活中1/4的时间都在上网。这一数字略低于去年的6小时49分钟。

随着互联网的兴起, 各厂DAU几何倍暴涨, 无数人靠着解决日常生活中的痛点而发家致富, 而繁荣背后是无数互联网从业者日以继夜的辛劳付出。

对于程序员而言业务系统 DAU 50万 与 DAU 5000万 在架构上是有着天壤之别的, 一个优秀的缓存策略可以缩短网页请求资源的时延,减少延迟提高并发,并且由于冗余的数据可以重复利用,还可以减少网络IO,缓解并发瓶颈。 在用户的DAU暴涨中各种的缓存手段也层出不穷, 主要分为 服务端缓存, 客户端缓存.

  • 服务端 (缓存方案 (ps:缺点)/技术实现)
    • 热点数据缓存 (ps:缓存雪崩) / Redids, Memcached
    • 进程缓存 (ps:缓存共享麻烦) / Ehcache, Guave Cache, Hibernate
    • DNS&CDN网络缓存 (ps:自建维护贵) / Squid , 云计算
  • 客户端
    • HTTP缓存 (ps:容易被测试找bug) / HTTP协议+Nginx&Tomcat
    • 数据预缓存 (ps:局限于微信小程序) / 周期性更新&数据预拉取
    • 内存&本地缓存(ps: 需要管理维护) / Vuex, LocalStorage&SessionStorage

HTTP缓存最佳Demo

HTTP缓存是一个比较复杂但是又比较重要的机制, 我们浏览一个页面时发现发现异常的情况下, 通常第一个怀疑是不是浏览器做了缓存, 所以一般的做法就是Ctrl+F5 组合键重新请求一次这个页面, 重新请求的页面肯定是最新的页面。

为什么 重新请求就一定能够请求到没有缓存的页面呢?

  • 首先是在浏览器端, 如果是按 Ctrl+F5 组合键刷新页面, 那么浏览器会直接向目标 URL 发送请求, 而不会使用浏览器缓存的数据。
  • 其次即使请求发送到服务器端, 也有可能访问到的是缓存的数据。
  • 所以为了保证用户能够看到最新的数据, 必须通过HTTP 来控制。

图 1 所示 当我们使用 Ctrl+F5组合键刷新一个页面时, 在HTTP的请求头中会增加一些请求头.来告诉服务器我们要获取的是最新数据而不是缓存.

HTTP缓存的两大阵营

强缓存

服务端告知客户端缓存存活时间后,由客户端判断并决定是否使用CDN缓存。

即首次发起请求时,服务端会在Response Headers 中写入 缓存存活时间。当请求再次发出时,如果缓存没有过期,将直接从 CDN 缓存服务器获取资源,而不会再与服务器发生通信。


协商缓存

由服务端决定并告知客户端是否使用缓存。

协商缓存机制下,浏览器需要向服务器去询问缓存的相关信息,进而判断是重新发起请求、下载完整的响应,还是从本地获取缓存的资源。

各类HTTP缓存的特点以及应用场景

  • 强缓存(HTTP标准)
    • Cache-Control(HTTP1.1)&Pragma(HTTP1.0)
    • Expires (HTTP1.0)
  • 协商缓存
    • Last-Modifiy/if-Modify-Since(HTTP1.1)
    • ETag/if-None-Match(HTTP1.1)

Cache-Control&Pragme

Pragma: no-cache是为了兼容 HTTP1.0 ,Cache-Control: no-cache 是 HTTP 1.1提供的, 个人认为 Pragma 字段为上古时期的设计Bug, 两者相辅相成用于指定所有缓存机制在整个请求/响应链中必须服从的命令, 不仅可以控制浏览器缓存还可以控制代理服务器,CDN服务器等

多选值 作用
Public 所有内容都将被缓存,在响应头中设置
Private 内容只缓存到私有缓存中,在响应头中设置
no-cache 所有内容都不会被缓存,在请求头和响应头中设置
no-store 所有内容都不会被缓存到缓存或 Internet 临时文件中, 在响应头中设置
must-revalidation/proxy-revalidation 如果缓存的内容失效, 请求必须发送到服务器/代理以进行重新验证,在请求头中设置
max-age=xxx 缓存的内容将在 xxx 秒后失效, 这个选项只有在 HTTP 1.1 中可用, 比 Last-Modified 生效优先级高, 在响应头中设置

Expires

Exprires 的值为响应头返回的数据到期时间 Expires: Sat, 25 Feb 2020 18:26:17 GMT , 当浏览器再次请求时的请求时间小于之前返回的 Exprires 时间,则直接使用缓存数据。但由于服务端时间和客户端时间可能有误差,这也将导致缓存命中的误差.

Last-Modifiy/if-Modify-Since

服务器在响应请求时,会在响应头上 用 Last-Modified 告诉浏览器资源的最后修改时间. 例: last-modified: Thu, 14 Nov 2019 04:56:25 GMT , 浏览器再次请求服务器的时候,请求头会包含此字段,后面跟着在缓存中获得的最后修改时间。服务端收到此请求头发现有if-Modified-Since,则与被请求资源的最后修改时间进行对比,如果一致则返回304和响应报文头,浏览器只需要从缓存中获取信息即可。
从字面上看,就是说:从某个时间节点算起,是否文件被修改了

  • 如果真的被修改:那么开始传输响应一个整体,服务器返回状态码:200 OK
  • 如果没有被修改:那么只需传输响应header,服务器返回状态码:304 Not Modified

ETag/if-None-Match

Etag:
服务器响应请求时,通过此字段告诉浏览器当前资源在服务器生成的唯一标识(生成规则由服务器决定)
If-None-Match:
再次请求服务器时,浏览器的请求报文头部会包含此字段,后面的值为在缓存中获取的标识。服务器接收到次报文后发现If-None-Match则与被请求资源的唯一标识进行对比。

不同,说明资源被改动过,则响应整个资源内容,返回状态码200。
相同,说明资源无新修改,则响应header,浏览器直接从缓存中获取数据信息。返回状态码304.

但是实际应用中由于Etag的计算是使用算法来得出的,而算法会占用服务端计算的资源,所有服务端的资源都是宝贵的,所以就很少使用Etag了。

Etag 强验证器和弱验证器
ETag 分为强验证器和弱验证器。

强验证器要求文档的每个字节都相等,而弱验证器只要求文档的含义相等

  • 强验证:

  • 弱验证(前面会加上‘ W/’ 来标识):

不同刷新的请求执行过程

  • 浏览器地址栏中写入URL,回车
    浏览器发现缓存中有这个文件了,不用继续请求了,直接去缓存拿。(最快)
  • F5就是告诉浏览器,别偷懒,好歹去服务器看看这个文件是否有过期了。于是浏览器就胆胆襟襟的发送一个请求带上If-Modify-since。
  • Ctrl+F5 告诉浏览器,你先把你缓存中的这个文件给我删了,然后再去服务器请求个完整的资源文件下来。于是客户端就完成了强行更新的操作.

HTTP缓存最佳实践

张大胖长长松了口气说: "我看你应该是在家办公, 用的自己电脑没有配置HTTP缓存强制刷新!"

"矮油, 这样子呀, 大胖哥哥,你可真厉害! 我以后能不能多请教你一些技术问题啊 ?"
Yuki 检查了下红着脸说道.

张大胖 二郎腿翘的老高然后故作镇定道:

"没什么,不过是写代(Bug)码总结出来的经验! 这算啥 洒洒水而已啦, 复工后隔离 14天 我们星巴克见, 慢慢讲给你听 !"

(๑•̀ㅂ•́) ✧ 邦 的一声 , 张大胖一个没坐稳从藤椅上摔了个底朝天 !

萧子山的Tip

不同业务用的缓存类型就不一样, 有的网站只用强缓存, 有的用协商缓存, 有的各用一点, 亲爱的读者们, 笔者布置个作业, 下面这些网站 document 都用了 那些HTTP缓存技术呢 ?

  • www.zhihu.com/hot
  • mp.weixin.qq.com/s/FlZXj4kk_hfqeyEIYdyXGA
  • www.taobao.com

资料参考

  • 深入分析 Java Web 技术内幕
  • 掘金社区 <浅谈HTTP缓存>
  • 掘金社区 <HTTP----HTTP缓存机制>

深入浅出分享 Java 干货 , 找回对代码的 Passion , 助力月入 20K+

1人推荐
随时随地看视频
慕课网APP