具有最后修改的缓存过期控制

时间:2009-02-18 20:55:34

标签: apache caching browser mod-expires

在Apache的mod_expires模块中,Expires指令有两个基准时间段,访问修改

ExpiresByType text/html "access plus 30 days"

可以理解地表示缓存将在30天后请求新鲜内容。

然而,

ExpiresByType text/html "modification plus 2 hours"

没有直观意义。

除非向服务器发出请求,否则浏览器缓存如何知道文件已被修改?如果它正在调用服务器,缓存此指令有什么用?在我看来,我不理解缓存的一些关键部分。请赐教。

4 个答案:

答案 0 :(得分:36)

以“修改”为基础的Expires*指令是指服务器上文件的修改时间。因此,如果您设置“修改加2小时”,则在文件修改后2小时内(在服务器上)请求内容的任何浏览器都会将该内容缓存到文件修改时间后2小时。并且浏览器知道该时间何时是因为服务器发送了具有适当到期时间的Expires标头。

让我用一个例子来解释一下:说你的Apache配置包括

ExpiresDefault modification plus 2 hours

并且您在服务器上有一个index.html指令所适用的文件ExpiresDefault。假设您在格林尼治标准时间9:53上传index.html版本,覆盖之前的现有index.html(如果有的话)。所以现在index.html的修改时间是GMT 9:53。如果您在服务器上运行ls -l(或Windows上的dir),您会在列表中看到它:

-rw-r--r--  1 apache apache    4096  Feb 18 09:53 index.html

现在,对于每个请求,Apache都会发送Last-Modified标头,其中包含文件的最后修改时间。由于你有ExpiresDefault指令,它还会发送Expires标题,其时间等于文件的修改时间(9:53)加上两个小时。所以这是浏览器看到的内容的一部分:

Last-Modified: Wed, 18 Feb 2009 09:53:00 GMT
Expires: Wed, 18 Feb 2009 11:53:00 GMT

如果浏览器发出此请求的时间是格林威治标准时间11:53之前,则浏览器将缓存该页面,因为它尚未过期。因此,如果用户首先在格林威治标准时间11:00访问该页面,然后在格林威治标准时间11:30再次访问同一页面,则浏览器将看到其缓存版本仍然有效且不会(或者更确切地说,不允许)发出新的HTTP请求。

如果用户在格林威治标准时间12:00第三次进入该页面,浏览器会看到其缓存版本现已过期(在11:53之后),因此它会尝试验证页面,向服务器发送请求使用If-Modified-Since标头。由于页面的日期自首次提供以来未被更改,因此将返回没有正文的304(未修改)响应。由于到期日期已经过去 - 页面是“陈旧的” - 每次访问页面时都会发出验证请求,直到验证失败。

现在,让我们假装你在11:57上传了一个新版本的页面。在这种情况下,浏览器尝试在12:00验证旧版本的页面失败,并且它在响应中以及新页面中接收这两个新标题:

Last-Modified: Wed, 18 Feb 2009 11:57:00 GMT
Expires: Wed, 18 Feb 2009 13:57:00 GMT

(上传新版本后文件的最后修改时间变为11:57,Apache计算到期时间为11:57 + 2:00 =格林尼治标准时间13:57。)

在13:57之前不需要验证(使用更近的日期)。

(当然请注意,上面列出的两个标题会发送许多其他内容,为了简单起见,我只是删掉了所有其他内容)

答案 1 :(得分:3)

服务器发送标题,例如:“Last-Modified: Wed, 18 Feb 2009 00:00:00 GMT”。缓存的行为基于此标头或访问时间。

如果预计每天都会刷新内容,那么您希望它在“修改加24小时”后到期。

如果您不知道何时会刷新内容,那么最好将其基于访问时间。

答案 2 :(得分:0)

我的理解是修改要求浏览器根据Last-Modificatied HTTP标头的值来建立缓存时间。因此,修改加2小时将是最后修改时间+ 2小时。

答案 3 :(得分:0)

首先,感谢David Z的详细解释。回答丛林人的问题,如果服务器仍然需要发出请求,为什么调用缓存是有意义的,答案是时间保存在服务器返回的内容中。如果缓存指令指示文件的内容仍然是新鲜的,而不是返回内容,则返回具有空响应主体的304代码。这就是节省时间的地方。

这里有一个比我给出的更好的解释,来自https://devcenter.heroku.com/articles/increasing-application-performance-with-http-cache-headers

  

虽然条件请求会通过网络调用呼叫,但未修改的资源会导致空响应正文 - 从而节省了将资源转移回最终客户端的成本。后端服务通常能够非常快速地确定资源的上次修改日期,而无需访问本身可以节省非平凡处理时间的资源。

     

基于时间

     

基于时间的条件请求确保只有在自缓存浏览器副本后请求的资源发生更改时才会传输内容。如果缓存的副本是最新的,则服务器返回304响应代码。

     

要启用条件请求,应用程序通过Last-Modified响应标头指定资源的上次修改时间。

     

Cache-Control:public,max-age = 31536000   最后修改时间:2011年1月3日星期一17:45:57 GMT

     

下次浏览器请求此资源时,如果资源的内容在此日期之后未使用If-Modified-Since请求标头,则只会询问资源的内容

     

If-Modified-Since:Mon,03 Jan 2011 17:45:57 GMT

     

如果资源自2011年1月3日星期一17:45:57 GMT后没有变化,服务器将返回一个带有304响应代码的空体。