太慢了!
“HTTP
你过来一下,有件事想和你商量商量!” 浏览器老大晃悠到了 HTTP
的手术室中说道。
“怎么有空过来,正忙着呢,快坐。” 说着,我放下手中的器具,抽出放在一旁的凳子。
“不了不了,我就想了解了解情况,门口还有还多 URL
等着你发送呢!” 浏览器老大叹了口气。
我一看门外,吓了一跳,门口的 URL
都已经围着我的手术室绕了一圈了。“什么情况?” 我问道。
“这个页面的 HTTP
请求有点多啊!” 浏览器又叹了口气,缓缓的说道:“你想想有什么办法能快一点?”
“这我也没有办法呀,我这只有 6
个人,要不你加点?”
“不行啊,浏览器空间太小了,操作系统老大不愿意在派人过来了,算了,你先忙,我想想办法!” 浏览器老大一脸的无奈。
协商
手术室外的 URL
慢慢的减少,大概过了 500ms
我终于放下了手中的手术刀,长舒一口气,发现了还在手术室内来回踱步的浏览器老大。
“HTTP
你有没有发现,有一些 URL
你送了好几次!” 浏览器老大若有所思道。
“我没注意诶,不过印象中是有的。” 说完,我陷入了思考。
“那你回忆回忆,他们带回来的数据,一样吗?” 浏览器老大想到了关键点。
“我想想哈!” 我陷入了回忆中,喃喃自语道:“有一个 URL
来了 3
次,确实有,结果的话,是一样的!”
“真的?那其实都没必要发啊,直接拿上一次的数据给我就行啦!” 庄严的浏览器突然兴奋的像个小孩子。
“是没错,但是...” 我刚想开口。
“没有但是!先这么试试,把之前的数据给存一存,磁盘内存空间你自己调配哈。” 一脸兴奋的浏览器突然打断我的话,跳着就出去了。
“这个老大有点精神大条啊,不行啊,这怎么行啊。” 我自言自语道:“不过想法是个好想法,就是怎么存,哪些资源需要存的问题。首先针对于数据的请求,我应该不用缓存,也就是 Content-type
里有关于 json
的那些请求。其次也不能把文件一直存着吧,要是变了咋办呢!那就先给个固定时间吧!不错,哈哈!我真是个天才!!”
屏幕外的愤怒
“我靠,这 Chrome
,我每次发版都要好久才有反应,Google
上说这个是固定缓存时间!都什么嘛!还让不让程序员干活了!”
“加个时间戳吧,所有问题迎刃而解!”
“哎,也太不智能了啊,这可是 Chrome
啊!”
浏览器老大听到略带愤怒的声音 Cue
到了他,不禁一哆嗦,赶忙来到了 HTTP
的手术室!
“HTTP
你怎么搞的,现在屏幕外都抱怨起来了,我都听到大家准备用 FireFox
了!” 浏览器老大急的满头汗。
“还不是上次你说的把数据给存起来,我还优化了下,至少没有把 json
数据给存下来,要不然...” 突然间我想到了 FireFox
一脸得意的样子,也急了起来。
“怎么办!要不咱们不优化吧!” 浏览器老大说道。
“其实吧,这几天下来,我也思考了下,文件的缓存不应该由我们来决定,你想他们(屏幕外的开发者)在发布的时候会先把文件发到服务器上,如果服务器可以通知我们更新的话,那就最好不过了!”
“说的有道理,但是有一点,服务器不可能通知到我们啊,因为连接是单向的。” 突然间兴奋又失落,浏览器老大叹了口气:“看来还是不行啊!”
“不不不!这件事我要和我在服务器的哥们谈谈,老大你先别沮丧,我有个挺好的办法的,我先验证验证。如果验证通过了,那么我有信心做好!”
“哦...” 浏览器老大还在失望的情绪里,看来对我的想法不是很相信。
强缓存
拿起办公桌上的电话,转动几圈后,听筒里传来了 “嘟嘟” 声。
“喂,你个不识相的,被派到 Chrome
就了不起了?这么久才来一个电话!”
“太忙了啊!说正事,我有个想法想和你谈谈!”
“什么想法?我这也很忙啊,别说有点没的啊,老娘忙着呢!”
“这个想法一担实现,我们的工作量会减轻不少呢!” 我顿了顿接着说道:“你有没有发觉,其实有很多请求都是一样的?”
“是啊,而且有时候还挺多的!说到这,我也想问,你们客户端的 HTTP
怎么老是请求一样的东西?一直请求一直爽?”
“这个没的办法啊,用户老是刷新页面,还有有的用户每天访问的就那几个页面,这就导致了我们经常向你要同一些东西。”
“那你们缓存下来啊!别动不动就向我要!”
“我们已经开始试验了,但实验效果一直不理想,一开始我们设定的缓存时间是一天,但是页面的变动我们完全不知道!”
“是哦,这些天从你哪儿的请求确实少了不少。”
“现在浏览器老大因为缓存不更新数据这个问题,已经打算放弃缓存了!但我有个想法,可以解决这个问题,需要试一试才行!”
“什么想法,说吧,我来配合你!”
“还记得报文头吗?”
“当然,我们不就干这个的吗?”
“你可以给个资源的有效时间吗?”
“有效时间?什么意思?”
“就是资源不会发生变动的时长。”
“这个我也不知道咯!”
“让开发者设置啊,把这个权限给他们,我们约定这个有效时间放在报文头中行吧!”
“嗯,是个不错的想法,然后你们就根据这个设置,缓存对应的资源?”
“bingo
~”
“OK
那我向我这边的应用层程序开放这个设置,报文头中我给你加个 Expires
的字段,代表过期时间,你直接用就好!”
“这么贴心!谢啦!”
“好嘞!那我先去通知一下!”
屏幕外的自责
“兄弟,不好意思哈,我刚刚把这个资源设置成了明天过期 ~~ 你强刷一下试试?”
“...” 默默的按下了 CTRL + F5
“兄弟,没用...”
“啊!这个资源中间要走代理服务器...”
“那咋办?”
“加个时间戳?”
“不行啊!”
“会不会你没发成功?”
“...”
协商缓存
“喂?在吗?”
“又有什么事?老娘很忙的!”
“还记得上次我找你吗?我们加了个 Expires
的响应头?”
“嗯,怎么了,不挺好的吗?你们把锅成功摔给了我们!” 电话那头传来了愤怒的声音:“老娘真是着了你的道!这些开发者,明明自己设置了 Expires
,还以为没发好,整天的往服务器上传东西,烦死了!”
“消消气 ~ 消消气 ~ 我这还有一个事呢。” 我一脸尴尬的说道:“在改版之后呢,少了不少请求,但是我们发现资源一旦过期了,我们还是得向你们要,但返回的数据我们对比了下,还是一样的!所以这里还是需要和你们配合优化一下。”
“还来!” 电话那头传来了略带愤怒的声音:“还想甩锅?”
“消消气消消气,想想这能减少好多工作量呢!这次也是加一个响应头就好 ~”
“说吧!”
“你们那边能根据资源生成一个唯一标识吗?就是资源变了这个标识也会变的那种。”
“能啊,这还不简单,根据修改时间就好了啊!”
“原来这么简单啊,确实修改时间符合这个条件,那你把这个时间给我们,我们存下来,然后请求相同资源的时候我们会把这个标识给你们,你们对比一下,如果一样就直接返回 304
我们就直接使用缓存了,行吧?是不是少了好多工作量?”
“确实!这个想法不错!能减不少的工作量。行吧,给你们加上!就叫 Last-Modified
吧,你们的请求头里的就叫 If-Modified-Since
吧,我去通知应用层程序!”
“得嘞 ~”
翻新
“喂!在吗?”
“哟,大忙人开始闲了?” 对面传来了略带嫉妒的声音。
“对啊,自从开始使用我们上次约定好的报文头,工作量巨减啊,HTTP
协议升级了,听说了吗?” 我有点小得意。
“是啊,升 1.1
了,终于能够长连了,但是效果不是很理想啊,该堵住的地方还是堵住了。” 听起来服务器那边碰到了点难事。
“不管这个,还记得 Expires
这个首部吗?”
“记得,就是过期时间嘛。”
“现在这个描述不准确,我们本地时间和你给的不太一致,我们客户端想要的其实是一个缓存的策略,比如缓存多久时间啊,如何缓存之类的,趁着协议升级,我们也改改吧。”
“嗯,不错,每次都要重新计算过期时间也是挺麻烦的,那这个就交给你们了,我这边直接设置缓存策略。就叫 Cache-Control
吧!根据你们的使用情况,来定规则,这个就交给你了。”
“嗯,好的。我们这边总结一下,等下传真给你。”
“关于缓存,还有一个事,我也要提一下。” 电话那头,语气略带抱歉。
“嗯嗯,你说。”
“其实根据修改时间来确定缓存资源不是很准确,我们这的规则是只要文件被打开了就认为是修改了,所以有误差,还有就是如果文件的修改时间小于 1
秒,那个这个值其实是不变的!”
“还有这样的问题啊,那有解决办法吗?”
“我们这可以根据文章内容生成标识符,我通过新的报文头 ETag
给你们,我们这已经准备支持了。这次准备提到新的协议规范里。”
“OK
这不错,那我们使用哪个字段给你们?”
“If-None-Match
”
“好的,我记一下。”
“URL
来了,我先挂了哈 ~ 策略等下给你传真,你收一下!”
“嗯,忙去吧。”
Cache-Control
大约过了 100ms
服务端的传真机开始打印,内容如下:
指令 | 作用 |
---|---|
public |
使用者都可以缓存(客户端和代理服务器)。 |
private |
仅客户端可以缓存(比如浏览器)。 |
max-age = time |
仅缓存 time 所规定的时间,一旦缓存过期,需要重新请求。 |
s-max-age = time |
仅在代理服务器中生效,覆盖 max-age 效果。 |
no-store |
不缓存响应。 |
no-cache |
缓存,但缓存立即失效,配合 ETag 使用。 |
max-stable = time |
在 time 时间内,即使缓存失效,也使用缓存。 |
min-fresh = time |
需要在 time 时间内,重新拿去资源。 |
失效不代表缓存清楚,仅仅代表缓存过期,如果服务器(也就是你)确认缓存有效,就使用缓存。
指令可组合使用,赋上组合使用结构图:
该图可作为开发者文档。
下图为我们这边总结的缓存命中规则,供你们参考:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。