PHP客户端缓存详解

        一、什么是”Last-Modified”? 
        在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified的属性标记此文件在服务期端最后被修改的时间,格式类似这样: 
        Last-Modified: Fri, 12 May 2006 18:53:33 GMT 
        客户端第二次请求此URL时,根据 HTTP 协议的规定,浏览器会向服务器传送 If-Modified-Since 报头,询问该时间之后文件是否有被修改过: 
        If-Modified-Since: Fri, 12 May 2006 18:53:33 GMT 
        如果服务器端的资源没有变化,则自动返回 HTTP 304 (Not Changed.)状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。 
      注意:

         1、对于一些图像,css,js等静态文件资源,配置好了的apache服务器会理解这些If-Modified-Since请求头标,将头标里的时间和文件的最后修改时间进行比较并作出响应,如果二者相等则发送一个304 Not Modfied来告诉客户端所请求资源并未修改让客户端放心使用缓存中的资源,否则的话会重新发送一个新的资源和新的Last-Modified的头标。

          2、但是对于一个动态的PHP脚本,我们即使在脚本加入了header('Last Modified: '.$time)来发送一个Last Modified响应头标,当客户端附带'If-Modified-Since'在次请求时apache服务器不会进行处理,这需要我们自己用$_SERVER['HTTP_IF_MODIFIED_SINCE']来获取'If-Modified-Since'的值自己来进行判断处理。

       

<?php

//设置 Last-Modified  $mktime为所设定的时间
header( 'Last-Modified: ' . gmdate ( 'r' , $mktime ) . ' GMT' );  
//再次请求时获取Last-Modified值
$again = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
echo "".$again;

?>


        二、什么是”Etag”? 
        HTTP 协议规格说明定义ETag为“被请求变量的实体值” 。另一种说法是,ETag是一个可以与Web资源关联的记号(token)。典型的Web资源可以一个Web页,但也可能是JSON或XML文档。服务器单独负责判断记号是什么及其含义,并在HTTP响应头中将其传送到客户端,以下是服务器端返回的格式: 
        ETag: "50b1c1d4f775c61:df3" 
        客户端的查询更新格式是这样的: 
        If-None-Match: W/"50b1c1d4f775c61:df3" 
        如果ETag没改变,则返回状态304然后不返回,这也和Last-Modified一样。本人测试Etag主要在断点下载时比较有用。

  

<?php

//设置 ETag  $etab为所设定的标志
$etab = "yuanyanbing";  
header( 'ETag: '.$etab );
//再次请求时获取ETag:值
$againb = $_SERVER['HTTP_IF_NONE_MATCH'];
echo "".$againb;

?>


     Last-Modified和Etags如何帮助提高性能?
        聪明的开发者会把Last-Modified 和ETags请求的http报头一起使用,这样可利用客户端(例如浏览器)的缓存。因为服务器首先产生 Last-Modified/Etag标记,服务器可在稍后使用它来判断页面是否已经被修改。本质上,客户端通过将该记号传回服务器要求服务器验证其(客户端)缓存。 
        过程如下:
                1. 客户端请求一个页面(A)。 
                2. 服务器返回页面A,并在给A加上一个Last-Modified/ETag。 
                3. 客户端展现该页面,并将页面连同Last-Modified/ETag一起缓存。 
                4. 客户再次请求页面A,并将上次请求时服务器返回的Last-Modified/ETag一起传递给服务器。 
                5. 服务器检查该Last-Modified或ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304和一个空的响应体。

        三、Expires

Expires表明缓存何时因该过期(GMT时间),属于HTTP 1.0 标准,通常是用来对Cache-Control的max-age的一个补充,来兼容HTTP 1.0,不赞成单独使用Expires,因为客户端时间容易发生偏差。

        四、Pragma

HTTP 1.0 标准,通常是在不缓存时使用,Pragma: no-cache。


 

        五、关于Cache-Control

 

public

可以在任何地方缓存

private

内容只缓存到私有缓存中

no-cache

不能在任何地方缓存

must-revalidate

缓存必须检查跟新版本

proxy-revalidate

代理缓存必须检查跟新版本

max-age

内容能够被缓存的时间

s-maxage

覆盖共享缓存的max-age设置

 

Cache-directive 打开一个新的浏览器窗口 在原窗口中单击 Enter 按钮 刷新 单击 Back 按钮
public 浏览器呈现来自缓存的页面 浏览器呈现来自缓存的页面 浏览器重新发送请求到服务器 浏览器呈现来自缓存的页面
private 浏览器重新发送请求到服务器 第一次,浏览器重新发送请求到服务器;此后,浏览器呈现来自缓存的页面 浏览器重新发送请求到服务器 浏览器呈现来自缓存的页面
no-cache/no-store 浏览器重新发送请求到服务器 浏览器重新发送请求到服务器 浏览器重新发送请求到服务器 浏览器重新发送请求到服务器
must-revalidation/proxy-revalidation 浏览器重新发送请求到服务器 第一次,浏览器重新发送请求到服务器;此后,浏览器呈现来自缓存的页面 浏览器重新发送请求到服务器 浏览器呈现来自缓存的页面
max-age=xxx (xxx is numeric) 在 xxx 秒后,浏览器重新发送请求到服务器 在 xxx 秒后,浏览器重新发送请求到服务器 浏览器重新发送请求到服务器 在 xxx 秒后,浏览器重新发送请求到服务器

浏览器行为影响

在先前有效访问后,在以后对同一URI资源的请求中,浏览器只进行两种动作:

(1)直接在缓存中去获取内容。如果先前有效访问的响应头包含 Expires,max-age的话,'打开新窗口' '输入URI回车' '前一页' '后一页'这些浏览器行为不会使浏览器在Expires,max-age设置的有效期时间内去访问服务器,而是在缓存中去获取内容,但是' 刷新' 或 '重载'例外。

(2)访问服务器,根据服务器响应来获取内容。这种情况发生在设置no-cache等头标要求不缓存,或者是设置了 Expires,max-age但浏览器行为是 ' 刷新' 或 '重载'时候。'Last-Modified' 'ETag' 'must-revalidate' 等有些特殊,不直接受浏览器行为影响,它们也是访问服务器后,再由服务器判断是发送新的资源,还是发送一个304 Not Modfied让浏览器使用缓存中的资源。

<?php   
/********************************
 * 客户端缓存控制函数
 * $type  缓存类型
 * $interval  客户端缓存过期时间
 * $mktime  设置Last-Modified
 * $etag  设置ETag标志
 ******************************/  
function  http_cache_control( $type = 'nocache' , $interval =0, $mktime = '' , $etag = '' ){     
   if ( $type == 'nocache' )
   {     
       header('Expires: -1' );  //设置 -1为立刻过期    
       header('Pragma: no-cache' );     
       header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0' );     
   }
   else 
   {   //检查  ETag: 值   $_SERVER [ 'HTTP_IF_NONE_MATCH' ]
       if (isset( $_SERVER [ 'HTTP_IF_NONE_MATCH' ]) &&  $etag  &&  $_SERVER [ 'HTTP_IF_NONE_MATCH' ] ==  $etag )
       {     
            header('HTTP/1.1 304 Not Modfied' );     
       }//检查  Last-Modified: 值   $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ]
       elseif (isset( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ]) &&  $mktime  &&  $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ] ==  gmdate ( 'r' , $mktime ). ' GMT' )
       {     
           header('HTTP/1.1 304 Not Modfied' );     
       }
       else 
       {     //根据修改时间加过期时间,算出过期时间点
            if ( $mktime )
            {     
               $gmtime  =  gmdate ( 'r' , $mktime + $interval ). ' GMT' ;     
               header('Expires: ' . $gmtime );     
            }     
            if ( $type == 'public' )//设置缓存类型为public
            {     
               header('Cache-Control: public,max-age=' . $interval );     
            }
            elseif ( $type == 'private' )//设置缓存类型为 private
            {     
           	   header('Cache-Control: private,max-age=' . $interval . ',s-maxage=0' );     
            }elseif ( $type == 'none' )
            {     
               header('Cache-Control: must-revalidate,proxy-revalidate' );     
            }     
        }     
        $mktime && header( 'Last-Modified: ' . gmdate ( 'r' , $mktime ) . ' GMT' );     
        $etag   &&  header( 'ETag: ' . $etag );     
   }     
}     
?>    


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值