在如今的 web 系统中, cache 应该是每个 web 系统架构师或者开发人员必须要掌握的技能。而 cache 在 web 的世界中一般分为客户端 cache( 当然有些人也叫它浏览器 cache) 和服务端 cache, 这篇文章不涉及 服务端 cache 的内容 . 下面我们主要来看看客户端 cache 所涉及 http header 相关联的知识。
首先登场的是 Last-modified/if-modified-since ,当用户第一次浏览一个网站的时候,服务器会在响应头中增加 Last-modified 这个 http 响应头, Last-modified 的格式如:当用户第二次再请求同样的 url 的时候,浏览器会将 last-modified 的值附加到 if-modified-since 这个 http 请求头中,服务器端接收到请求后,首先 check 一下 if-modified-since 头信息中的时间是否与当前 url 对应的文件的最后修改时间一致,如果一致,则服务器返回 http 304 状态码,这样当浏览器收到 http 304 状态码了以后,就会利用本地缓存的内容来完成对本次用户操作的响应。如果过程的形象点的描述可以通过如下图描述:
对于 Last-modified/if-modified-since 的缓存控制,可能有人会问对于动态内容是否有效果?其实这个与动态内容和静态内容没什么关系,浏览器和服务器之间是通过 http 协议通信的,浏览器本身并不关心,也不知道本地缓存中的内容是服务器动态生成的还是仅仅是静态数据,对于浏览器来说,只要服务器在对某此请求设置了 Last-modified 的 http 响应头以后,浏览器就会在下次请求的时候带上 if-modified-since 的请求头,从而完成和服务器之间的缓存协商控制。如果用 java servlet 为例,服务器只需要通过 response.addDateHeader("Last-Modified",time) , 即可完成将 http 响应头写入响应。另外基于 Last-modified/if-modified-since 的客户端缓存,存在一些缺点,比如当你的 web 站点部署在一个集群环境中,而当用户的同样的请求被路由到不同的 web 服务器的时候就有可能会造成缓存失效,因为不同的服务器时间有可能存在不一致的情况。
其次我们来看看 Etag/if-none-match,Etag 是 http 1.1 规范引入的一个新的 http 实体头, Etag 在规范中仅仅只 etag 可以用来对同一个资源的其它实体头进行对比,没有做进一步的解释,其实我们可以把 Etag 理解为一个服务器在某个资源上面做的一个记号,至于这个记号用来做什么要看服务器如何去解析它,因此我们再设计我们自己的应用的时候,借助 Etag 来实现客户端缓存和服务器之间的缓存协商控制。下面我们来看一下 Etag 如何结合到一个 web 的请求之中。当浏览器第一次请求一个资源的时候,服务器在响应头里面加入 Etag 的标识, Etag 的值既是当前响应内容经过计算以后的值( http 规范没有对 etag 值的计算方式做规定,可以是 md5 或者其它方式)当第二次浏览器发送请求的时候,浏览器便会用原先请求中 Etag 响应头的值作为 if-None-Match 请求头的值,这样服务器接受到此次请求以后,根据 if-None-Match 的取值和当前的内容进行对比,如果相同则返回一个 304 not modified 响应码,这样浏览器收到 304 后就会用客户端本地 cache 来完成对本次请求的响应。上述过程可以通过下图形象的描述:
通过以上的描述我们可以看出, Etag 可以避免 Last-Modified 因为服务器时间不同步造成的缓存失效问题,另外值得我们关注的是 Etag 和 last-modified 仅仅只能节省网络带宽,并不能真正的减少对服务器的 http 请求数,如果要想真正的减少服务器端得请求数,还需要另外的 http header 的协助,下面我们就来看一下,如何减少对服务器端得请求数。
Expries 是另外一个与客户端缓存有关系的 http 头,在浏览器请求一个资源的时候,服务器设置了 Expries 头以后,下次浏览器再请求同样资源的时候,如果发现资源 expires 没有超期,则直接用客户端本地 cache 中数据来完成本次响应,不会向服务器再发送请求。此过程可以通过下图形象的描述:
如果在 java servlet 中,则可以通过如下方法来设置一次响应内容的超期时间。
response.setDateHeader("Expires", expiresTime);
对于 Expires 响应头我们需要注意一点,当响应头中已经设置了 Cache-Contrl:max-age 以后, max-age 将覆盖掉 expires 的效果(参见 http1.1 规范)原文如下:
Note: if a response includes a Cache-Control field with the max-
age directive (see section 14.9.3 ), that directive overrides the
Expires field.
对于 Expires 特别适合对于网站静态资源的缓存,比如 js,image,logo 等,这些资源不会经常发生变化,另外一个也适合于一些周期性更新的内容。
上面说了 Expires ,虽然它可以避免每次都向服务器发送请求,但是它依赖于服务器时间和客户端的时间一致,如果服务器端时间和客户端时间不一致的话,往往会导致缓存失效,接下来我们再来看看另外一个比较重要的 Cache-Control 头,它采用基于客户端的时间来进行对缓存的控制。 Cache-Control 这个 HTTP header 的取值有很多,我们主要来与本主题相关的 max-age: 这个取值代表缓存内容从请求时间开始多久过期,作用类似于 expires 。
另外 Cache-control 还有另外一个头: no-cache: 告诉浏览器,响应的内容不容许缓存,说道 no-cache, 我们有必要看看另外一个响应头 Pragma:no-cache, 可能很多人(包括我之前也是)认为设置了 Pragma:on-cache 以后,浏览器将不会对其内容进行缓存,但是我们错了,在 http1.1 规范没有明确的规定 Pragma:no-cache 作为响应头的意义,原文如下(来自 http1.1 规范):
Note: because the meaning of "Pragma: no-cache as a response
header field is not actually specified, it does not provide a
reliable replacement for "Cache-Control: no-cache" in a response
最后我们需要关注另外一个问题:如何清除浏览器缓存?假如我们一个资源超期时间设置的太长了,而我们又更新了一些资源怎么办?这里大多数网站都采用资源版本化来解决,通俗一点就是给每个资源分配一个缓存版本,当修改资源以后,只需要增加一下版本号即可。比如 javaeye 的 http://www.iteye.com/javascripts/application.js?1309443254 , 1309443254 这个既是版本号,当 application.js 发生变化的时候,只需要修改此版本号即可。
一些参考资料:
http://www.infoq.com/cn/articles/etags
http://betterexplained.com/articles/how-to-optimize-your-site-with-http-caching/
http://www.jdon.com/jivejdon/thread/40381
http://www.mnot.net/cache_docs/#CACHE-CONTROL
相关推荐
### 计算机组成与系统设计—Project-Cache Controller #### 颖悟与目标 本项目旨在帮助学习者深入理解缓存体系结构及其运行机制。通过本项目的实践,学生能够掌握缓存的设计原理,包括如何利用硬件描述语言...
在Go语言的Web服务开发中,中间件是一个重要的概念,它允许开发者插入额外的功能层,如日志记录、性能监控、认证、缓存等,而无需改变基础的处理请求的代码。本文将深入探讨"Go-microcache",这是一个专为Go设计的轻...
cahce数据缓存 rabbitmq消息中间件 Mybatis mysql 本科毕业设计:java基于Springboot框架开发的酒店管理系统(源码+数据库),适合初学者参考学习,项目经过严格测试,确保可以运行! 本科毕业设计:java基于...
SQUID代理的性能本身已经是代理服务器中的佼佼者,本系统将其性 能发挥的极至:通过ramdisk技术,让SQUID把网页cahce到内存中,这样,你所访问的网页,除了第一次需要到网络上取,以后都将来自内存!本文将为大家介绍如何用...
Freescale的内部材料,Cache相关,非常适合做基础开发的人,也适合学生学习。Freescale的内部材料,Cache相关,非常适合做基础开发的人,也适合学生学习。 Freescale的内部材料,Cache相关,非常适合做基础开发的人...
cahce数据缓存 rabbitmq消息中间件 Mybatis MySQL的 ===================================== 项目启动 因为这是很久之前开发的系统,数据库并没有重新编写,故原始文件中无sql文件运行,如要运行还得自己创建数据库...
- cahce数据缓存 - rabbitmq消息中间件 - Mybatis - mysql ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信...
ASP.NET的页面缓存技术是提高Web应用程序性能的关键方法之一,尤其在处理大量数据库操作时。SqlCacheDependency是ASP.NET中的一种高级缓存机制,它允许开发者基于SQL Server数据库的更改来自动更新缓存的内容。在本...
db-cahce-yii2-component #Yii2 组件,缓存 sql 请求结果,然后根据此结果(数组)创建模型。 *设置: 'dbCache' => [ 'class' => 'app\components\DbCache' ], *通过 ID 查找用户(及其帖子和评论): $query = ...
ASP(Active Server Pages)是微软开发的一种服务器端脚本环境,用于创建动态网页和Web应用程序。这个"ASP高级技术WORD版"的压缩包文件显然包含了关于ASP编程的深入技术和实践案例,适合那些已经掌握基础ASP知识并...
使用文件系统的NodeJ的模块缓存。 存储字符串,整数,布尔值,对象,类等... node-filesystem-cache使用Filesystem的NodeJ的模块缓存。 存储字符串,整数,布尔值,对象,类等...安装npm install node-filesystem-...
锁定缓存缓存值并在解析要缓存的值时锁定。 许多缓存库无法锁定获取要缓存的值的进程。 这意味着您需要两个高速缓存的多个资源密集型进程可以同时运行以计算一个值。 该库将锁定与缓存相结合,并确保只有一个计算...
特性界面简洁清爽,对移动端友好支持markdown语法支持Emoji表情输入支持Github账户登录支持@用户支持在线播放音乐(小彩蛋)每日励志名言更多功能还在开发...使用建立数据库javachina,编码为utf-8,导入 javachina...
详细讲解了MMU和CAHCE的概念,容易理解,适合嵌入式入门学习者
缓存技术是asp.net程序设计中非常实用的技术,也是大型web程序设计中比较常见的技术。本文就以实例形式对此加以说明。具体如下: asp.net页面的SqlCacheDependency Sql缓存: Cahce/SqlCachePage.aspx页面代码如下:...
在计算机科学领域,存储体系是计算性能的关键组成部分。高速缓存(Cache)是现代计算机架构中的一个重要组件,它用于缓解主内存与CPU之间速度不匹配的问题。本实验“存储体系实验-利用高速缓存(Cache)的局部性优化...
特性:界面简洁清爽,对移动端友好支持markdown语法支持Emoji表情输入支持Github账户登录支持@用户支持在线播放音乐(小彩蛋)每日励志名言更多功能还在开发...使用:建立数据库javachina,编码为utf-8,导入 ...
PHP是一种广泛使用的服务器端脚本语言,尤其适合处理Web开发中的各种任务,包括数据采集和缓存管理。 首先,我们需要了解如何使用PHP进行网页抓取。PHP可以通过cURL库或者file_get_contents函数来获取远程网页内容...
CAHCE_PROGRAM=10 BLOCK_OF_CHIPS=1024 READ_CYCLE=2 WRITE_CYCLE=2 BUS_WIDTH=0 SCAN_FILENAME=Nand_Scan CODE_FILENAME=General FLASH_ID=NO_FLASH PC0= PC1= ENABLE_JUMP=0 SECTOR_SIZE=0 FACTORY_PATTERN=FF ...
simple_cahce PHP 如何轻松地将动态页面缓存到静态文本页面中 PHP phpContent编辑 使用带有 Ajax 和 PHP 后端的 HTML5 contentEditable 来更新网页 PHP 数学验证码 简单的 PHP 匹配基于 cpatcha 的输入检查 PHP