📄 caching.html
字号:
<li>如果应答的状态码是200(OK),除非明确打开了<code class="directive"><a href="./mod/mod_cache.html#cacheignorenolastmod">CacheIgnoreNoLastMod</a></code>指令,否则该应答还必须至少包含一个"Etag"、"Last-Modified"或"Expires"头才能被缓存。</li>
<li>如果应答头"Cache-Control:"中包含"private"选项,除非明确打开了<code class="directive"><a href="./mod/mod_cache.html#cachestoreprivate">CacheStorePrivate</a></code>指令,否则将不被缓存。</li>
<li>同样,如果应答头"Cache-Control:"中包含"no-store"选项,除非明确打开了<code class="directive"><a href="./mod/mod_cache.html#cachestorenostore">CacheStoreNoStore</a></code>指令,否则将不被缓存。</li>
<li>如果应答包含"Vary:"头,并且其中包含通配符"*"(匹配所有),也将不被缓存。</li>
</ol>
<h3>什么不应该被缓存?</h3>
<p>简而言之,随时间变化的内容不应该被缓存;取决于特定请求的内容不应该被缓存;依赖于不被HTTP内容协商处理的请求的内容也不应该被缓存。[本句翻译的很没把握,原文:In short, any content which is highly time-sensitive, or which varies depending on the particulars of the request that are not covered by HTTP negotiation, should not be cached.]</p>
<p>如果你有某些动态内容,它们的变化依赖于请求发起者的IP地址或者差不多每5分钟就会发生改变,那么这些内容毫无疑问是不应该被缓存的。</p>
<p>另一方面,如果内容的变化依赖于各种HTTP头,更加明智的做法可能是通过使用"Vary"头进行缓存。</p>
<h3>易变的/协商的内容</h3>
<p>当<code class="module"><a href="./mod/mod_cache.html">mod_cache</a></code>接收到一个后端发出的、带有"Vary"头的应答的时候,它将尽可能智能的处理它。如果有机会,<code class="module"><a href="./mod/mod_cache.html">mod_cache</a></code>将会检查之后进入的请求的"Vary"头属性,然后用正确的缓冲区内容为这个请求提供服务。</p>
<p>举个例子来说,接收到一个带有如下"Vary"头的应答:</p>
<div class="example"><p><code>
Vary: negotiate,accept-language,accept-charset
</code></p></div>
<p><code class="module"><a href="./mod/mod_cache.html">mod_cache</a></code>将只会使用与原始请求的accept-language和accept-charset头匹配的缓存内容来提供服务。</p>
</div><div class="top"><a href="#page-header"><img alt="top" src="./images/up.gif" /></a></div>
<div class="section">
<h2><a name="security" id="security">安全方面的考虑</a></h2>
<h3>授权(Authorisation),访问控制(Access & Control)</h3>
<p><code class="module"><a href="./mod/mod_cache.html">mod_cache</a></code>非常像一个内置的反向代理(reverse-proxy)。除非必须要向后端提交请求,否则缓冲模块将直接为请求提供服务。对于缓冲本地资源,这种模式彻底改变了Apache的安全模型。</p>
<p>因为遍历文件系统的目录结构以寻找可能存在的<code>.htaccess</code>文件是一个开销非常昂贵的操作,它部分地抵消了缓冲所带来的好处(加速请求),所以<code class="module"><a href="./mod/mod_cache.html">mod_cache</a></code>并不检查缓存中的实体是否被允许(authorised)用于提供服务。换句话说,只要<code class="module"><a href="./mod/mod_cache.html">mod_cache</a></code>中缓存的内容尚未失效,那么它们将被直接用于为请求提供服务。</p>
<p>举例来说,如果你为某个资源按照IP地址配置了访问许可,你必须要确保这些内容不被缓存。你可以使用<code class="directive"><a href="./mod/mod_cache.html#cachedisable">CacheDisable</a></code>指令或<code class="module"><a href="./mod/mod_expires.html">mod_expires</a></code>模块达到这个目的。不做权限检查的<code class="module"><a href="./mod/mod_cache.html">mod_cache</a></code>模块非常像一个反向代理:缓存内容并用缓存的内容向任意IP地址上的任意客户提供服务。</p>
<h3>本地利用(Local exploits)</h3>
<p>因为终端用户的请求可以由缓冲区直接提供服务,所以缓冲区自身便成为一个那些企图干扰、破坏内容的攻击者的攻击目标。很重要的、需要牢记的一点是:缓冲区必须始终对运行Apache的用户是可写的。这正好与通常的原则:始终保持所有内容对运行Apache的用户不可写,完全相反!</p>
<p>如果运行Apache的用户是潜在的不安全用户,比如,通过一个有漏洞的CGI进程,就有可能对缓冲区发起攻击,当使用<code class="module"><a href="./mod/mod_disk_cache.html">mod_disk_cache</a></code>的时候,就很容易插入或者修改缓冲区中内容。</p>
<p>这样一来,运行Apache的用户就会增加一个与其它类型的攻击相比更加危险的安全隐患。如果你正在使用<code class="module"><a href="./mod/mod_disk_cache.html">mod_disk_cache</a></code> ,你必须时刻牢记:确保为Apache及时打上所有的安全补丁并且使用<a href="suexec.html">suEXEC</a>以一个不同于运行Apache用户的其他用户身份运行CGI进程。</p>
<h3>缓存中毒(Cache Poisoning)</h3>
<p>当将Apache作为一个缓冲代理服务器运行的时候,将可能存在一个所谓"缓存中毒"的问题。"缓存中毒"是一个泛称术语,用于指代各种造成代理服务器从后台检索到错误内容的攻击。</p>
<p>举个例子来说,如果你运行Apache的系统所使用的DNS服务器发生了DNS缓存中毒,攻击者将可能欺骗Apache连接到一个错误的服务器去请求内容。另一个例子是所谓的HTTP请求走私(request-smuggling)攻击。</p>
<p>这篇文档并不是深入探讨HTTP请求走私的地方(你应当去问<a href="http://www.google.com/">google</a>),但有一点你必须知道:攻击者可以通过制造一连串的请求并利用原始web服务器的漏洞,达到完全控制代理服务器所检索到的内容的目的。</p>
</div><div class="top"><a href="#page-header"><img alt="top" src="./images/up.gif" /></a></div>
<div class="section">
<h2><a name="filehandle" id="filehandle">文件句柄缓冲(File-Handle Caching)</a></h2>
<table border="1" cellpadding="0" cellspacing="0" bordercolor="#AAAAAA" class="related">
<tr><th>相关模块</th><th>相关指令</th></tr>
<tr><td><ul><li><code class="module"><a href="./mod/mod_file_cache.html">mod_file_cache</a></code></li><li><code class="module"><a href="./mod/mod_mem_cache.html">mod_mem_cache</a></code></li></ul></td><td><ul><li><code class="directive"><a href="./mod/mod_file_cache.html#cachefile">CacheFile</a></code></li><li><code class="directive"><a href="./mod/mod_cache.html#cacheenable">CacheEnable</a></code></li><li><code class="directive"><a href="./mod/mod_cache.html#cachedisable">CacheDisable</a></code></li></ul></td></tr>
</table>
<p>打开文件的动作本身就是一个造成延时的原因,特别是打开网络文件系统中的文件。通过维护一个保存高使用率文件的文件描述符的缓冲区,Apache就可以避免这种延时。当前,Apache提供了两种不同的文件句柄缓冲实现方法。</p>
<h3>缓冲文件(CacheFile)</h3>
<p>存在于Apache中最基本的缓冲方式是由<code class="module"><a href="./mod/mod_file_cache.html">mod_file_cache</a></code>实现的文件句柄(file-handle)缓冲。胜于缓存文件内容本身,这个缓冲区维护一张打开的文件描述符表,用于保存在配置文件中使用<code class="directive"><a href="./mod/mod_file_cache.html#cachefile">CacheFile</a></code>指令指定的文件的文件句柄。</p>
<p><code class="directive"><a href="./mod/mod_file_cache.html#cachefile">CacheFile</a></code>指令指示Apache在启动时打开某个文件并且为所有之后对这个文件的访问重复使用这个文件句柄。</p>
<div class="example"><pre>CacheFile /usr/local/apache2/htdocs/index.html</pre></div>
<p>如果你打算使用这种方式缓存大量的文件句柄,你必须确保操作系统对同时打开的文件的数量限制是足够的。</p>
<p>虽然使用<code class="directive"><a href="./mod/mod_file_cache.html#cachefile">CacheFile</a></code>不会导致文件的内容被缓存,但是将会导致在Apache运行期间所有对文件的更改都不会生效。用于提供服务的文件的内容将从Apache启动以来一直保持不变。</p>
<p>如果在Apache运行期间文件被删除了,Apache将会持续维护一个打开的文件描述符并且使用Apache启动时文件的内容来提供服务。这个通常也意味着虽然文件已经被删除,并且不在文件系统中显示出来,但是释放的空间并不会被覆盖,直到Apache被停止、文件描述符被关闭。</p>
<h3>CacheEnable fd</h3>
<p><code class="module"><a href="./mod/mod_mem_cache.html">mod_mem_cache</a></code>也提供了一个文件句柄缓冲方案,可以通过<code class="directive"><a href="./mod/mod_cache.html#cacheenable">CacheEnable</a></code>指令来启用。</p>
<div class="example"><pre>CacheEnable fd /</pre></div>
<p>与<code class="module"><a href="./mod/mod_cache.html">mod_cache</a></code>的方案相比,这种方案更加智能:缓存内容失效以后相应的句柄将不再被维护。</p>
</div><div class="top"><a href="#page-header"><img alt="top" src="./images/up.gif" /></a></div>
<div class="section">
<h2><a name="inmemory" id="inmemory">内存缓冲(In-Memory Caching)</a></h2>
<table border="1" cellpadding="0" cellspacing="0" bordercolor="#AAAAAA" class="related">
<tr><th>相关模块</th><th>相关指令</th></tr>
<tr><td><ul><li><code class="module"><a href="./mod/mod_mem_cache.html">mod_mem_cache</a></code></li><li><code class="module"><a href="./mod/mod_file_cache.html">mod_file_cache</a></code></li></ul></td><td><ul><li><code class="directive"><a href="./mod/mod_cache.html#cacheenable">CacheEnable</a></code></li><li><code class="directive"><a href="./mod/mod_cache.html#cachedisable">CacheDisable</a></code></li><li><code class="directive"><a href="./mod/mod_file_cache.html#mmapstatic">MMapStatic</a></code></li></ul></td></tr>
</table>
<p>直接从系统的内存中提供服务通常是取得服务内容最快速的方法。从一个磁盘控制器读取文件,或者更糟糕的是从远程网络读取文件,其速度要慢上几个数量级。磁盘控制器通常涉及到物理动作,访问网络要受限于网络带宽,而访问内存通常仅仅只需要几毫微秒时间。</p>
<p>内存也许是目前单位字节最昂贵的存储器,保证它充分发挥作用非常重要。将文件缓存在内存中将导致系统可用内存的减少。正如我们将要看到的,在操作系统存在内存缓冲区的情况下,这不是一个大问题。但是当使用Apache自己的内存缓冲区的情况下,确保没有为缓冲区分配太多的内存就显得十分重要。否则,操作系统将会使用swap(虚拟内存/交换区),这可能会导致性能急剧下降。</p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -