博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HTTP 缓存(上)
阅读量:6425 次
发布时间:2019-06-23

本文共 5072 字,大约阅读时间需要 16 分钟。

hot3.png

在写web前端页面时把自己的修改提交到了web服务器,但是有时在刷新前端页面时,往往发现显示的内容并不是修改后的内容,为什么呢?

095450_Ff26_1475335.png

这个时候的解决方法就是删除浏览器缓存,然后再重新刷新,就可以看到修改后的内容了,浏览器到底做了什么使得修改没在页面中呈现,缓存到底是什么东东等等,带着这些疑问,开始了HTTP缓存学习之旅。


缓存是什么?                                                                                                                                             Web缓存是可以自动保存常见文档副本的HTTP 设备。当Web请求抵达缓存时,如果本地有“已缓存的”副本,就可以从本地设备而不是服务器中提取这个文档。


为什么使用缓存?(即缓存的优点)                                                                                                               

  • 缓存减少了冗余的数据传输,节约了网络费用

  • 缓存缓解了网络瓶颈的问题

  • 缓存降低了对原始服务器的要求

  • 缓存降低了距离时延


缓存解决的问题:                                                                                                                                          

  • 冗余的数据传输 :减少那些流入/流出原始服务器的,被浪费掉了的重复流量

  • 带宽瓶颈: 缓存可以改善由有限广域网带宽造成的网络瓶颈

  • 瞬间堵塞: 瞬间拥塞会使web服务器过载

  • 距离时延: 即使使用的是并行的持久连接,光速也会造成显著的时延(将缓存放在附近的机房里可以将文件传输距离从数千里缩短到数十米)


缓存的分类:

        缓存分为服务端侧(server side,比如 Nginx,redis,memcached)和客户端侧(client side,比如 web browser)。

服务端缓存又分为 代理服务器缓存 和 反向代理服务器缓存(也叫网关缓存,比如 Nginx反向代理、Squid等),其实广泛使用的 CDN 也是一种服务端缓存,目的都是让用户的请求走”捷径“,并且都是缓存图片、文件等静态资源。

客户端侧缓存一般指的是浏览器缓存,目的就是加速各种静态资源的访问,想想现在的大型网站,随便一个页面都是一两百个请求,每天 pv 都是亿级别,如果没有缓存,用户体验会急剧下降、同时服务器压力和网络带宽都面临严重的考验。


用户行为对浏览器缓存的影响:

    用户在浏览器地址栏中键入回车,F5或CTRL+F5时,对浏览器缓存的影响,请看下图:

   1.     清除缓存,使用(chrome://cache/)命令查看google浏览器是否有缓存存在,如下图可以看到浏览器缓存清除干净:

 101943_psGi_1475335.png

缓存清理干净后,输入URL,然后回车, 请求头,响应头等信息如下:

103227_bsiS_1475335.png

由上图可以看到: 请求头中有:

Cache-Control: max-age=0

字段,

响应头中有:

etag:"2835167081"last-modified: Wed, 18 Mar 2015 16:23:38 GMT

字段。

状态码为:

Status code: 200 0k

对上述现象解释:首先,我们清除了浏览器的缓存,也就是说在我们发送请求的时候没有缓存的存在,请求头中

Cache-Control:max-age=0的意思是不经过缓存验证,直接把请求发送的web服务器。服务器收到请求后,回复给客户端的响应头中包含了etag和last-modified。

    2. 不清除缓存(即存在缓存)的情况下,在地址栏键入回车:

104205_l0pD_1475335.png

可以看出请求头中多了如下字段:

If-Modified-Since: Web, 18 Mar 2015 16:23:38 GMTIf-None-Match: "2835167081"

可以看出字段的值与上次服务器返回的 last-modified 和etag的值是相同的。

此时返回的状态码为:

Status Code : 304 Not Modified

 3. 在地址栏中键入F5(刷新):

    105254_yfm4_1475335.png

    可以看出与行为2的信息是相同的。(到底行为2和行为3有什么区别,在下文讲述)。

   4.  在地址栏中键入Ctrl+F5(强制刷新)

105708_rwBF_1475335.png

可以看到请求头中发生了变化如下:

Cache-Control:no-cachePragma: no-Cache

状态码内容如下:

Status code: 200 ok

5.  关闭浏览器(不清楚缓存),然后打开浏览器键入回车:

110339_vnl9_1475335.png

可以看出请求头和状态码都发生了变化。有上述现象总结(用户行为对缓存请求头的影响)如下:110645_V15Y_1475335.png

几种状态码的区别:

141825_COO2_1475335.jpg


浏览器请求流程:

        浏览器第一次请求

131525_vubb_1475335.png

    浏览器再次请求时:

132900_uCjh_1475335.png


与缓存相关的几种报文头的解释:

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

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

133546_NYUM_1475335.png

将最大使用期设置为零,Cache-Control : max-age=0从而在每次访问的时候都进行刷新。

注意事项:

         文档过期系统并不是一个完美的系统。如果发布者不小心分配了一个很久之后的过期日期,在文档过期之前,它要对文档做的任何修改都不一定能显示在所有缓存中,因此,很多发布者都不会使用很长的过期时间。而且,很多发布者甚至都不使用过期日期,这样缓存就很难确定文档会在多长时间内保持新鲜了。

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使用。

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

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

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

# Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,# 它将不能准确标注文件的修改时间,如果某些文件会被定期生成,# 当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存# 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形

Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified与ETag一起使用时,服务器会优先验证ETag。

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

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


如何构建可缓存站点

前面了解了Web缓存的运行机制极其重要性之后,我们可以从以下这些方面去努力改善我们的站点,保证缓存被最有效的利用,达到最佳的性能。

    同一个资源保证URL的稳定性

    URL是浏览器缓存机制的基础,所以如果一个资源需要在多个地方被引用,尽量保证URL是固定的。

    给CSS,JS,图片等资源增加HTTP缓存头,并强制入口Html不被缓存

    对于不经常修改的静态资源,比如Css,js,图片等,可以设置一个较长的过期的时间,或者至少加上Last-Modified/Etag,而对于html页面这种入口文件,不建议设置缓存。这样既能保证在静态资源不变的情况下,可以不重发请求或直接通过304避免重复下载,又能保证在资源有更新的,只要通过给资源增加时间戳或者更换路径,就能让用户访问最新的资源。

    减少对Cookie的依赖

    过多的使用Cookie会大大增加HTTP请求的负担,每次GET或POST请求,都会把Cookie都带上,增加网络传输流量,导致增长交互时间;同时Cache是很难被缓存的,应该尽量少使用,或者这在动态页面上使用。

   减少对HTTPS加密协议的使用

   通过HTTPS请求的资源,默认是不会被缓存的,必须通过特殊的配置,才能让资源得到缓存。建议只对涉及敏感信息的请求使用HTTPS传输,其他类似Css,Js,图片这些静态资源,尽量避免使用。

     多用Get方式请求动态cgi

     虽然POST的请求方式比Get更安全,可以避免类似密码这种敏感信息在网络传输,被代理或其他人截获,但是Get请求方式更快,效率更高,而且能被缓存,建议对于那些不涉及敏感信息提交的请求尽量使用Get方式请求。

   动态CGI也是可以被缓存

   如果动态脚本或CGI输入的内容在一定的时间范围内是固定的,或者根据GET参数相同,输入的内容相同,我们也认为请求是可以被缓存的,有以下几种方式,可以达到这个效果:

  1. 让动态脚本定期将内容改变时导出成静态文件,Web直接访问带有Last-Modified/Etag的静态文件

  2. 开发者可以通过代码给动态脚本的响应头中添加Cache-Control: max-age,告诉浏览器在过期前可以直接使用副本

  3. 通过代码给动态脚本的响应头添加Last-Modified/Etag信息,浏览器再次请求的时候,可以通过解析If-Modified-Since/If-None-Match得知浏览器是否存在缓存,由代码逻辑控制是否返回304


如何给站点增加缓存机制

HTTP请求/响应头中添加缓存报头可以有效利用站点缓存,作为一个Web前端开发者,我要做什么呢?答案是:啥都不用做。不过要去推动Web运营人员、Web后端开发人员分别给服务器和动态脚本CGI增加合适的缓存报头。

待整理:

cowboy中处理对静态文件的处理是如何使用缓存的?

在cowboy中应该如何使用缓存?

HTML5 应用程序缓存的使用?

参考文章:

转载于:https://my.oschina.net/lvhuizhenblog/blog/383498

你可能感兴趣的文章
PostgreSQL 如何比较两个表的定义是否一致
查看>>
Ambari安装Hadoop集群
查看>>
WCF学习之旅—基于ServiceDebug的异常处理(十七)
查看>>
CLREX
查看>>
再也不用担心this指向的问题了
查看>>
使用putty远程连接linux
查看>>
【comparator, comparable】小总结
查看>>
Node 版本管理
查看>>
34、重分布配置实验之分发列表distribute-list
查看>>
命令模式-对象行为型
查看>>
VS2017配置、提高生产力、代码辨识度 (工欲善其事必先利其器)新手必备!
查看>>
[Phoenix] 七、如何使用自增ID
查看>>
路由基本配置(上)
查看>>
windows上传文件到linux乱码解决
查看>>
fpm打包zabbix-agent
查看>>
pythopn List(列表)
查看>>
学习笔记 十五: mariadb
查看>>
学习笔记 124: 预备知识总结
查看>>
windows server之AD(1)
查看>>
如何升级PowerShell
查看>>