您的位置:首页 > 理论基础 > 计算机网络

浏览器缓存浅析(一)

2015-10-02 17:01 405 查看
    虽然知道浏览器有缓存功能,也一直在使用浏览器的缓存功能,但是一直没有对它进行过深入了解,最近正好看到了浏览器缓存的相关文章,于是多方面的了解了下浏览器缓存的相关知识,总算对浏览器缓存有了一个大概的认识,下面我们就来认识下浏览器缓存吧。

    什么是浏览器缓存?

    浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这就是浏览器缓存。

     为什么使用浏览器缓存?

     对于浏览器缓存,相信大家都不会陌生,因为我们经常使用它,但是我们为什么使用浏览器缓存呢?作为用户,使用缓存可以使我们更快的打开一个已经访问过的页面。作为web站点的管理者,浏览器缓存可以在一定程度上减少服务器开销,同时避免相同内容的重复传输带来的带宽浪费。

    浏览器缓存是如何产生的?

    浏览器请求某个URL,服务端会根据请求返回相应内容,此时浏览器会把这些内容存储起来,这样就产生了浏览器缓存。浏览器缓存的产生同时依赖于浏览器和web服务器,它们之间必然存在沟通,这种沟通机制我们称之为“缓存协商”。

    什么是缓存协商?

    我们平时访问的内容是由web服务器生成,而缓存这些内容需要在浏览器本地完成,任何一方都不可能独立完成这一系列过程,所以它们之间必须有一种沟通机制,这就是HTTP中的缓存协商。

    如何进行缓存协商?

    1.Last-Modified:内容的最后修改时间。

    2.ETag:一串编码来标记内容,没有规定具体的格式和计算方式,只要能够起到标识内容的作用即可。

    当浏览器第一次请求某一个URL时,服务端在返回内容的同时也会返回相应的“头信息”,该头信息中就包含了“Last-Modified”和“ETag”(这里特指请求静态文件,动态文件并不包含在内,下面会对动态文件做特别说明,不同操作系统,不同web服务器可能返回的头信息可能不同),当浏览器再次请求该URL的时候,浏览器会向服务器传送If-Modified-Since和If-None-Match报头,询问该时间之后文件是否有被修改过,如果修改过,则请求最新内容,如果没有被修改过,则使用浏览器缓存。

    虽然两种协商方法均可让浏览器使用缓存内容,但是两者在仍有一定区别,Last-Modified针对的是时间,ETag针对的是内容。

    ETag的优缺点:

    优点:

    ETag 解决了 Last-Modified 无法解决的一些问题。例如文件做周期性更改,内容不变,仅仅改变修改时间;某些文件修改非常频繁,比如在秒以下的时间内进行修改,Last-Modified无法判断;某些服务器不能精确的获取到最后修改时间。

    缺点:

    不同操作系统,web服务器对于ETag的计算方法也不同,当使用不同操作系统,不同类型的web服务器做负载均衡的时候,如果用ETag作为判断条件,在被负载均衡到不同服务器后,则很容易导致缓存失效。

    “Last-Modified”和“ETag”两者存在其一,就可以进行缓存协商。

    如何测试是否使用了浏览器缓存?

    google浏览器的“审查元素”和Firefox的Firebug插件都能够查看请求URL的相关头信息,但是它们并不够直观,想要直观的观看这些信息,我们需要借助专业的工具 ,IE浏览器下有“HttpWatch”,火狐浏览器下有HttpFox。这里我们使用HttpFox,输入测试网址,首次请求返回200,再次请求便返回了304(关于200和304状态码可以参考下面的解释),证明浏览器缓存确实已经生效。



    动态文件如何进行浏览器缓存?

    动态内容本身并不受浏览器缓存机制的排斥,只要HTTP头信息中包含缓存协商信息动态内容一样可以被浏览器缓存。对于静态文件服务端会自动生成相应的“Last-Modified”和“ETag”,但是动态文件就没这特权了,想要动态内容被缓存,需要我们手动添加缓存协商信息,也就是添加“Last-Modified”或者“ETag”。我们以Last-Modified为例

<?php
header("Last-Modified:".gmdate("D , d M Y H:i:s ")."GMT");
echo date('Y-m-d H:i:s');

    这样我们就为这个php文件添加了Last-Modified了,我们输入网址测试网址,使用HttpFox进行查看。



    那么这样做是否已经能让动态文件也使用浏览器缓存了呢,我们在来请求一下。
    


    但是现实是残酷的,再次请求并没有让我们看到希望的结果,返回的状态码仍然是200,证明并没有使用浏览器缓存,难道我们做错了吗?非也,如果我们仔细观察,会发现浏览器对于我们的请求并非无动于衷,再次请求的时候它发送了“If-Modified-Since”报头,这就意味着浏览器在询问web服务器“该文件是否有更新”?如果是静态文件,web服务器可以自行做主对比静态文件的最后修改时间和浏览器的询问时间进行对比,但是对于动态内容,web服务器无法自行做主,这部分工作需要动态文件自己来完成。既然浏览器已经发出了请求,我们也不能无动于衷,那就让我们来积极响应浏览器吧。
<?php
if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])){
$modified_time = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
if($modified_time + 3600 > time()){
header("HTTP/1.1 304 Not Modified");
exit(1);
}
}
header("Last-Modified:".gmdate("D , d M Y H:i:s ")."GMT");
echo date('Y-m-d H:i:s');

    我们通过全局变量$_SERVER可以获取到浏览器的请求头信息If-Modified-Since,然后根据它进行判断,例如当请求头信息中的If-Modified-Since距离请求的时间不到1个小时候的时候,我们就使用浏览器缓存。我们来看下我们的成果吧。



    HTTP状态码小知识

    1.状态码200:请求已成功,请求所希望的响应头或数据体将随此响应返回。

    2.状态码304:如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码。

     注意事项:

    1.浏览器和web服务器沟通的唯一途径便是HTTP

    2.一般web服务器会为静态文件的HTTP响应头信息自动生成最后修改时间和ETag标记,下次访问的时候会自动使用浏览器缓存,动态内容则不会,需要手动添加和判断,才能使用浏览器缓存。

    3.网站在做负载均衡的时候,不管是基于Last-Modified还是基于ETag进行浏览器缓存的判断,都有可能出现缓存失效的情况。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  浏览器 缓存 http 200 304