- 什么是网络缓存?人们为什么要使用它们?
- Web缓存的种类
- Web 缓存对我来说不是坏事吗?我为什么要帮助他们?
- Web 缓存的工作原理
- 如何(以及如何不)控制缓存
- 构建缓存感知站点的技巧
- 编写缓存感知脚本
- 经常问的问题
- 实施说明 - Web 服务器
- 实施说明——服务器端脚本
- 参考资料和更多信息
- 关于本文档
什么是网络缓存?人们为什么要使用它们?
Web缓存位于一个或多个 Web 服务器(也称为 原始服务器)和一个或多个客户端之间,观察请求的到来,保存响应的副本——如 HTML 页面、图像和文件(统称为表示)——为自己。然后,如果对同一 URL 有另一个请求,它可以使用它已有的响应,而不是再次向源服务器请求它。
使用 Web 缓存有两个主要原因:
- 减少延迟——因为请求是从缓存(更靠近客户端)而不是原始服务器得到满足的,所以它获取表示并显示它所花费的时间更少。这使得 Web 看起来响应更快。
- 减少网络流量——因为表示被重用,它减少了客户端使用的带宽量。如果客户为流量付费,这可以节省资金,并使他们的带宽要求更低且更易于管理。
Web缓存的种类
浏览器缓存
如果您检查任何现代 Web 浏览器(如 Internet Explorer、Safari 或 Mozilla)的首选项对话框,您可能会注意到“缓存”设置。这使您可以留出计算机硬盘的一部分来存储您已经看到的表示,专为您而设。浏览器缓存根据相当简单的规则工作。它将检查以确保表示是新鲜的,通常是一个会话一次(即浏览器当前调用中的一次)。
当用户单击“后退”按钮或单击链接以查看他们刚刚查看的页面时,此缓存特别有用。此外,如果您在整个站点中使用相同的导航图像,它们将几乎立即从浏览器的缓存中提供。
代理缓存
Web 代理缓存的工作原理相同,但规模更大。代理以相同的方式为成百上千的用户提供服务;大公司和 ISP 通常将它们设置在他们的防火墙上,或作为独立设备(也称为中介)。
因为代理缓存不是客户端或原始服务器的一部分,而是在网络上,所以请求必须以某种方式路由到它们。一种方法是使用浏览器的代理设置手动告诉它使用什么代理;另一个正在使用拦截。拦截代理通过底层网络本身将 Web 请求重定向到它们,因此客户端不需要为它们进行配置,甚至不需要知道它们。
代理缓存是一种共享缓存;他们通常拥有大量用户,而不是只有一个人使用它们,因此他们非常擅长减少延迟和网络流量。那是因为流行的表示被重复使用了很多次。
网关缓存
也称为“反向代理缓存”或“代理缓存”,网关缓存也是中介,但它们不是由网络管理员部署以节省带宽,而是通常由网站管理员自己部署,以使他们的网站更具可扩展性、可靠性和表现更好。
可以通过多种方法将请求路由到网关缓存,但通常使用某种形式的负载平衡器使其中一个或多个看起来像客户端的原始服务器。
内容分发网络(CDN) 在整个 Internet(或其中的一部分)中分发网关缓存,并将缓存出售给感兴趣的网站。Speedera和Akamai是 CDN 的例子。
本教程主要关注浏览器和代理缓存,尽管有些信息也适合那些对网关缓存感兴趣的人。
Web 缓存对我来说不是坏事吗?我为什么要帮助他们?
Web 缓存是 Internet 上最容易被误解的技术之一。网站管理员尤其害怕失去对网站的控制,因为代理缓存可以“隐藏”他们的用户,使他们很难看到谁在使用该网站。
对他们来说不幸的是,即使不存在 Web 缓存,Internet 上的变数也太多,无法确保他们能够准确了解用户如何查看他们的站点。如果这对您来说是一个大问题,本教程将教您如何在不使您的站点缓存不友好的情况下获取所需的统计信息。
另一个问题是缓存可以提供过时或 陈旧的内容。但是,本教程可以向您展示如何配置服务器以控制内容的缓存方式。
CDN 是一个有趣的发展,因为与许多代理缓存不同,它们的网关缓存与被缓存的网站的利益保持一致,因此不会出现这些问题。但是,即使你使用了 CDN,你仍然要考虑到下游会有代理和浏览器缓存。
另一方面,如果您很好地规划您的网站,缓存可以帮助您的网站更快地加载,并节省您的服务器和 Internet 链接的负载。差异可能是巨大的;一个难以缓存的站点可能需要几秒钟才能加载,而相比之下,利用缓存的站点似乎是瞬时的。用户会喜欢加载速度快的站点,并且会更频繁地访问。
这样想;许多大型互联网公司正花费数百万美元在世界各地建立服务器群来复制他们的内容,以便让他们的用户尽可能快地访问这些内容。缓存为您做同样的事情,而且它们更接近最终用户。最重要的是,您无需为它们付费。
事实上,无论您喜欢与否,都会使用代理和浏览器缓存。如果您没有正确配置要缓存的站点,它将使用缓存管理员决定的任何默认值进行缓存。
Web 缓存的工作原理
所有缓存都有一组规则,它们使用这些规则来确定何时从缓存中提供表示(如果可用)。这些规则有些是在协议中设置的(HTTP 1.0 和 1.1),有些是由缓存的管理员(浏览器缓存的用户,或者代理管理员)设置的。
一般来说,这些是最常见的遵循规则(如果你不明白细节,不要担心,下面会解释):
- 如果响应的标头告诉缓存不要保留它,它就不会。
- 如果请求经过身份验证或安全(即 HTTPS),它将不会被共享缓存缓存。
- 在以下情况下,缓存的表示被认为是新鲜的(即,无需检查原始服务器即可发送到客户端):
- 它有过期时间或其他年龄控制标头集,并且仍在新鲜期限内,或者
- 如果缓存最近看到过表示,并且它是相对很久以前修改的。
新的表示直接从缓存中提供,无需与原始服务器核对。
- 如果表示过时,将要求源服务器对其进行 验证,或告诉缓存它拥有的副本是否仍然有效。
- 在某些情况下——例如,当它与网络断开连接时——缓存可以在不检查源服务器的情况下提供陈旧的响应。
如果响应中没有验证器(ETag
或标头),并且没有任何明确的新鲜度信息,则通常(但并非总是)将其视为不可缓存。Last-Modified
总之,新鲜度和验证是缓存处理内容的最重要方式。一个新的表示将立即从缓存中可用,而一个经过验证的表示将避免再次发送整个表示,如果它没有改变的话。
如何(以及如何不)控制缓存
Web 设计人员和网站管理员可以使用多种工具来微调缓存如何处理他们的网站。这可能需要您动手操作服务器的配置,但结果是值得的。有关如何在您的服务器上使用这些工具的详细信息,请参阅下面的实施部分。
HTML 元标记和 HTTP 标头
HTML 作者可以将标记放在文档的 <HEAD> 部分来描述其属性。这些元标记通常用于相信它们可以将文档标记为不可缓存,或在特定时间使其过期。
元标记易于使用,但不是很有效。那是因为它们只受到少数浏览器缓存的尊重,而不是代理缓存(几乎从不读取文档中的 HTML)。虽然将 Pragma: no-cache 元标记放入网页中可能很诱人,但它不一定会使网页保持最新。
Expires
如果您的站点托管在 ISP 或托管农场,并且他们不给您设置任意 HTTP 标头(如和 Cache-Control
)的能力,请大声抱怨;这些是完成工作所必需的工具。
另一方面,真正的HTTP 标头可让您对浏览器缓存和代理如何处理您的表示进行大量控制。它们在 HTML 中是看不到的,通常由 Web 服务器自动生成。但是,您可以在某种程度上控制它们,具体取决于您使用的服务器。在以下部分中,您将了解哪些 HTTP 标头很有趣,以及如何将它们应用到您的站点。
HTTP 标头由服务器在 HTML 之前发送,并且只能被浏览器和任何中间缓存看到。典型的 HTTP 1.1 响应标头可能如下所示:
HTTP/1.1 200 OK 日期:1998 年 10 月 30 日星期五 13:19:41 GMT 服务器:Apache/1.3.3 (Unix) 缓存控制:max-age=3600,必须重新验证 过期:1998 年 10 月 30 日星期五 14:格林威治标准时间 19:41 最后修改时间:1998 年 6 月 29 日星期一 02:28:12 GMT ETag:“3e86-410-3596fbbc” 内容长度:1040 内容类型:文本/html
HTML 将跟在这些标题之后,由空行分隔。有关如何设置 HTTP 标头的信息,请参阅实施部分。
Pragma HTTP 标头(以及为什么它们不起作用)
许多人认为将Pragma: no-cache
HTTP 标头分配给表示会使它无法缓存。这不一定是真的; HTTP 规范没有为 Pragma 响应标头设置任何指南;相反,讨论了 Pragma 请求标头(浏览器发送到服务器的标头)。虽然一些缓存可能会尊重这个标头,但大多数不会,而且它不会有任何影响。请改用下面的标题。
使用 Expires HTTP 标头控制新鲜度
HTTPExpires
头是控制缓存的基本手段;它告诉所有缓存相关表示的新鲜时间。在那之后,缓存将始终与原始服务器核对以查看文档是否已更改。Expires
几乎每个缓存都支持标头。
Expires
大多数 Web 服务器允许您以多种方式设置响应标头。通常,它们将允许设置一个绝对过期时间,一个基于客户端最后一次检索表示的时间(上次访问时间),或者一个基于上次文档在您的服务器上更改的时间(上次修改时间) .
Expires
标头特别适合使静态图像(如导航栏和按钮)可缓存。因为它们变化不大,所以您可以为它们设置极长的到期时间,使您的网站对用户的响应速度更快。它们对于控制定期更改的页面的缓存也很有用。例如,如果您每天早上 6 点更新一次新闻页面,您可以将表示设置为在该时间过期,这样缓存将知道何时获取新副本,而无需用户点击“重新加载”。
标头中唯一有效的值Expires
是 HTTP 日期;其他任何东西很可能会被解释为“过去”,因此表示是不可缓存的。另外,请记住 HTTP 日期中的时间是格林威治标准时间 (GMT),而不是本地时间。
例如:
过期时间:1998 年 10 月 30 日星期五 14:19:41 GMT
如果您使用标头,请务必确保您的 Web 服务器的时钟准确无误Expires
。一种方法是使用网络时间协议(NTP);与您的本地系统管理员联系以了解更多信息。
尽管Expires
标头很有用,但它有一些限制。首先,因为涉及日期,Web 服务器上的时钟和缓存必须同步;如果他们对时间有不同的想法,将无法实现预期的结果,并且缓存可能会错误地将陈旧内容视为新鲜内容。
另一个问题Expires
是很容易忘记您已将某些内容设置为在特定时间过期。如果您不在Expires
时间过去之前更新时间,每个请求都会返回到您的 Web 服务器,从而增加负载和延迟。
缓存控制 HTTP 标头
HTTP 1.1 引入了一类新的标头,即Cache-Control
响应标头,使 Web 发布者能够更好地控制其内容,并解决Expires
.
有用的Cache-Control
响应标头包括:
max-age=
[seconds] — 指定表示将被视为新鲜的最长时间。与 类似Expires
,该指令是相对于请求的时间,而不是绝对的。[seconds] 是从您希望表示新鲜的请求时间开始的秒数。s-maxage=
[seconds] — 类似于max-age
,只是它仅适用于共享(例如,代理)缓存。public
— 将经过身份验证的响应标记为可缓存;通常,如果需要 HTTP 身份验证,响应将自动保密。private
— 允许特定于一个用户的缓存(例如,在浏览器中)存储响应;共享缓存(例如,在代理中)可能不会。no-cache
— 每次释放缓存副本之前,强制缓存将请求提交给源服务器进行验证。这有助于确保尊重身份验证(与公开相结合),或保持严格的新鲜度,而不牺牲缓存的所有好处。no-store
— 指示缓存在任何情况下都不要保留表示的副本。must-revalidate
— 告诉缓存它们必须遵守您提供给它们的关于表示的任何新鲜度信息。HTTP 允许缓存在特殊条件下提供陈旧的表示;通过指定此标头,您告诉缓存您希望它严格遵守您的规则。proxy-revalidate
— 类似于must-revalidate
,只是它只适用于代理缓存。
例如:
缓存控制:max-age=3600,必须重新验证
当 和Cache-Control
都Expires
存在时, Cache-Control
优先。如果您打算使用 Cache-Control
标头,则应该查看 HTTP 1.1 中的优秀文档;请参阅参考资料和更多信息。
验证器和验证
在Web 缓存的工作原理中,我们说过服务器和缓存在表示发生变化时使用验证进行通信。通过使用它,缓存可以避免在本地已经有副本但不确定它是否仍然新鲜时必须下载整个表示。
验证器非常重要;如果一个不存在,并且没有任何可用的新鲜度信息(Expires
或Cache-Control
),则缓存根本不会存储表示。
最常见的验证器是文档上次更改的时间,如Last-Modified
标头中所示。当缓存存储了包含Last-Modified
标头的表示时,它可以使用它来询问服务器自上次看到以来表示是否已更改,并发出请求If-Modified-Since
。
HTTP 1.1 引入了一种称为ETag 的新型验证器。ETag 是由服务器生成的唯一标识符,每次表示时都会更改。因为服务器控制着 ETag 的生成方式,所以缓存可以确保如果 ETag 在它们发出请求时匹配 If-None-Match
,则表示确实是相同的。
几乎所有缓存都使用 Last-Modified 时间作为验证器;ETag 验证也变得普遍。
大多数现代 Web 服务器都会自动生成ETag
和Last-Modified
标头以用作静态内容(即文件)的验证器;你不需要做任何事情。但是,他们对动态内容(如 CGI、ASP 或数据库站点)了解不够,无法生成它们;请参阅编写缓存感知脚本。
构建缓存感知站点的技巧
除了使用新鲜度信息和验证之外,您还可以采取许多其他措施来使您的网站对缓存更友好。
- 始终如一地使用 URL——这是缓存的黄金法则。如果您在不同的页面上向不同的用户或来自不同的站点提供相同的内容,则它应该使用相同的 URL。这是使您的站点缓存友好的最简单和最有效的方法。例如,如果您在 HTML 中使用过一次“/index.html”作为参考,请始终以这种方式使用。
- 使用一个通用的图像和其他元素库,并从不同的地方回顾它们。
- 通过使用
Cache-Control: max-age
具有较大值的标头,使缓存存储不经常更改的图像和页面。 - 通过指定适当的最长期限或过期时间,使缓存识别定期更新的页面。
- 如果资源(尤其是可下载文件)发生变化,请更改其名称。这样,您可以让它在很久以后过期,并且仍然保证提供正确的版本;链接到它的页面是唯一需要较短到期时间的页面。
- 不要不必要地更改文件。如果你这样做,一切都会有一个虚假的年轻
Last-Modified
日期。例如,在更新您的网站时,不要复制整个网站;只需移动您已更改的文件即可。 - 仅在必要时使用 cookie ——cookie 难以缓存,并且在大多数情况下不需要。如果您必须使用 cookie,请将其用于动态页面。
- 使用REDbot检查您的页面 — 它可以帮助您应用本教程中的许多概念。
编写缓存感知脚本
默认情况下,大多数脚本不会返回验证器(aLast-Modified
或ETag
响应标头)或新鲜度信息(Expires
或Cache-Control
)。虽然有些脚本确实是动态的(这意味着它们对每个请求返回不同的响应),但许多脚本(如搜索引擎和数据库驱动的站点)可以从缓存友好中受益。
一般来说,如果一个脚本产生的输出可以在稍后的时间(无论是几分钟还是几天后)用相同的请求重现,那么它应该是可缓存的。如果脚本的内容只根据 URL 中的内容而改变,那么它是可缓存的;如果输出取决于 cookie、身份验证信息或其他外部标准,则可能不是。
- 使脚本缓存友好(以及性能更好)的最佳方法是在内容发生变化时将其内容转储到普通文件中。然后 Web 服务器可以像对待任何其他网页一样对待它,生成和使用验证器,这使您的生活更轻松。请记住只写入已更改的文件,以便
Last-Modified
保留时间。 - 使脚本以有限的方式可缓存的另一种方法是为尽可能远的将来设置一个与年龄相关的标头。虽然这可以用 完成
Expires
,但使用 可能最容易Cache-Control: max-age
,这将使请求在请求后的一段时间内保持新鲜。 - 如果你不能这样做,你需要让脚本生成一个验证器,然后响应和
If-Modified-Since
/或If-None-Match
请求。这可以通过解析 HTTP 标头,然后304 Not Modified
在适当的时候响应来完成。不幸的是,这不是一项简单的任务。
其他一些技巧;
- 除非合适,否则不要使用 POST 。大多数缓存不保存对 POST 方法的响应;如果您在路径或查询中发送信息(通过 GET),缓存可以存储该信息以备将来使用。
- 不要在 URL 中嵌入特定于用户的信息,除非生成的内容对该用户来说是完全独一无二的。
- 不要指望来自同一个主机的用户的所有请求,因为缓存通常一起工作。
- 生成
Content-Length
响应标头。这很容易做到,而且它将允许您的脚本的响应在持久连接中使用 。这允许客户端在一个 TCP/IP 连接上请求多个表示,而不是为每个请求都建立一个连接。它使您的网站看起来更快。
有关更多具体信息,请参阅实施说明。
经常问的问题
使可缓存最重要的事情是什么?
一个好的策略是确定最受欢迎、最大的表示(尤其是图像)并首先使用它们。
如何使用缓存使我的页面尽可能快?
最可缓存的表示是具有较长新鲜时间集的表示。验证确实有助于减少查看表示所花费的时间,但缓存仍然必须联系原始服务器以查看它是否是新鲜的。如果缓存已经知道它是新鲜的,它将被直接提供。
我知道缓存很好,但我需要统计有多少人访问了我的页面!
如果您必须知道每次访问页面时,请在页面(或页面本身)上选择一个小项目,并通过为其提供合适的标题使其不可缓存。例如,您可以引用每个页面中的 1x1 透明不可缓存图像。标Referer
头将包含有关调用它的页面的信息。
请注意,即使这样也无法提供有关您的用户的真正准确的统计数据,并且对 Internet 和您的用户不友好;它会产生不必要的流量,并迫使人们等待下载未缓存的项目。有关这方面的更多信息,请参阅参考资料中的关于解释访问统计信息。
如何查看表示的 HTTP 标头?
许多 Web 浏览器让您在“页面信息”或类似界面中看到Expires
和标头。Last-Modified
如果可用,这将为您提供页面菜单和与之关联的任何表示(如图像)及其详细信息。
要查看表示的完整标头,您可以使用 Telnet 客户端手动连接到 Web 服务器。
为此,您可能需要在单独的字段中键入端口(默认为 80),或者您可能需要连接到www.example.com:80
或www.example.com 80
(注意空格)。请查阅 Telnet 客户端的文档。
打开与该站点的连接后,键入对表示的请求。例如,如果您想查看 http://www.example.com/foo.html
、连接到www.example.com
、端口80
和类型的标头:
GET /foo.html HTTP/1.1 [返回] 主机:www.example.com [返回][返回]
每次看到 时按 Return 键[return]
;确保最后按两次。这将打印标题,然后是完整的表示。要仅查看标头,请将 HEAD 替换为 GET。
我的页面受密码保护;代理缓存如何处理它们?
默认情况下,受 HTTP 身份验证保护的页面被认为是私有的;它们不会被共享缓存保存。但是,您可以使用 Cache-Control: public 标头公开经过身份验证的页面;HTTP 1.1 兼容的缓存将允许它们被缓存。
如果您希望此类页面可缓存,但仍对每个用户进行身份验证,请结合Cache-Control: public
和no-cache
标头。这告诉缓存它必须在从缓存中释放表示之前将新客户端的身份验证信息提交给源服务器。这看起来像:
缓存控制:公共,无缓存
无论是否这样做,最好尽量减少身份验证的使用;例如,如果您的图像不敏感,请将它们放在单独的目录中,并配置您的服务器不要强制对其进行身份验证。这样,这些图像将自然可缓存。
如果人们通过缓存访问我的网站,我是否应该担心安全问题?
https://
代理缓存不会缓存(或解密)页面,因此您不必担心。但是,因为缓存存储http://
响应和通过它们获取的 URL,所以您应该注意不安全的站点;不道德的管理员可能会收集有关其用户的信息,尤其是在 URL 中。
事实上,您的服务器和客户端之间的网络上的任何管理员都可以收集此类信息。一个特别的问题是当 CGI 脚本将用户名和密码放在 URL 本身时;这使得其他人可以轻松找到并使用他们的登录名。
如果您总体上了解围绕 Web 安全的问题,那么您应该不会对代理缓存感到惊讶。
我正在寻找一个集成的 Web 发布解决方案。哪些是缓存感知的?
它各不相同。一般来说,解决方案越复杂,缓存就越困难。最糟糕的是那些动态生成所有内容并且不提供验证器的;它们可能根本无法缓存。与供应商的技术人员联系以获取更多信息,并参阅下面的实施说明。
我的图像一个月后就会过期,但我现在需要在缓存中更改它们!
无法绕过 Expires 标头;除非缓存(浏览器或代理)用完空间并且必须删除表示,否则将使用缓存副本直到那时。
最有效的解决方案是更改指向它们的任何链接;这样,全新的表示将从源服务器重新加载。请记住,任何引用这些表示的页面也将被缓存。因此,最好使静态图像和类似表示非常易于缓存,同时严格控制引用它们的 HTML 页面。
Pragma: no-cache
如果您想从特定缓存重新加载表示,您可以在使用缓存时强制重新加载(在 Firefox 中,按住 shift 键的同时按下“重新加载”将通过发出请求标头来执行此操作)。或者,您可以让缓存管理员通过他们的界面删除表示。
我运行虚拟主机服务。我怎样才能让我的用户发布缓存友好的页面?
如果您使用的是 Apache,请考虑允许他们使用 .htaccess 文件并提供适当的文档。
否则,您可以为每个虚拟服务器中的各种缓存属性建立预定区域。例如,您可以指定一个目录 /cache-1m,该目录将在访问后缓存一个月,以及一个 /no-cache 区域,该区域将提供标头,指示缓存不要存储来自它的表示。
无论您能做什么,最好首先与最大的客户合作进行缓存。大部分节省(带宽和服务器负载)将从高容量站点实现。
我已将我的页面标记为可缓存,但我的浏览器会在每次请求时不断请求它们。我如何强制缓存保留它们的表示?
不需要缓存来保留表示并重用它;他们只需要在某些情况下不保留或使用它们。所有缓存都根据它们的大小、类型(例如,图像与 html)或它们保留本地副本的剩余空间来决定保留哪些表示。与更受欢迎或更大的代表相比,您的可能不值得保留。
一些缓存确实允许它们的管理员确定保留哪种表示的优先级,还有一些允许将表示“固定”在缓存中,以便它们始终可用。
实施说明 - Web 服务器
一般来说,最好使用您选择部署的任何 Web 服务器的最新版本。它们不仅可能包含更多对缓存友好的功能,而且新版本通常还具有重要的安全性和性能改进。
HTTP 服务器
Apache使用可选模块来包含标头,包括 Expires 和 Cache-Control。这两个模块都在 1.2 或更高版本中可用。
这些模块需要内置到 Apache 中;尽管它们包含在发行版中,但默认情况下它们并未打开。要了解您的服务器是否启用了这些模块,请找到 httpd 二进制文件并运行httpd -l
;这应该打印可用模块的列表(请注意,这仅列出编译的模块;在更高版本的 Apache 上,httpd -M
也用于包括动态加载的模块)。我们正在寻找的模块是 expires_module 和 headers_module。
- 如果它们不可用,并且您有管理访问权限,则可以重新编译 Apache 以包含它们。这可以通过取消注释配置文件中适当的行,或使用
-enable-module=expires
和-enable-module=headers
参数来配置(1.3 或更高版本)来完成。查阅在 Apache 发行版中找到的 INSTALL 文件。
一旦你有了一个带有适当模块的 Apache,你就可以使用 mod_expires 来指定表示何时应该过期,在 .htaccess 文件或服务器的 access.conf 文件中。您可以指定访问或修改时间的到期时间,并将其应用于文件类型或作为默认值。有关详细信息,请参阅模块文档,如果遇到问题,请与当地的 Apache 专家联系。
要应用Cache-Control
标头,您需要使用 mod_headers 模块,它允许您为资源指定任意 HTTP 标头。请参阅mod_headers 文档。
下面是一个示例 .htaccess 文件,它演示了一些标头的使用。
- .htaccess 文件允许 Web 发布者使用通常只能在配置文件中找到的命令。它们会影响所在目录及其子目录的内容。与您的服务器管理员联系以了解它们是否已启用。
### activate mod_expires ExpiresActive On ### Expires .gif's 1 month from when they're accessed ExpiresByType image/gif A2592000 ### Expire else everything 1 day from when it's last modified ###(这使用替代语法) ExpiresDefault "修改加1天" ### Apply a Cache-Control header to index.html <Files index.html> Header append Cache-Control "public, must-revalidate" </Files>
- 请注意,mod_expires 会
Cache-Control:max-age
根据需要自动计算并插入标头。
Apache 2 的配置与 1.3 非常相似; 有关详细信息,请参阅 2.2 mod_expires和 mod_headers文档。
微软IIS
Microsoft的 Internet Information Server 使得以某种灵活的方式设置标头变得非常容易。请注意,这仅在服务器版本 4 中才有可能,该版本仅在 NT Server 上运行。
要为网站的某个区域指定标题,请在 Administration Tools
界面中选择它,然后调出其属性。选择选项HTTP Headers
卡后,您应该会看到两个有趣的区域;Enable Content Expiration
和Custom HTTP headers
。第一个应该是不言自明的,第二个可用于应用 Cache-Control 标头。
有关在 Active Server Pages 中设置标头的信息,请参阅下面的 ASP 部分。也可以从 ISAPI 模块设置标头;有关详细信息,请参阅 MSDN。
Netscape/iPlanet 企业服务器
从 3.6 版开始,Enterprise Server 不提供任何明显的方法来设置 Expires 标头。但是,它从 3.0 版本开始就支持 HTTP 1.1 的特性。这意味着 HTTP 1.1 缓存(代理和浏览器)将能够利用您所做的缓存控制设置。
要使用 Cache-Control 标头,请Content Management | Cache Control Directives
在管理服务器中选择。然后,使用资源选择器,选择要设置标题的目录。设置标题后,单击“确定”。有关详细信息,请参阅NES 手册。
实施说明——服务器端脚本
要记住的一件事是,使用 Web 服务器设置 HTTP 标头可能比使用脚本语言更容易。两者都试试。
因为服务器端脚本的重点是动态内容,所以即使内容可以被缓存,也不会产生非常可缓存的页面。如果您的内容经常更改,但不是每次点击时都会更改,请考虑设置 Cache-Control: max-age 标头;大多数用户会在相对较短的时间内再次访问页面。例如,当用户点击“后退”按钮时,如果没有可用的验证器或新鲜度信息,他们将不得不等到页面从服务器重新下载后才能看到。
电脑影像
CGI 脚本是最流行的内容生成方式之一。您可以通过在发送正文之前添加 HTTP 响应标头来轻松附加它们;大多数 CGI 实现已经要求您为标头执行此操作 Content-Type
。例如,在 Perl 中;
#!/usr/bin/perl print "Content-type: text/html\n"; 打印“过期时间:1998 年 10 月 29 日星期四 17:04:19 GMT\n”; 打印“\n”; ### 内容正文如下...
因为它都是文本,所以您可以使用Expires
内置函数轻松生成和其他与日期相关的标题。如果你使用它会更容易 Cache-Control: max-age
;
打印“缓存控制:最大年龄=600\n”;
这将使脚本在请求后可缓存 10 分钟,这样如果用户点击“后退”按钮,他们就不会重新提交请求。
CGI 规范还使客户端发送的请求标头在脚本环境中可用;每个标头的名称前都有“HTTP_”。因此,如果客户端发出请求If-Modified-Since
,它将显示为HTTP_IF_MODIFIED_SINCE
.
服务器端包括
SSI(通常与扩展名 .shtml 一起使用)是 Web 发布者能够将动态内容放入页面的首批方式之一。通过在页面中使用特殊标记,可以使用有限形式的 in-HTML 脚本。
大多数 SSI 实现不设置验证器,因此不可缓存。但是,Apache 的实现确实允许用户指定可以缓存哪些 SSI 文件,方法是在适当的文件上设置组执行权限,并结合指令XbitHack full
。有关详细信息,请参阅mod_include 文档。
PHP
PHP是一种服务器端脚本语言,当内置于服务器中时,可用于将脚本嵌入到页面的 HTML 中,与 SSI 非常相似,但具有更多的选项。PHP 可以用作任何 Web 服务器(Unix 或 Windows)上的 CGI 脚本,或用作 Apache 模块。
默认情况下,PHP 处理的表示没有分配验证器,因此是不可缓存的。但是,开发人员可以使用该Header()
函数设置 HTTP 标头。
例如,这将创建一个 Cache-Control 标头,以及一个三天后的 Expires 标头:
<?php Header("Cache-Control: must-revalidate"); $偏移量 = 60 * 60 * 24 * 3; $ExpStr = "过期:" . gmdate("D, d MYH:i:s", time() + $offset) 。“ 格林威治标准时间”; 标题($ExpStr); ?>
请记住,Header()
函数必须出现在任何其他输出之前。
如您所见,您必须Expires
手动为标头创建 HTTP 日期;PHP 不提供为您做这件事的功能(尽管最近的版本使它更容易;请参阅PHP 的日期文档)。当然,设置 a 很容易Cache-Control: max-age header
,这对大多数情况都适用。
有关详细信息,请参阅header 的手册条目。
冷聚变
Macromedia的Cold Fusion是一种商业服务器端脚本引擎,支持 Windows、Linux 和几种 Unix 上的多种 Web 服务器。
Cold Fusion 使用标记使设置任意 HTTP 标头相对容易 CFHEADER 。不幸的是,他们设置
Expires
标头的示例(如下所示)有点误导。
<CFHEADER NAME="Expires" VALUE="#Now()#">
它并不像您想象的那样工作,因为时间(在本例中是发出请求的时间)没有转换为 HTTP 有效日期;相反,它只是作为 Cold Fusion 的日期/时间对象的表示形式打印出来。大多数客户端要么忽略这样的值,要么将其转换为默认值,例如 1970 年 1 月 1 日。
但是,Cold Fusion 确实提供了可以完成这项工作的日期格式化功能; GetHttpTimeString. 结合,很容易设置过期日期;在这里,我们设置一个标题来声明该页面的表示在一个月后过期;
DateAdd
<cfheader name="Expires" value="#GetHttpTimeString(DateAdd('m', 1, Now()))#">
您还可以使用CFHEADER
标签来设置Cache-Control: max-age
和其他标头。
请记住,Web 服务器标头在 Cold Fusion 的某些部署(例如 CGI)中被传递;通过在服务器上而不是在 Cold Fusion 中设置标头,检查你的以确定是否可以利用它来发挥你的优势。
ASP 和 ASP.NET
从 ASP 设置 HTTP 标头时,请确保在任何 HTML 生成之前放置 Response 方法调用,或用于 Response.Buffer
缓冲输出。另请注意,某些版本的 IISCache-Control: private
默认在 ASP 上设置标头,并且必须声明为公共才能由共享缓存缓存。
Active Server Pages 内置于 IIS 中,也可用于其他 Web 服务器,还允许您设置 HTTP 标头。例如,要设置过期时间,您可以使用Response
对象的属性;
<% Response.Expires=1440 %>
指定从请求到表示过期的分钟数。Cache-Control
标题可以这样添加:
<% Response.CacheControl="public" %>
在 ASP.NET 中,Response.Expires
已弃用;设置与缓存相关的标头的正确方法是使用Response.Cache
;
Response.Cache.SetExpires(DateTime.Now.AddMinutes(60)); Response.Cache.SetCacheability (HttpCacheability.Public);
参考资料和更多信息
HTTP 规范
HTTP 规范是实施该协议的权威指南。
关于解释访问统计
Jeff Goldberg 关于为什么你不应该依赖访问统计和点击计数器的信息丰富的咆哮。
小红人
检查 HTTP 资源以确定它们将如何与 Web 缓存交互,以及它们通常如何使用该协议。
via https://www.mnot.net/cache_docs/