`

http 浏览器缓存

    博客分类:
  • web
阅读更多

以tomcat为例,浏览器和tomcat之间通过如下几个head来控制是否从服务器端获取资源文件还是之间从浏览器cache中去取

Last-Modified/If-Modified-Since,ETag/If-None-Match

下面通过实验的方式直观的看这几个head是如何工作的,首先创建一个demo项目,然后创建一个html文件和一个js文件用来测试(1.html引用1.js)

下面是第一次访问的截图,可以看到1.html和1.js都返回了200,因为这是第一次访问



 

 

然后看下1.js的http的head信息如下图

因为是第一次访问,request head里面没有跟cache有关的信息,但是可以看到response head里面有Last-Modified和ETag



 

 

下面在访问的时候,request里面就会携带与Last-Modified/Etag对应的HttpRequestHeader:If-Modified-Since和If-None-Match,如下图



 

关于If-Modified-Since,tomcat会把这个时间与服务器上实际文件的最后修改时间进行对比。如果时间一致,那么返回304,客户端就直接使用本地缓存文件。如果时间不一致,就会返回200和新的文件内容。客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示在浏览器中

关于If-None-Match,服务器把这个值和资源的ETag值比较看是否改变,如果变了,则返回200和新的文件内容

 

其实http协议里面是有专门的协议来控制200(from cache)的,就是Cache-Control: max-age=秒 和 Expires,我们可以通过如下的filter来实现js文件的过期时间为1minute

	<filter>
		<filter-name>ExpiresFilter</filter-name>
		<filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class>
		<init-param>
			<param-name>ExpiresByType image</param-name>
			<param-value>access plus 1 minutes</param-value>
		</init-param>
		<init-param>
			<param-name>ExpiresByType text/css</param-name>
			<param-value>access plus 10 minutes</param-value>
		</init-param>
		<init-param>
			<param-name>ExpiresByType application/javascript</param-name>
			<param-value>access plus 1 minutes</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>ExpiresFilter</filter-name>
		<url-pattern>/*</url-pattern>
		<dispatcher>REQUEST</dispatcher>
	</filter-mapping>

 重启tomcat后,访问1.html,一分钟之内就算update 了 1.js文件,浏览器也会忽略他,直接200(from cache)

如下图,



 

 

 

可以看到time是0,

对应的http head如下,



 

就是max-age为60起的作用

 

可是在我测试的时候偶尔会发现有200(from cache)这样的status出现(在我没有用ExpireFilter的时候),无论是Firefox还是chrome这种状态说明浏览器没有发起请求,直接用local的cache,甚至我已经修改了后台的js文件,有时候还是会出现200(from cache),这个可能是浏览器的某些算法擅自认为这个文件在服务器端没有被更新而之间用本地的cache

 

贴一段google来的话,如下

 

这个结论不是很准确,实际上这个问题答案全部都在https://tools.ietf.org/html/rfc7234

简单说一下

浏览器的缓存机制分为两块,也就是规范中的4.2. Freshness 和 4.3. Validation

Freshness

Cache Control与Expires是一组,他们是用来进行Freshness验证,也就是提供客户端检测文件是否足够新鲜,可以无需向服务端发起Validation请求就能保证并未过期可以直接使用。

所有的from cache的请求实际上都是由于浏览器认为本地的缓存资源足够新鲜,所以无需额外请求而直接使用。

具体的判断方法可以参考协议,实际上就是根据本地的时间和服务器返回头的约定信息进行对比验证。

历史问题

为何有两个参数而不是一个参数则是由于历史原因,在HTTP1.0中定义的是Expires,Expires的值是一个明确的过期时间,而后来使用中发现一旦客户端时间与服务器时间不一致就会引发很多缓存问题。

因此在HTTP 1.1中新添加了Cache Control,实现了更优的文件过期声明,比如max-age配置,是一个timespan,告知客户端这个文件多长时间不会过期而不是直接告知过期时间。

Validation

Last-Modified和ETag则是另一组控制信息,他们用来实现Validation。他们的职责是在本地缓存被浏览器判断可能不够新鲜的时候,会用这两组信息向服务器请求数据,如果服务器内容没有改变,那么约定服务器会返回304 HTTP Code表明这个缓存可以直接使用,无需重新拉取,而一旦服务器内容改变了就会返回200,同时返回新的文件内容。

历史问题

至于为何有两组字段来解决这个问题依然是历史问题,在HTTP 1.0中约定的是Last-Modified,他代表的含义是文件最后一次修改的时间,那么这种约定带来的问题是一旦内容是动态生成的,这个时间在服务器端不一定可以正确的生成,其次是Last-Modified只有秒级的精度,如果在一秒内有一次以上的文件修改,这样的缓存就会造成额外的问题。

因此HTTP1.1中新引入了ETag,他的实现不尽相同,对于动态内容,常规做法是对动态内容做HASH计算,作为ETAG返回,对于静态资源,一般是使用inode+mtime进行计算。

额外的问题

ETag也有他自己的问题,所以经常在使用中会关闭ETag。举例来说,同一个文件在不同物理机上的inode是不同的,这就导致了在分布式的Web系统中,当访问落在不同的物理机上时会返回不同的ETag,进而导致304失效,降级为200请求。解决办法也有从ETag算法中剥离inode,只是使用mtime,但是这样实际上和Last-Modified就一样了。当然你也可以额外的做一些改进,使ETag对静态资源的算法也是通过hash计算的。不过由于一般我们会使用CDN技术,因此集群部署中的ETag问题并不会造成太大的影响,所以折腾的人也不太是很多。

总结

总结一下,ETag的设置并不会影响Freshness验证,Freshness验证会和浏览器策略以及Cache Control与Expires有关。

 

ps:https://stackoverflow.com/questions/1665082/http-status-code-200-cache-vs-status-code-304

https://developer.yahoo.com/performance/rules.html#expires=

 

如果有一个2M的js文件需要做到200(from cache)的话,首先可以让他10年不过期,用这个配置access plus 10 years,然后给js命名bundle.0.2.0.js,这样下次build的时候html就应该引入bundle.0.2.1.js这样之前的文件自然就失效了

  • 大小: 37.5 KB
  • 大小: 48 KB
  • 大小: 49.4 KB
  • 大小: 46.2 KB
  • 大小: 53.5 KB
分享到:
评论

相关推荐

    HTTP+JS+浏览器缓存技术

    总结了浏览器缓存的原理,如何管理浏览器缓存

    浏览器HTTP缓存运行机制流程图.zip

    浏览器HTTP缓存运行机制的流程图 强缓存和协商缓存

    2024年浏览器缓存HTTP缓存机制(面试常考).zip

    浏览器缓存【2024年浏览器缓存/HTTP缓存机制(面试常考)简介】 内容概要: 这篇博客为网络技术初学者提供了一个全面的理解浏览器缓存和HTTP缓存机制的指南。通过通俗易懂的语言,本博客介绍了浏览器缓存的工作原理...

    禁止浏览器缓存当前文档内容

    有三个HTTP响应头字段都可以禁止浏览器缓存当前页面: response.setDateHeader(“Expires”,0); response.setHeader(“Cache-Control”,”no-cache”); response.setHeader(“Pragma”,”no-cache”); 不是所有的...

    浏览器HTTP缓存机制

    描述了web浏览器,关于HTTP缓存机制的流程

    浏览器缓存相关知识.zip

    浏览器缓存 浏览器缓存主要可以分为两大类:客户端缓存和服务端缓存。客户端缓存,即浏览器缓存,是本文主要讨论的内容。而服务端缓存则主要包括代理服务器缓存和反向代理服务器缓存,以及广泛使用的CDN等。这些...

    浏览器缓存机制面试常考.zip

    通过通俗易懂的语言,本博客介绍了浏览器缓存的工作原理,HTTP缓存控制字段,缓存策略的应用,以及面试中可能遇到的关于缓存的问题和实战演练。此外,还探讨了缓存的高级话题,如缓存头字段、缓存与性能的关系,以及...

    UC浏览器缓存加密视频Y2hlbmppbmdjb25n文件破解合并exe工具

    1、【合并视频.exe】可将UC浏览器缓存或下载的Y2hlbmppbmdjb25n加密或非加密视频文件合并成mp4视频的工具。 2、使用示例:https://img-blog.csdnimg.cn/0a29f18018c246ebbe70efb82f72c288.png 该示例图可以复制链接...

    浏览器缓存机制

    浏览器缓存机制、Expires策略(http1.0)和Cache-control策略(http1.1)、Last-Modified/If-Modified-Since、ETag/If-None-Match

    浏览器缓存技术介绍以及优化建议

    资源介绍了浏览器缓存相关信息。浏览器缓存是一种性能优化技术,它允许浏览器存储网页资源的副本,以便在后续访问时快速加载。通过设置HTTP响应头,如`Expires`和`Cache-Control`,可以控制资源的缓存策略。强缓存...

    js清除浏览器缓存的几种方法

    关于浏览器缓存 浏览器缓存,有时候我们需要他,因为他可以提高网站性能和浏览器速度,提高网站性能。但是有时候我们又不得不清除缓存,因为缓存可能误事,出现一些错误的数据。像股票类网站实时更新等,这样的网站...

    Web应用与开发作业

    (2)有3个http响应头字段可以禁止浏览器缓存当前页面,它们在Servlet中的示例代码如下。 response.setDateHeader("Expires",-1); response.setHeader("Cache-Control","no-cache"); response.setHeader("Pragma",...

    关于angularJs清除浏览器缓存的方法

    浏览器缓存,有时候我们需要他,因为他可以提高网站性能和浏览器速度,提高网站性能。但是有时候我们又不得不清除缓存,因为缓存可能误事,出现一些错误的数据。像股票类网站实时更新等,这样的网站是不要缓存的,像...

    浏览器之HTTP缓存的那些事

    浏览器之HTTP缓存的那些事 什么是浏览器缓存 浏览器HTTP执行机制 缓存模式 缓存相关的Http Header Cache-Control Expires Last-Modified ETag

    深入PHP与浏览器缓存的分析

    我们往往在服务器上对缓存设置进行各种优化方案,但是我们却很少注意到客户端缓存,准确的说是浏览器的缓存机制。其实每种浏览器都有缓存策略,会暂时将每一个浏览过的文件缓存在一个特殊的文件夹里。我们就可以在...

    浅析http协议、cookies和session机制、浏览器缓存.docx

    浅析http协议、cookies和session机制、浏览器缓存.docx

    ASP.NET性能优化之让浏览器缓存动态网页的方法

    OutputCache是针对所有访问服务器资源的用户,本篇要介绍的浏览器缓存则是针对单个用户,让浏览器在我们的控制下彻底不持续访问服务器上的动态内容,也就是我们要让浏览器变成我们的缓存机制中的一部分,在某些特定...

    浏览器缓存问题处理

    根据以上的请求过程,我们来分析一下,为什么浏览器会有缓存。有两种可能:客户端没有向服务器发送文件请求;服务器接收到请求后,没有向客户端返回最新文件。 一、针对第一种可能性,主要涉及到的是http请求及响应...

Global site tag (gtag.js) - Google Analytics