通过HTTP协议做Web缓存

本文讲的是通过HTTP协议做Web缓存,其实缓存就像办健身卡,我第一次花了699办了一年的卡之后,接下来的一年我都可以免费锻炼。 在web 中, 我们交的不是钱,而是空间,我们耗费一定的空间之后,能够获得网页打开速度质的飞跃。 当我们第一次访问一个页面时,我们需要交纳一定的空间, 将下载的css,js,html已经img等相关资源保存在本地。 在第二次,第三次。。。访问时,就可以不用去下载文件了。 通常来说,设置文件的缓存有两种方式,一种是在服务器内设置响应头文件,另外一个是使用h5的manifest文件来进行相关设置. 我们先看看报文设置响应头的方式吧

服务器的缓存协商

这种方式设置的缓存有两种,一种是需要服务器验证,另外一种是不用发送请求验证。

ETag/Last-Modified

这两种方式做法类似,都要向服务器发送一次请求进行验证。简直,缓存就缓存呗,为什么还要验证呢? 其实,这是该协议的一种特有方式,发送一次验证主要是检查文件是否发生变化。

ETag

ETag是用来计算文件的内容是否发生变化,比如,你在文件中删除一个空格,这样都算文件内容发生变化。 通常做法是用md5或者SHA1算法,计算出文件的唯一值。 在前端其实都可以完成, 找到一个文件文件解析的md5算法,然后将文件传入,就可以得到ETag的值。 不过这里,我们着重点并不是让你生成Etag,而是看看ETag在缓存中的重要作用。 ETag是HTTP/1.1A的一种办法,由Web服务器生成,并写入响应头中。


  1. //response Headers 
  2. ETag:"751F63A30AB5F98F855D1D90D217B356" 

接着,到了浏览器之后,便缓存在本地。 当下次打开同样的文章时,会在请求头中发送If-None-Match, 给服务器检查文件是否发生变化。如果没有,则告诉浏览器使用本地的,否则返回新文件


  1. //request Headers 
  2. If-None-Match: "751F63A30AB5F98F855D1D90D217B356" 

通常情况下,服务器默认是打开Etag的,但是为了防止你的同事,或者后台哥哥的后台配置文件不正确,关闭了Etag,这时候,就需要你对对 配置文件 做一些设置。 这里我以Nginx为例: 打开ngnix.conf文件,检查是否有以下语句:


  1. etag off; 
  2. more_set_headers -s 404 -t 'ETag'; 
  3. more_clear_headers 'Etag'; 

如果有则将其删除掉。然后重启nginx就可以了。他们将Etag关闭的原因其实也很简单,就是因为,Etag打开之后会增加服务器的负载,造成性能的局限性,所以,关闭或者打开Etag都要经过权衡的。

Last-Modified

这和文档内容信息验证不同,这里采用的是日期验证办法。 即,服务器上会对文件打上一个文件改动的日期,然后客户端接受该日期,下次请求时,返回该日期,服务器验证,如果日期未变,则告诉浏览器使用本地缓存即可。 即,在服务器的相应头中,可以设置Last-Modified,来启用这一缓存协议.


  1. //Response Header  
  2. Last-Modified:Tue, 03 Mar 2015 01:38:18 GMT 

接受到这一响应头之后,浏览器会对该文件做一个缓存,并保存该日期。当下次请求的时候,会通过If-Modified-Since将日期传入并验证:


  1. If-Modified-Since:Tue, 03 Mar 2015 01:38:18 GMT 

如果日期未变,则告诉浏览器使用缓存。 那我们通常应该怎样启用服务器这一功能呢? 默认情况下,服务器会对静态资源发送Last-modified的tag。 但是,需要注意,Last-Modified的更新时间只能以秒来计,如果你文件改动过于频繁,Last-Modified是无效的(不过,谁牛逼到1s内能多次更新文件嘞~) 实际上.Last-Modified的这个标签的我们通常并不会单独使用它,通常与expires结合,形成一个可降级的缓存.

Expires/Cache-Control

Expires/Cache协议与上述验证协议最大的不同在于,他可以省略发送验证请求环节,不需要服务器的验证,而直接使用本地缓存。 通常这种方式,适用于,项目稳定,版本迭代不多的时候。

Expires

在服务器端可以设置Expires的一个绝对时间。


  1. //Response Headers 
  2. Expires:Tue, 03 May 2016 09:33:34 GMT 

这告诉浏览器,在2016.5.3号之前,可以直接使用该文本的缓存副本。但是,可能会因为服务器和客户端的GMT时间不同,会有一定的bug。 所以,这里只提议在长时间缓存的情况下使用。否则,应该选择Cache-Control. 那在服务器端该怎么设置呢? 这里以nginx为例:


  1. location ~* \.(?:css|js)$ { 
  2.   expires 1d; 
  3.   access_log off; 
  4.   add_header Cache-Control "public"; 

通过 expires 设置过期时间为一天,此时,服务器会根据当前的时间,加上一天.同时添加Expires和Cache-Control头部标签。 即,得到的Response Header为:


  1. Expires: Fri, 28 Feb 2014 10:42:09 GMT 
  2. Cache-Control: max-age=86400 //24*60*60 

(HTTP规定,如果出现max-age和expires,则max-age默认覆盖掉expires) 当expires为负数表示no-cache,正数或零表示max-age=time。 如果你不想缓存,可以直接设置:


  1. expires -1; //永远过期,Cache-Control: no-cache 

Cache-Control

这应该是HTTP1.1为了解决HTTP1.0中expires的时间差的bug,而新添加的一个tag. 他的配置项很多,其实完全都可以取代expires(现在大多数服务器都支持). 引用一段原话:

Cache-Control 头在 HTTP/1.1 规范中定义,取代了之前用来定义响应缓存策略的头(例如 Expires)。当前的所有浏览器都支持 Cache-Control,因此,使用它就够了。

不过,目前大部分服务器都会将两者添加上,因为HTTP规定,如果Cache-Control和expires同时出现的话,expires会默认被覆盖掉。 此时,返回的响应码不再是304(文件未改动),而是200(资源成功访问).

当前每次发送请求之前浏览器会检查缓存系统里,是否有相应文件的备份,如果有的话,则直接从本地模仿一个Response头 理论知识铺垫完毕,我们来take a look. 看看cache-control 有哪些可以配置的属性(以下属性都跟在cache-control后)

  • public: 共有缓存,可被缓存代理服务器缓存,比如CDN
  • private: 私有缓存,不能被共有缓存代理服务器缓存,可被用户的代理缓存如浏览器。
  • max-age=[秒]:表示在这个时间范围内缓存是新鲜的无需更新。类似Expires时间,不过这个时间是相对的,而不是绝对的。也就是某次请求成功后多少秒内缓存是新鲜的。
  • s-maxage=[秒]:类似max-age, 除了仅应用于共享缓存(如代理)。
  • no-cache:这里不是不缓存的意思,只是每次在使用缓存之前都强制发送请求给源服务器进行验证,检查文件该没改变(其实这里和ETag/Last区别不大)
  • no-store:就是禁止缓存,不让浏览器保留缓存副本
  • must-revalidate:告诉浏览器,你这必须再次验证检查信息是否过期, 返回的代号就不是200而是304了。
  • proxy-revalidate:类似must-revalidate,除了只能应用于代理缓存。

比如,这里我可以设置Cache-Control为:


  1. //Response Headers  
  2. Cache-Control:private, max-age=0, must-revalidate 

该文件是一个私有文件,只能被浏览器缓存,而不能被代理缓存。max-age标识该缓存 立即过期 ,其实和no-cache实际上区别不大. 然后must-revalidate告诉浏览器,你必须给我再验证文件过没过期,比如接下来可能会验证Last-Modified或者ETag.如果没有过期则使用本地缓存. 其实上面可以直接等同于:


  1. //Response Headers  
  2. Cache-Control:private,no-cache 

使用no-store的结果


  1. //Response Headers 
  2. Cache-Control:no-store; 

这样表明,不管一不一样都需要重新下载. 强烈表示,不让你使用缓存文件。后续的就不会去验证ETag了。 当然,如果你将IE6那种古老的浏览器考虑进来的话,那你干脆就做的不要脸一点,直接用下面的tag就行:


  1. Cache-Control: no-cache, no-store, must-revalidate //HTTP1.1 
  2. Pragma: no-cache //HTTP1.0 
  3. Expires: 0 //Proxy 

不过现在基本上也没有不支持Cache-Control的浏览器了。所以,正常情况下,可以直接使用.如下的策略来进行设置:(From google developer )

我们通常在nginx怎么配置对应的cache-control头呢?


  1. ##设置no-cache 
  2. //Nginx 
  3. expires -1; 
  4. //cache-control 
  5. Cache-Control:no-cache 
  6.  
  7. ##设置max-age=0 
  8. //Nginx 
  9. expires 0; 
  10. //cache-control 
  11. Cache-Control:max-age=0 
  12.  
  13. ##设置其他头部 
  14. //nginx 
  15. add_header  Cache-Control "no-cache"; 
  16. add_header  Pragma no-cache; 

上面说的基本上是服务器的响应头,那在浏览器的Request headers里存在cache-control代表什么呢? 当请求头中有: Cache-Control: max-age=0 ,表示缓存需要进行验证(ETag||Last-Modified),如果缓存未过期,则可以使用。 当请求头中有: Cache-Control: no-cache ,表示浏览器只能获取最新的文件。 和Response Header中的no-store相对应。

组合拳法之缓存策略

上面介绍的last/ETag/Expires/Cache都是HTTP协议的缓存策略。当然,缓存不止这一种,比如在HTML 4.0中定义的某些meta也可以实现自定义缓存的


  1. <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /> 
  2. <meta http-equiv="Pragma" content="no-cache" /> 
  3. <meta http-equiv="Expires" content="0" /> 

但,实际情况是,这些meta只能在file:// 本地文件中使用,如果是服务器则默认被覆盖。现在目前主流的就是使用HTTP1.1协议缓存 不过我们一般都不会单独使用某一项。 但是,组合之后他们的效果是怎样的呢?

如果你的网页不是什么特别定制化的(私密)的,使用缓存能给你网站的性能带来极大的提升。所以很推荐使用。 一个网站,说白了就是HTML+JS+CSS+fonts+img 这几类文件(视频就呵呵了). 我们可以针对这几类文件做一些缓存层级

上面只是一个简单的设置,要知道HTML是一定不能缓存的(大部分网页)。 缓存设置时间应该在你版本稳定之后设置,否则会得不偿失。 另外设置Cache-Control还可以配合ETag或者Last-Modified进行补偿验证,如果后面文件变化也可以及时反映出来。

清除缓存

最常用的办法就是修改文件的版本号,或者生成随机文件名。 如果你只是在本地测试,想手动清楚缓存的话,可以使用.

但是在Mac中不一样,使用command+R = F5刷新, command+shift+R= ctrl+F5硬性重新加载. 另外,即使你设置了缓存策略,但是他也不会进行缓存的文件。 这些文件包括动态认证的文件,比如需要cookie验证,输入验证码等产生的文件。POST请求文件不能被缓存。

本文作者:佚名

来源:51CTO

原文标题:通过HTTP协议做Web缓存

时间: 2024-10-22 17:05:09

通过HTTP协议做Web缓存的相关文章

web缓存的疑问,请大家帮忙

问题描述 最近在学习nginx,很多问题不明白,请教各位大鸟们帮忙解答!!!问题1 使用nginx做web缓存,举个例子:将响应的html缓存到内存里,下次相同的URL访问的时候,nginx服务器判断缓存中是否存在以及是否过期失效,如果存在不失效就返回此html.我的理解正确吗?是一定要保存到内存里吗?过期时间在nginx里配置,会不会与html页面里的meta缓存设置冲突呢?问题2:有段nginx的配置如下,不知道是什么意思server{....location ~ .*.(gif|jpg|j

作为前端应当了解的Web缓存知识

缓存优点 通常所说的Web缓存指的是可以自动保存常见http请求副本的http设备.对于前端开发者来说,浏览器充当了重要角色.除此外常见的还有各种各样的代理服务器也可以做缓存.当Web请求到达缓存时,缓存从本地副本中提取这个副本内容而不需要经过服务器.这带来了以下优点: 缓存减少了冗余的数据传输,节省流量 缓存缓解了带宽瓶颈问题.不需要更多的带宽就能更快加载页面 缓存缓解了瞬间拥塞,降低了对原始服务器的要求. 缓存降低了距离延时, 因为从较远的地方加载页面会更慢一些. 缓存种类 缓存可以是单个用

Web缓存基础:术语、HTTP报头和缓存策略

Web缓存基础:术语.HTTP报头和缓存策略 简介 对于您的站点的访问者来说,智能化的内容缓存是提高用户体验最有效的方式之一.缓存,或者对之前的请求的临时存储,是HTTP协议实现中最核心的内容分发策略之一.分发路径中的组件均可以缓存内容来加速后续的请求,这受控于对该内容所声明的缓存策略. 在这份指南中,我们将讨论一些Web内容缓存的基本概念.这主要包括如何选择缓存策略以保证互联网范围内的缓存能够正确的处理您的内容.我们将谈一谈缓存带来的好处.副作用以及不同的策略能带来的性能和灵活性的最大结合.

基于反向代理的Web缓存加速——可缓存的CMS系统设计

web|缓存|设计 对于一个日访问量达到百万级的网站来说,速度很快就成为一个瓶颈.除了优化内容发布系统的应用本身外,如果能把不需要实时更新的动态页面的输出结果转化成静态网页来发布,速度上的提升效果将是显著的,因为一个动态页面的速度往往会比静态页面慢2-10倍,而静态网页的内容如果能被缓存在内存里,访问速度甚至会比原有动态网页有2-3个数量级的提高. 动态缓存和静态缓存的比较 基于反向代理加速的站点规划 基于apache mod_proxy的反向代理加速实现 基于squid的反向代理加速实现 面向

给企业配置可升级Web缓存方案

无论企业有多大,Web缓存都有助于优化性能和节省带宽.而且如果选择了正确的缓存解决方案,它可以随着企业网络的增长而扩大,而无需进行昂贵且耗时的重建. Web缓存提供了比将访问对象放在Internet Web服务器上更好的方法,它将需要频繁访问的Web页面和对象保存在离用户更近的系统中.当再次访问这些对象的时候加快了速度. 几年以前,理论是超高带宽的Internet连接会使Web缓存毫无用处,但是结果并非如此.即使最快的速率达到30-45Mbps的光纤Internet连接和速度在100 Mbps到

想要做web视频直播 不知道如何入手

问题描述 想要做web视频直播 不知道如何入手 想要做视频直播不知道如何入手,用什么技术?请大神指点 解决方案 windows server搭建流媒体服务器,客户端用windows media player 解决方案二: 这个不难吧,和正常的视频差不多,知识捕捉一下桌面而已,无非就是每秒多少帧而已 解决方案三: 需要了解流媒体的播放协议,如:RTP.RTSP 等,这些协议都有开源的代码可以参考的,建议你查找一下. 解决方案四: 使用第三方软件的平台, 如YY等等. 解决方案五: 使用第三方软件的

Web 缓存欺骗攻击技术详解

本文讲的是Web 缓存欺骗攻击技术详解,Omer Gil早在今年年初就在他的博客上发表了有关于Web缓存欺骗攻击技术的博文,随后他在BlackHat USA 2017 和BSides Tel-Aviv 2017 上对这种攻击技术进行了演示,并做了更深入的研究. 在他发布的"Web 缓存欺骗技术白皮书"中,详细的介绍了这种攻击技术.这份白皮书大致包含了如下内容: ·攻击原理概述 ·实施攻击的方法 ·攻击所需的条件 ·已知的几个主流的Web 框架及缓存机制 ·缓解措施 Web缓存欺骗这种攻

新型Web攻击技术——Web缓存欺骗

本文讲的是新型Web攻击技术--Web缓存欺骗,Web缓存欺骗是一种新的Web攻击向量,这种攻击技术的出现使得多种Web缓存技术和框架面临风险. Web缓存和服务器反应的一点介绍 很多网站通常都倾向于使用web缓存功能(例如通过CDN,负载均衡器或简单的反向代理).使用Web缓存功能的目的很简单:存储那些经常检索的文件,以减少Web服务器响应的延迟. 让我们来看一个网络缓存的例子.网站http://www.example.com通过配置了反向代理作为Web缓存.存储在服务器上并需要返回用户个人内

做WEB,怎么用内存表,怎么向内存表插入数据。请指点。最好用C#

问题描述 做WEB,怎么用内存表,怎么向内存表插入数据.请指点.最好用C# 解决方案 解决方案二:利用DataTable和SESSION把TABLE表里的值覆给SESSION,之后进行操作表!购物车有很多都是利用这一点做的解决方案三:????????????解决方案四:内存表...-------->DataTabledt=newDataTable();dt.Columns.Add(...);dt.Columns.Add(...);DataRowdr=dt.NewRows();dr[0]=text