📄 caching.html
字号:
<h3>操作系统缓冲</h3>
<p>几乎所有现代的操作系统都由内核直接管理文件数据在内存中的缓冲。这是一个强有力的特性,并且在极大程度上操作系统做的非常好。比如在Linux系统上,让我们看看第一次读取一个文件和第二次读取同样的文件所需要的时间:</p>
<div class="example"><pre>
colm@coroebus:~$ time cat testfile > /dev/null
real 0m0.065s
user 0m0.000s
sys 0m0.001s
colm@coroebus:~$ time cat testfile > /dev/null
real 0m0.003s
user 0m0.003s
sys 0m0.000s</pre></div>
<p>即使对于这样的一个小文件,两次读取的时间差异也十分惊人。这是由于内核在内存中缓存了文件的内容。</p>
<p>通过确保在你的系统上始终存在"多余的"内存,你就可以确保会有越来越多的文件内容被缓存在这个缓冲区中。这是一个非常有效的内存缓冲途径,并且根本无需对Apache作出任何额外的配置。</p>
<p>另外,由于操作系统知道文件何时被修改或删除了,它就可以自动的从内存缓冲区中删除失效的文件内容。这是一个优于Apache自身的内存缓冲区的巨大优点,因为Apache无法得知文件被修改或删除的信息。</p>
<p>尽管操作系统自动管理的缓冲区有着性能和洞悉文件状态的优势,但是在某些情况下Apache自己的内存缓冲却更加有效。</p>
<p>首先,操作系统只能缓存它自己知道的文件,如果你将Apache当作一个代理服务器运行,那么Apache可以缓存非本地文件。如果你还想要无可匹敌的内存缓存速度,也必须使用Apache自己的内存缓冲区。</p>
<h3>MMapStatic 缓冲</h3>
<p><code class="module"><a href="./mod/mod_file_cache.html">mod_file_cache</a></code>提供了<code class="directive"><a href="./mod/mod_file_cache.html#mmapstatic">MMapStatic</a></code>指令,它可以指示Apache在启动时将一个静态文件的内容映射到内存中(使用mmap()系统调用)。Apache将会使用内存中缓存的内容来为后来对这个文件的访问提供内容。</p>
<div class="example"><pre>MMapStatic /usr/local/apache2/htdocs/index.html</pre></div>
<p>使用了<code class="directive"><a href="./mod/mod_file_cache.html#cachefile">CacheFile</a></code>指令以后,在Apache运行期间,对这些文件所做的任何修改都不会生效。</p>
<p><code class="directive"><a href="./mod/mod_file_cache.html#mmapstatic">MMapStatic</a></code>指令并不关心它占用了多少内存,所以你必须确保不要过度滥用这个指令。每个Apache子进程都将复制这部分内存,所以非常重要的一点是你必须确保被映射的文件不能占用太多的内存,以至于操作系统不得不使用交换区或虚拟内存。</p>
<h3>mod_mem_cache 缓冲</h3>
<p><code class="module"><a href="./mod/mod_mem_cache.html">mod_mem_cache</a></code>提供了一个智能的HTTP内存缓冲方案。它同时也直接使用堆内存,这也意味着即使<var>MMap</var>不被你的操作系统所支持,<code class="module"><a href="./mod/mod_mem_cache.html">mod_mem_cache</a></code>仍然能够实现缓冲。</p>
<p>这种类型的缓冲可以通过以下方法启用:</p>
<div class="example"><pre>
# 启用内存缓冲
CacheEnable mem /
# 将缓冲区的大小限制为 1 MB
MCacheSize 1024</pre></div>
</div><div class="top"><a href="#page-header"><img alt="top" src="./images/up.gif" /></a></div>
<div class="section">
<h2><a name="disk" id="disk">磁盘缓冲(Disk-based 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_disk_cache.html">mod_disk_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></ul></td></tr>
</table>
<p><code class="module"><a href="./mod/mod_disk_cache.html">mod_disk_cache</a></code>为<code class="module"><a href="./mod/mod_cache.html">mod_cache</a></code>提供了一个基于磁盘的缓冲机制。和<code class="module"><a href="./mod/mod_mem_cache.html">mod_mem_cache</a></code>一样,这是一种智能缓冲,仅在缓存内容没有失效的情况下才从缓冲区中提供服务。</p>
<p>通常,这个模块将按如下方式进行配置:</p>
<div class="example"><pre>
CacheRoot /var/cache/apache/
CacheEnable disk /
CacheDirLevels 2
CacheDirLength 1</pre></div>
<p>请注意,因为缓冲区位于本地磁盘上,所以操作系统的内存缓冲区通常对它们的访问也有效。所以虽然这些文件被存储在本地磁盘上,但若这些文件被频繁的访问,那么很可能操作系统已经将它们保存在内存中了。</p>
<h3>深入理解缓冲存储区(Cache-Store)</h3>
<p>要将项目保存在缓冲区中,<code class="module"><a href="./mod/mod_disk_cache.html">mod_disk_cache</a></code>会为被请求的URL创建一个22字符的哈希值。该哈希值包含了该URL的主机名、协议、端口、路径、CGI变量,以确保多个URL不会发生碰撞。</p>
<p>这22个字符的取值范围是64个不同的字符,这意味着最多可以有22^64种可能的取值。例如,一个URL的哈希值可能是:<code>xyTGxSMO2b68mBCykqkp1w</code> 。这个哈希值将被用作缓存中对应于那个URL的文件名前缀,但是首先,这个哈希值将被按照<code class="directive"><a href="./mod/mod_disk_cache.html#cachedirlevels">CacheDirLevels</a></code>和<code class="directive"><a href="./mod/mod_disk_cache.html#cachedirlength">CacheDirLength</a></code>指令分解成每一级目录名。</p>
<p><code class="directive"><a href="./mod/mod_disk_cache.html#cachedirlevels">CacheDirLevels</a></code>指定了子目录的层数,<code class="directive"><a href="./mod/mod_disk_cache.html#cachedirlength">CacheDirLength</a></code>指定了每级子目录名的字符数。使用上述例子的设置,这个哈希值将被转化成如下文件名前缀:<code>/var/cache/apache/x/y/TGxSMO2b68mBCykqkp1w</code> 。</p>
<p>使用这种技术的总体目标是减少某个特定目录中子目录或文件的个数,因为绝大多的文件系统在子目录或文件数过多的情况下的访问速度都会大打折扣。将<code class="directive"><a href="./mod/mod_disk_cache.html#cachedirlength">CacheDirLength</a></code>设置为"1"将使得任意一层目录下的子目录数都不会超过64,若为设为"2"则为64*64,依此类推。除非你有一个非常好的理由,否则"1"将是<code class="directive"><a href="./mod/mod_disk_cache.html#cachedirlength">CacheDirLength</a></code>指令的推荐值。</p>
<p>如何设置<code class="directive"><a href="./mod/mod_disk_cache.html#cachedirlevels">CacheDirLevels</a></code>指令的值取决于你预计到将会在缓冲区中保存多少个文件。上述示例使用的"2"将会导致大约会有4096个子目录最终被建立,大约100万个文件被缓存,大约平均每个文件夹存储245个URL缓冲文件。</p>
<p>每个URL在缓冲区中至少会使用两个文件。通常,一个是包含了URL元信息(meta-information)的".header"文件,比如何时失效;另一个是".data"文件,包含了按字节复制的用于为URL提供服务的内容。</p>
<p>在通过使用"Vary"头进行内容协商的情况下,将会为该URL创建一个".vary"目录,该目录下将会保存多个适合不同协商内容的".data"文件。</p>
<h3>维护磁盘缓冲区</h3>
<p>虽然<code class="module"><a href="./mod/mod_disk_cache.html">mod_disk_cache</a></code>将会删除缓冲区中失效的文件,但是它并不负责维护整个缓冲区总共究竟应该占据多大空间以及至少要保留多少剩余空间。</p>
<p>作为弥补,Apache附带了一个<a href="programs/htcacheclean.html">htcacheclean</a>工具,正如你从它的名字猜到的,它可以周期性的清理缓冲区。确定<a href="programs/htcacheclean.html">htcacheclean</a>的运行频率以及缓冲区应当占有多大的磁盘空间是一件复杂的事情。必须要经过多次尝试和碰壁才能找到一个最佳值。</p>
<p><a href="programs/htcacheclean.html">htcacheclean</a>有两种运作模型。一种是作为后台守护进程运行,或者由cron周期性的调用。<a href="programs/htcacheclean.html">htcacheclean</a>经常使用一个小时或更多的时间来处理非常巨大的(几十G)缓冲区,所以如果你是使用cron来调用它的话,建议你测试一下多长时间运行一次比较合适,以避免在同一时间运行多个实例。</p>
<p class="figure">
<img src="images/caching_fig1.gif" alt="" width="600" height="406" /><br />
<a id="figure1" name="figure1"><dfn>图1</dfn></a>: 一个典型的缓冲区增长和清理的周期</p>
<p>因为<code class="module"><a href="./mod/mod_disk_cache.html">mod_disk_cache</a></code>模块自身并不关心究竟实际使用了多少磁盘空间,所以你必须确保<a href="programs/htcacheclean.html">htcacheclean</a>被配置为在清理了缓冲区以后预留了足够多的"增长空间"。</p>
</div></div>
<div id="footer">
<p class="apache">本文允许自由使用、分发、转载,但必须保留译者署名;详见:<a href="./translator_announcement.html#announcement">译者声明</a>。</p>
<p class="menu"><a href="./mod/index.html">模块索引</a> | <a href="./mod/directives.html">指令索引</a> | <a href="./faq/index.html">常见问题</a> | <a href="./glossary.html">词汇表</a> | <a href="./sitemap.html">站点导航</a></p></div>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -