<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
   <title>笔记 by 车东</title>
   <link rel="alternate" type="text/html" href="http://www.chedong.com/tech/" />
   <link rel="self" type="application/atom+xml" href="http://www.chedong.com/tech/atom.xml" />
   <id>tag:www.chedong.com,2008:/tech/10</id>
   <updated>2007-11-07T07:49:38Z</updated>
   <subtitle>为而不有……</subtitle>
   <generator uri="http://www.sixapart.com/movabletype/">Movable Type 3.36</generator>

<entry>
   <title>面向站长和网站管理员的Web缓存加速指南[翻译]</title>
   <link rel="alternate" type="text/html" href="http://www.chedong.com/tech/cache_docs.html" />
   <id>tag:www.chedong.com,2007:/tech//10.1377</id>
   
   <published>2007-09-05T16:28:05Z</published>
   <updated>2007-11-07T07:49:38Z</updated>
   
   <summary><![CDATA[原文（英文）地址： http://www.mnot.net/cache_docs/&nbsp; 版权声明：署名-非商业性使用-禁止演绎 2.0这是一篇知识性的文档，主要目的是为了让Web缓存相关概念更容易被开发者理解并应用于实际的应用环境中。为了简要起见，某些实现方面的细节被简化或省略了。如果你更关心细节实现则完全不必耐心看完本文，后面参考文档和更多深入阅读部分可能是你更需要的内容。什么是Web缓存，为什么要使用它？缓存的类型：浏览器缓存；代理服务器缓存；Web缓存无害吗？为什么要鼓励缓存？Web缓存如何工作：如何控制（控制不）缓存：HTML Meta标签 vs. HTTP头信息；Pragma HTTP头信息（为什么不起作用）；使用Expires（过期时间）HTTP头信息控制保鲜期；Cache-Control（缓存控制） HTTP头信息；校验参数和校验；创建利于缓存网站的窍门；编写利于缓存的脚本；常见问题解答； 缓存机制的实现：Web服务器端配置； 缓存机制的实现：服务器端脚本；参考文档和深入阅读；关于本文档；...]]></summary>
   <author>
      <name>车东</name>
      <uri>http://www.chedong.com</uri>
   </author>
   
   
   <content type="html" xml:lang="en" xml:base="http://www.chedong.com/tech/">
      <![CDATA[<p>原文（英文）地址： <a href="http://www.mnot.net/cache_docs/">http://www.mnot.net/cache_docs/</a>&nbsp; 版权声明：<a href="http://creativecommons.org/licenses/by-nc-nd/2.0/deed.zh">署名-非商业性使用-禁止演绎 2.0</a><br /></p><p>这是一篇知识性的文档，主要目的是为了让Web缓存相关概念更容易被开发者理解并应用于实际的应用环境中。为了简要起见，某些实现方面的细节被简化或省略了。如果你更关心细节实现则完全不必耐心看完本文，后面参考文档和更多深入阅读部分可能是你更需要的内容。<br /></p><ol><li>什么是Web缓存，为什么要使用它？</li><li>缓存的类型：</li><ol><li>浏览器缓存；</li><li>代理服务器缓存；</li></ol><li>Web缓存无害吗？为什么要鼓励缓存？</li><li>Web缓存如何工作：</li><li>如何控制（控制不）缓存：</li><ol><li>HTML Meta标签 vs. HTTP头信息；</li><li>Pragma HTTP头信息（为什么不起作用）；</li><li>使用Expires（过期时间）HTTP头信息控制保鲜期；</li><li>Cache-Control（缓存控制） HTTP头信息；<br /></li><li>校验参数和校验；</li></ol><li>创建利于缓存网站的窍门；</li><li>编写利于缓存的脚本；</li><li>常见问题解答；</li><li> 缓存机制的实现：Web服务器端配置；</li><li> 缓存机制的实现：服务器端脚本；</li><li>参考文档和深入阅读；</li><li>关于本文档；</li></ol>]]>
      <![CDATA[<h3>什么是Web缓存，为什么要使用它？</h3> Web缓存位于Web服务器之间（1个或多个，内容源服务器）和客户端之间（1个或多个）：缓存会根据进来的请求保存输出内容的副本，例如html页面， 图片，文件（统称为副本），然后，当下一个请求来到的时候：如果是相同的URL，缓存直接使用副本响应访问请求，而不是向源服务器再次发送请求。<br /> <br /> 使用缓存主要有2大理由：<br /><ul><li><strong>减少相应延迟</strong>：因为请求从缓存服务器（离客户端更近）而不是源服务器被相应，这个过程耗时更少，让web服务器看上去相应更快；</li><li><strong>减少网络带宽消耗</strong>：当副本被重用时会减低客户端的带宽消耗；客户可以节省带宽费用，控制带宽的需求的增长并更易于管理。</li></ul> <h3><span style="font-weight: bold">缓存的类型</span></h3><h4>  浏览器缓存 </h4><p>对于新一代的Web浏览器来说（例如：IE，Firefox）：一般都能在设置对话框中发现关于缓存的设置，通过在你的电脑上僻处一块硬盘空间用于存储你已经看过的网站的副本。浏览器缓存根据非常简单的规则进行工作：在同一个会话过程中（在当前浏览器没有被关闭之前）会检查一次并确定缓存的副本足够新。这个缓存对于用户点击&ldquo;后退&rdquo;或者点击刚访问过的链接特别有用，如果你浏览过程中访问到同一个图片，这些图片可以从浏览器缓存中调出而即时显现。<br /></p><h4> 代理服务器缓存</h4><p>Web代理服务器使用同样的缓存原理，只是规模更大。代理服务器群为成百上千用户服务使用同样的机制；大公司和ISP经常在他们的防火墙上架设代理缓存或者单独的缓存设备；</p><p>由于带路服务器缓存并非客户端或者源服务器的一部分，而是位于原网络之外，请求必须路由到他们才能起作用。一个方法是手工设置你的浏览器：告诉浏览器使用 那个代理，另外一个是通过中间服务器：这个中间服务器处理所有的web请求，并将请求转发到后台网络，而用户不必配置代理，甚至不必知道代理的存在；<br /></p><p> 代理服务器缓存：是一个共享缓存，不只为一个用户服务，经常为大量用户使用，因此在减少相应时间和带宽使用方面很有效：因为同一个副本会被重用多次。<br /> </p><h4>网关缓存</h4><p>也被称为反向代理缓存或间接代理缓存，网关缓存也是一个中间服务器，和内网管理员部署缓存用于节省带宽不同：网关缓存一般是网站管理员自己部署：让他们的网站更容易扩展并获得更好的性能；<br /> 请求有几种方法被路由到网关缓存服务器上：其中典型的是让用一台或多台负载均衡服务器从客户端看上去是源服务器；<br /> <br /> 网络内容发布商&nbsp; (Content delivery networks CDNs)分布网关缓存到整个（或部分）互联网上，并出售缓存服务给需要的网站，<a href="http://www.speedera.com/">Speedera</a>和<a href="http://www.akamai.com/">Akamai</a>就是典型的网络内容发布商(下文简称CDN)。<br /> <br /> 本问主要关注于浏览器和代理缓存，当然，有些信息对于网关缓存也同样有效；<br /></p><h3> Web缓存无害吗？为什么要鼓励缓存？</h3><p> Web缓存在互联网上最容易被误解的技术之一：网站管理员经常怕对网站失去控制，由于代理缓存会&ldquo;隐藏&rdquo;他们的用户，让他们感觉难以监控谁在使用他们的网站。<br /> 不幸的是：就算不考虑Web缓存，互联网上也有很多网站使用非常多的参数以便管理员精确地跟踪用户如何使用他们的网站；如果这类问题也是你关心的，本文将告诉你如何获得精确的统计而不必将网站设计的非常缓存不友好。<br /> 另外一个抱怨是缓存会给用户过期或失效的数据；无论如何：本文可以告诉你怎样配置你的服务器来控制你的内容将被如何缓存。<br /> <br /> CDN是另外一个有趣的方向，和其他代理缓存不同：CDN的网关缓存为希望被缓存的网站服务，没有以上顾虑。即使你使用了CDN，你也要考虑后续的代理服务器缓存和浏览器缓存问题。</p><p>另外一方面：如果良好地规划了你的网站，缓存会有助于网站服务更快，并节省服务器负载和互联网的链接请求。这个改善是显著的：一个难以缓存的网站可能需要几秒去载入页面，而对比有缓存的网站页面几乎是即时显现：用户更喜欢速度快的网站并更经常的访问；</p><p>这样想：很多大型互联网公司为全世界服务器群投入上百万资金，为的就是让用户访问尽可能快，客户端缓存也是这个目的，只不过更靠近用户一端，而且最好的一点是你甚至根本不用为此付费。</p><p>事实上，无论你是否喜欢，代理服务器和浏览器都回启用缓存。如果你没有配置网站正确的缓存，他们会按照缺省或者缓存管理员的策略进行缓存。<br /> <br /></p><h3> 缓存如何工作</h3><p> 所有的缓存都用一套规则来帮助他们决定什么时候使用缓存中的副本提供服务（假设有副本可用的情况下）；一些规则在协议中有定义（HTTP协议1.0和1.1），一些规则由缓存的管理员设置（浏览器的用户或者代理服务器的管理员）；<br /> 一般说来：遵循以下基本的规则（不必担心，你不必知道所有的细节，细节将随后说明）<br /></p><ol><li> 如果响应头信息：告诉缓存器不要保留缓存，缓存器就不会缓存相应内容；</li><li> 如果请求信息是需要认证或者安全加密的，相应内容也不会被缓存；</li><li> 如果在回应中不存在校验器（ETag或者Last-Modified头信息），缓存服务器会认为缺乏直接的更新度信息，内容将会被认为不可缓存。</li><li> 一个缓存的副本如果含有以下信息：内容将会被认为是足够新的</li><ul><li>含有完整的过期时间和寿命控制头信息，并且内容仍在保鲜期内；</li><li>浏览器已经使用过缓存副本，并且在一个会话中已经检查过内容的新鲜度；</li><li>缓存代理服务器近期内已经使用过缓存副本，并且内容的最后更新时间在上次使用期之前；</li><li>够新的副本将直接从缓存中送出，而不会向源服务器发送请求；</li></ul><li> 如果缓存的副本已经太旧了，缓存服务器将向源服务器发出请求校验请求，用于确定是否可以继续使用当前拷贝继续服务；</li></ol> 总之：<strong><em>新鲜度</em></strong>和<strong>校验</strong>是确定内容是否可用的最重要途径：<p>&nbsp;</p><p> 如果副本足够新，从缓存中提取就立刻能用了；<br /> 而经缓存器校验后发现副本的原件没有变化，系统也会避免将副本内容从源服务器整个重新传输一遍。<br /> <br /></p><h3> 如何控制（控制不）缓存</h3><p> 有很多工具可以帮助设计师和网站管理员调整缓存服务器对待网站的方式，这也许需要你亲自下手对服务器的配置进行一些调整，但绝对值得；了解如何使用这些工具请参考后面的实现章节；<br /></p><h4> HTML meta标签和HTTP 头信息</h4><p> HTML的编写者会在文档的&lt;HEAD&gt;区域中加入描述文档的各种属性，这些META标签常常被用于标记文档不可以被缓存或者标记多长时间后过期；<br /> META标签使用很简单：但是效率并不高，因为只有几种浏览器会遵循这个标记（那些真正会&ldquo;读懂&rdquo;HTML的浏览器），没有一种缓存代理服务器能遵循这个 规则（因为它们几乎完全不解析文档中HTML内容）；有事会在Web页面中增加：Pragma: no-cache这个META标记，如果要让页面保持刷新，这个标签其实完全没有必要。<br /> 如果你的网站托管在ISP机房中，并且机房可能不给你权限去控制HTTP的头信息（如：Expires和Cache-Control），大声控诉：这些机制对于你的工作来说是必须的；<br /> 另外一方面： HTTP头信息可以让你对浏览器和代理服务器如何处理你的副本进行更多的控制。他们在HTML代码中是看不见的，一般由Web服务器自动生成。但是，根据 你使用的服务，你可以在某种程度上进行控制。在下文中：你将看到一些有趣的HTTP头信息，和如何在你的站点上应用部署这些特性。<br /> <br /> HTTP头信息发送在HTML代码之前，只有被浏览器和一些中间缓存能看到，一个典型的HTTP 1.1协议返回的头信息看上去像这样：<br /></p><div style="margin-left: 40px"><span style="font-style: italic"> HTTP/1.1 200 OK</span><br /><span style="font-style: italic"> Date: Fri, 30 Oct 1998 13:19:41 GMT</span><br /><span style="font-style: italic"> Server: Apache/1.3.3 (Unix)</span><br /><span style="font-style: italic"> Cache-Control: max-age=3600, must-revalidate</span><br /><span style="font-style: italic"> Expires: Fri, 30 Oct 1998 14:19:41 GMT</span><br /><span style="font-style: italic"> Last-Modified: Mon, 29 Jun 1998 02:28:12 GMT</span><br /><span style="font-style: italic"> ETag: &quot;3e86-410-3596fbbc&quot;</span><br /><span style="font-style: italic"> Content-Length: 1040</span><br /><span style="font-style: italic"> Content-Type: text/html</span><br /></div><p> <br /> 在头信息空一行后是HTML代码的输出，关于如何设置HTTP头信息请参考实现章节；<br /></p><h4> Pragma HTTP头信息 (为什么它不起作用)</h4><p> 很多人认为在HTTP头信息中设置了Pragma: no-cache后会让内容无法被缓存。但事实并非如此：HTTP的规范中，响应型头信息没有任何关于Pragma属性的说明，而讨论了的是请求型头信息 Pragma属性（头信息也由浏览器发送给服务器），虽然少数集中缓存服务器会遵循这个头信息，但大部分不会。用了Pragma也不起什么作用，要用就使 用下列头信息：<br /></p><h4> 使用Expires（过期时间）HTTP头信息来控制保鲜期</h4><p> Expires（过期时间） 属性是HTTP控制缓存的基本手段，这个属性告诉缓存器：相关副本在多长时间内是新鲜的。过了这个时间，缓存器就会向源服务器发送请求，检查文档是否被修改。几乎所有的缓存服务器都支持Expires（过期时间）属性；<br /> <br /> 大部分Web服务器支持你用几种方式设置Expires属性；一般的：可以设计一个绝对时间间隔：基于客户最后查看副本的时间（最后访问时间）或者根据服务器上文档最后被修改的时间；</p><p>Expires头信息：对于设置静态图片文件（例如导航栏和图片按钮）可缓存特别有用；因为这些图片修改很少，你可以给它们设置一个特别长的过期时间，这会使你的网站对用户变得相应非常快；他们对于控制有规律改变的网页也很有用，例如：你每天早上6点更新新闻页，你可以设置副本的过期时间也是这个时间，这样缓存 服务器就知道什么时候去取一个更新版本，而不必让用户去按浏览器的&ldquo;刷新&rdquo;按钮。</p><p>过期时间头信息属性值<strong>只能</strong>是HTTP格式的日期时间，其他的都会被解析成当前时间&ldquo;之前&rdquo;，副本会过期，记住：HTTP的日期时间必须是格林威治时间（GMT），而不是本地时间。举例：<br /></p><div style="margin-left: 40px"> <span style="font-style: italic">Expires: Fri, 30 Oct 1998 14:19:41 GMT</span><br /></div><p> 所以使用过期时间属性一定要确认你的Web服务器时间设置正确，一个途径是通过网络时间同步协议（Network Time Protocol NTP），和你的系统管理员那里你可以了解更多细节。<br /> 虽然过期时间属性非常有用，但是它还是有些局限，首先：是牵扯到了日期，这样Web服务器的时间和缓存服务器的时间必须是同步的，如果有些不同步，要么是应该缓存的内容提前过期了，要么是过期结果没及时更新。<br /> 还有一个过期时间设置的问题也不容忽视：如果你设置的过期时间是一个固定的时间，如果你返回内容的时候又没有连带更新下次过期的时间，那么之后所有访问请求都会被发送给源Web服务器，反而增加了负载和响应时间；<br /></p><h4> Cache-Control（缓存控制） HTTP头信息</h4><p> HTTP 1.1介绍了另外一组头信息属性：Cache-Control响应头信息，让网站的发布者可以更全面的控制他们的内容，并定位过期时间的限制。<br /> 有用的 Cache-Control响应头信息包括：<br /></p><ul><li><strong>max-age</strong>=[秒] &mdash; 执行缓存被认为是最新的最长时间。类似于过期时间，这个参数是基于请求时间的相对时间间隔，而不是绝对过期时间，[秒]是一个数字，单位是秒：从请求时间开始到过期时间之间的秒数。</li><li><strong>s-maxage</strong>=[秒] &mdash; 类似于max-age属性，除了他应用于共享（如：代理服务器）缓存 </li><li><strong>public </strong>&mdash; 标记认证内容也可以被缓存，一般来说： 经过HTTP认证才能访问的内容，输出是自动不可以缓存的；</li><li><strong>no-cache</strong> &mdash; 强制每次请求直接发送给源服务器，而不经过本地缓存版本的校验。这对于需要确认认证应用很有用（可以和public结合使用），或者严格要求使用最新数据的应用（不惜牺牲使用缓存的所有好处）；</li><li><strong>no-store</strong> &mdash; 强制缓存在任何情况下都不要保留任何副本</li><li><strong>must-revalidate</strong> &mdash; 告诉缓存必须遵循所有你给予副本的新鲜度的，HTTP允许缓存在某些特定情况下返回过期数据，指定了这个属性，你高速缓存，你希望严格的遵循你的规则。</li><li><strong>proxy-revalidate</strong> &mdash; 和 must-revalidate类似，除了他只对缓存代理服务器起作用</li></ul><p> 举例:<br /></p><div style="margin-left: 40px; font-style: italic"> Cache-Control: max-age=3600, must-revalidate<br /></div><p> 如果你计划试用Cache-Control属性，你应该看一下这篇HTTP文档，详见参考和深入阅读；<br /> <br /></p><h4> 校验参数和校验</h4><p> 在Web缓存如何工作： 我们说过：校验是当副本已经修改后，服务器和缓存之间的通讯机制；使用这个机制：缓存服务器可以避免副本实际上仍然足够新的情况下重复下载整个原件。<br /> 校验参数非常重要，如果1个不存在，并且没有任何信息说明保鲜期（Expires或Cache-Control）的情况下，缓存将不会存储任何副本；<br /> 最常见的校验参数是文档的最后修改时间，通过最后Last-Modified头信息可以，当一份缓存包含Last-Modified信息，他基于此信息，通过添加一个If-Modified-Since请求参数，向服务器查询：这个副本从上次查看后是否被修改了。<br /> HTTP 1.1介绍了另外一个校验参数： ETag，服务器是服务器生成的唯一标识符ETag，每次副本的标签都会变化。由于服务器控制了ETag如何生成，缓存服务器可以通过If-None-Match请求的返回没变则当前副本和原件完全一致。<br /> 所有的缓存服务器都使用Last-Modified时间来确定副本是否够新，而ETag校验正变得越来越流行；<br /> 所有新一代的Web服务器都对静态内容（如：文件）自动生成ETag和Last-Modified头信息，而你不必做任何设置。但是，服务器对于动态内容（例如：CGI,ASP或数据库生成的网站）并不知道如何生成这些信息，参考一下编写利于缓存的脚本章节；<br /> <br /></p><h3> 创建利于缓存网站的窍门</h3><p> 除了使用新鲜度信息和校验，你还有很多方法使你的网站缓存友好。<br /></p><ul><li><strong>保持URL稳定</strong>： 这是缓存的金科玉律，如果你给在不同的页面上，给不同用户或者从不同的站点上提供相同的内容，应该使用相同的URL，这是使你的网站缓存友好最简单，也是 最高效的方法。例如：如果你在页面上使用 &quot;/index.html&quot; 做为引用，那么就一直用这个地址；</li><li><strong>使用一个共用的库</strong>存放每页都引用的图片和其他页面元素；</li><li><strong>对于不经常改变的图片/页面启用缓存</strong>，并使用Cache-Control: max-age属性设置一个较长的过期时间；</li><li><strong>对于定期更新的内容</strong>设置一个缓存服务器可识别的max-age属性或过期时间；</li><li><strong>如果数据源（特别是下载文件）变更，修改名称</strong>，这样：你可以让其很长时间不过期，并且保证服务的是正确的版本；而链接到下载文件的页面是一个需要设置较短过期时间的页面。</li><li><strong>万不得已不要改变文件</strong>，否则你会提供一个非常新的Last-Modified日期；例如：当你更新了网站，不要复制整个网站的所有文件，只上传你修改的文件。</li><li><strong>只在必要的时候使用Cookie</strong>，cookie是非常难被缓存的，而且在大多数情况下是不必要的，如果使用cookie，控制在动态网页上；</li><li><strong>减少试用SSL</strong>，加密的页面不会被任何共享缓存服务器缓存，只在必要的时候使用，并且在SSL页面上减少图片的使用；</li><li><strong>使用可缓存性评估引擎</strong>，这对于你实践本文的很多概念都很有帮助；</li></ul><h3> 编写利于缓存的脚本</h3><p> 脚本缺省不会返回校验参数（返回Last-Modified或ETag头信息）或其他新鲜度信息（Expires或Cache-Control），有些动态脚本的确是动态内容（每次相应内容都不一样），但是更多（搜索引擎，数据库引擎网站）网站还是能从缓存友好中获益的。<br /> 一般说来，如果脚本生成的输出在未来一段时间（几分钟或者几天）都是可重复复制的，那么就是可缓存的。如果脚本输出内容只随URL变化而变化，也是可缓存的；但如果输出会根据cookie，认证信息或者其他外部条件变化，则还是不可缓存的。<br /> </p><ul><li>最利于缓存的脚本就是将内容改变时导出成静态文件，Web服务器可以将其当作另外一个网页并生成和试用校验参数，让一些都变得更简单，只需要写入文件即可，这样最后修改时间也有了；</li><li>另外一个让脚本可缓存的方法是对一段时间内能保持较新的内容设置一个相对寿命的头信息，虽然通过Expires头信息也可以实现，但更容易的是用Cache-Control: max-age属性，它会让首次请求后一段时间内缓存保持新鲜；</li><li>如果以上做法你都做不到，你可以让脚本生成一个校验属性，并对 If-Modified-Since 和/或If-None-Match请求作出反应，这些属性可以从解析HTTP头信息得到，并对符合条件的内容返回304 Not Modified（内容未改变），可惜的是，这种做法比不上前2种高效；</li></ul><p>其他窍门： </p><ul><li>尽量避免使用POST，除非万不得已，POST模式的返回内容不会被大部分缓存服务器保存，如果你发送内容通过URL和查询（通过GET模式）的内容可以缓存下来供以后使用；</li><li>不要在URL中加入针对每个用户的识别信息：除非内容是针对每个用户不同的；</li><li>不要统计一个用户来自一个地址的所有请求，因为缓存常常是一起工作的；</li><li>生成并返回Content-Length头信息，如果方便的话，这个属性让你的脚本在可持续链接模式时：客户端可以通过一个TCP/IP链接同时请求多个副本，而不是为每次请求单独建立链接，这样你的网站相应会快很多；</li></ul>具体定义请参考实现章节。<h3> 常见问题解答</h3><h4> 让网站变得可缓存的要点是什么？</h4><p> 好的策略是确定那些内容最热门，大量的复制（特别是图片）并针对这些内容先部署缓存。<br /> </p><h4>如何让页面通过缓存达到最快相应？</h4><p> 缓存最好的副本是那些可以长时间保持新鲜的内容；基于校验虽然有助于加快相应，但是它不得不和源服务器联系一次去检查内容是否够新，如果缓存服务器上就知道内容是新的，内容就可以直接相应返回了。<br /></p><h4> 我理解缓存是好的，但是我不得不统计多少人访问了我的网站！</h4><p> 如果你必须知道每次页面访问的，选择【一】个页面上的小元素，或者页面本身，通过适当的头信息让其不可缓存，例如： 可以在每个页面上部署一个1x1像素的透明图片。Referer头信息会有包含这个图片的每个页面信息；<br /> 明确一点：这个并不会给你一个关于你用户精确度很高的统计，而且这对互联网和你的用户这都不太好，消耗了额外的带宽，强迫用户去访问无法缓存的内容。了解更多信息，参考访问统计资料。<br /> </p><h4>我如何能看到HTTP头信息的内容？</h4><p> 很多浏览器在页面属性或类似界面中可以让你看到Expires 和Last-Modified信息；如果有的话：你会找到页面信息的菜单和页面相关的文件（如图片），并且包含他们的详细信息；<br /> 看到完整的头信息，你可以用telnet手工连接到Web服务器；<br /> 为此：你可能需要用一个字段指定端口（缺省是80），或者链接到www.example.com:80 或者 www.example.com 80(注意是空格)，更多设置请参考一下telnet客户端的文档；<br /> 打开网站链接：请求一个查看链接，如果你想看到http://www.example.com/foo.html 连接到www.example.com的80端口后，键入：<br /></p><div style="margin-left: 40px"><span style="font-style: italic"> GET /foo.html HTTP/1.1 [回车]</span><br /><span style="font-style: italic"> GET /foo.html HTTP/1.1 [return]</span><br /><span style="font-style: italic"> Host: www.example.com [回车][回车] </span><br /><span style="font-style: italic"> Host: www.example.com [return][return]</span><br /></div><p> 在[回车]处按键盘的回车键；在最后，要按2次回车，然后，就会输出头信息及完整页面，如果只想看头信息，将GET换成HEAD。<br /> <br /></p><h4> 我的页面是密码保护的，代理缓存服务器如何处理他们？</h4><p> 缺省的，网页被HTTP认证保护的都是私密内容，它们不会被任何共享缓存保留。但是，你可以通过设置Cache-Control: public让认证页面可缓存，HTTP 1.1标准兼容的缓存服务器会认出它们可缓存。<br /> 如果你认为这些可缓存的页面，但是需要每个用户认证后才能看，可以组合使用Cache-Control: public和no-cache头信息，高速缓存必须在提供副本之前，将将新客户的认证信息提交给源服务器。设置就是这样：<br /></p><blockquote><em> Cache-Control: public, no-cache</em><br /></blockquote><p> 无论如何：这是减少认证请求的最好方法，例如： 你的图片是不机密的，将它们部署在另外一个目录，并对此配置服务器不强制认证。这样，那些图片会缺省都缓存。<br /></p><h4> 我们是否要担心用户通过cache访问我的站点？</h4><p> 代理服务器上SSL页面不会被缓存（不推荐被缓存），所以你不必为此担心。但是，由于缓存保存了非SSL请求和从他们抓取的URL，你要意识到没有安全保护的网站，可能被不道德的管理员可能搜集用户隐私，特别是通过URL。<br /> 实际上，位于服务器和客户端之间的管理员可以搜集这类信息。特别是通过CGI脚本在通过URL传递用户名和密码的时候会有很大问题；这对泄露用户名和密码是一个很大的漏洞；<br /> 如果你初步懂得互联网的安全机制，你不会对缓存服务器有任何。<br /></p><h4> 我在寻找一个包含在Web发布系统解决方案，那些是比较有缓存意识的系统？</h4><p> 这很难说，一般说来系统越复杂越难缓存。最差就是全动态发布并不提供校验参数；你无发缓存任何内容。可以向系统提供商的技术人员了解一下，并参考后面的实现说明。<br /></p><h4> 我的图片设置了1个月后过期，但是我现在需要现在更新。</h4><p> 过期时间是绕不过去的，除非缓存（浏览器或者代理服务器）空间不足才会删除副本，缓存副本在过期之间会被一直使用。<br /> 最好的办法是改变它们的链接，这样，新的副本将会从源服务器上重新下载。记住：引用它们的页面本身也会被缓存。因此，使用静态图片和类似内容是很容易缓存的，而引用他们的HTML页面则要保持非常更新；<br /> 如果你希望对指定的缓存服务器重新载入一个副本，你可以强制使用&ldquo;刷新&rdquo;（在FireFox中在reload的时候按住shift键：就会有前面提到恶Pragma: no-cache头信息发出）。或者你可以让缓存的管理员从他们的界面中删除相应内容；<br /> </p><h4>我运行一个Web托管服务，如何让我的用户发布缓存友好的网页？</h4><p> 如果你使用apahe，可以考虑允许他们使用.htaccess文件并提供相应的文档；<br /> 另外一方面： 你也可以考虑在各种虚拟主机上建立各种缓存策略。例如： 你可以设置一个目录 /cache-1m 专门用于存放访问1个月的访问，另外一个 /no-cache目录则被用提供不可存储副本的服务。<br /> 无论如何：对于大量用户访问还是应该用缓存。对于大网站，这方面的节约很明显（带宽和服务器负载）；<br /></p><h4> 我标记了一些网页是可缓存的，但是浏览器仍然每次发送请求给服务。如何强制他们保存副本？</h4><p> 缓存服务器并不会总保存副本并重用副本；他们只是在特定情况下会不保存并使用副本。所有的缓存服务器都回基于文件的大小，类型（例如：图片 页面），或者服务器空间的剩余来确定如何缓存。你的页面相比更热门或者更大的文件相比，并不值得缓存。<br /> 所以有些缓存服务器允许管理员根据文件类型确定缓存副本的优先级，允许某些副本被永久缓存并长期有效；<br /></p><h3> 缓存机制的实现 - Web服务器端配置</h3><p>一般说来，应该选择最新版本的Web服务器程序来部署。不仅因为它们包含更多利于缓存的功能，新版本往往在性能和安全性方面都有很多的改善。<br /></p><h4>Apache HTTP服务器</h4><p>Apache有些可选的模块来包含这些头信息： 包括Expires和Cache-Control。 这些模块在1.2版本以上都支持；<br />这些模块需要和apache一起编译；虽然他们已经包含在发布版本中，但缺省并没有启用。为了确定相应模块已经被启用：找到httpd程序并运行httpd -l 它会列出可用的模块，我们需要用的模块是mod_expires和mod_headers<br /></p><ul><li>如果这些模块不可用，你需要联系管理员，重新编译并包含这些模块。这些模块有时候通过配置文件中把注释掉的配置启用，或者在编译的时候增加-enable -module=expires和-enable-module=headers选项（在apache 1.3和以上版本）。 参考Apache发布版中的INSTALL文件；</li></ul><p>Apache一旦启用了相应的模块，你就可以在.htaccess文件或者在服务器的access.conf文件中通过mod_expires设置副本什 么时候过期。你可设置过期从访问时间或文件修改时间开始计算，并且应用到某种文件类型上或缺省设置，参考<a href="http://httpd.apache.org/docs/1.3/mod/mod_expires.html">模块的文档</a>获得更多信息，或者遇到问题的时候向你身边的apache专家讨教。<br /> 应用Cache-Control头信息，你需要使用mod_headers,它将允许你设置任意的HTTP头信息，参考<a href="http://httpd.apache.org/docs/1.3/mod/mod_headers.html">mod_headers的文档</a>可以获得更多资料；<br /> 这里有个例子说明如何使用头信息：<br /></p><ul><li>.htaccess文件允许web发布者使用命令只在配置文件中用到的命令。他影响到所在目录及其子目录；问一下你的服务器管理员确认这个功能是否启用了。 <br /></li></ul><div style="margin-left: 40px"><span style="font-style: italic"> ### 启用 mod_expires</span><br /><span style="font-style: italic"> ExpiresActive On</span><br /><span style="font-style: italic"> ### 设置 .gif 在被访问过后1个月过期。</span><br /><span style="font-style: italic"> ExpiresByType image/gif A2592000</span><br /><span style="font-style: italic"> ### 其他文件设置为最后修改时间1天后过期</span><br /><span style="font-style: italic"> ### (用了另外的语法)</span><br /><span style="font-style: italic"> ExpiresDefault &quot;modification plus 1 day&quot;</span><br /><span style="font-style: italic"> ### 在index.html文件应用 Cache-Control头属性</span><br /><span style="font-style: italic"> &lt;Files index.html&gt;</span><br /><span style="font-style: italic"> Header append Cache-Control &quot;public, must-revalidate&quot;</span><br /><span style="font-style: italic"> &lt;/Files&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br /></div><ul><li>注意： 在适当情况下mod_expires会自动计算并插入Cache-Control:max-age 头信息</li></ul><p> Apache 2.0的配置和1.3类似，更多信息可以参考2.0的<a href="http://httpd.apache.org/docs/2.2/mod/mod_expires.html">mod_expires</a>和<a href="http://httpd.apache.org/docs/2.2/mod/mod_headers.html">mod_headers文档</a>；<br /> <br /></p><h4> Microsoft IIS服务器</h4><p> Microsoft的IIS可以非常容易的设置头信息，注意：这只针对IIS 4.0服务器，并且只能在NT服务器上运行。<br /> 为网站的一个区域设置头信息，先要到管理员工具界面中，然后设置属性。选择HTTP Header选单，你会看到2个有趣的区域：启用内容过期和定制HTTP头信息。头一个设置会自动配置，第二个可以用于设置Cache-Control头信息；<br /> 设置asp页面的头信息可以参考后面的ASP章节，也可以通过ISAPI模块设置头信息，细节请参考MSDN。<br /> <br /></p><h4> Netscape/iPlanet企业服务器</h4><p> 3.6版本以后，Netscape/iPlanet已经不能设置Expires头信息了，他从3.0版本开始支持HTTP 1.1的功能。这意味着HTTP 1.1的缓存（代理服务器/浏览器）优势都可以通过你对Cache-Control设置来获得。<br /> 使用Cache-Control头信息，在管理服务器上选择内容管理|缓存设置目录。然后：使用资源选择器，选择你希望设置头信息的目录。设置完头信息后，点击&ldquo;OK&rdquo;。更多信息请参考<a href="http://developer.netscape.com/docs/manuals/enterprise/admnunix/content.htm#1006282">Netscape/iPlanet企业服务器的手册</a>。<br /> <br /></p><h4> 缓存机制的实现：服务器端脚本</h4><p> 需要注意的一点是：也许服务器设置HTTP头信息比脚本语言更容易，但是两者你都应该使用。<br /> 因为服务器端的脚本主要是为了动态内容，他本身不产生可缓存的文件页面，即使内容实际是可以缓存的。如果你的内容经常改变，但是不是每次页面请求都改变， 考虑设置一个Cache-Control: max-age头信息；大部分用户会在短时间内多次访问同一页面。例如： 用户点击&ldquo;后退&rdquo;按钮，即使没有新内容，他们仍然要再次从服务器下载内容查看。<br /> <br /></p><h4> CGI程序</h4><p> CGI脚本是生成内容最流行的方式之一，你可以很容易在发送内容之前的扩展HTTP头信息；大部分CGI实现都需要你写 Content-Type头信息，例如这个Perl脚本：<br /></p><div style="margin-left: 40px"><span style="font-style: italic"> #!/usr/bin/perl</span><br /><span style="font-style: italic"> print &quot;Content-type: text/html\n&quot;;</span><br /><span style="font-style: italic"> print &quot;Expires: Thu, 29 Oct 1998 17:04:19 GMT\n&quot;;</span><br /><span style="font-style: italic"> print &quot;\n&quot;;</span><br /><span style="font-style: italic"> ### 后面是内容体...</span><br /></div><p> 由于都是文本，你可以很容易通过内置函数生成Expires和其他日期相关的头信息。如果你使用Cache-Control: max-age;会更简单；<br /></p><div style="margin-left: 40px"><span style="font-style: italic"> print &quot;Cache-Control: max-age=600\n&quot;;</span><br /></div><p> 这样脚本可以在被请求后缓存10分钟；这样用户如果按&ldquo;后退&rdquo;按钮，他们不会重新提交请求；<br /> CGI的规范同时也允许客户端发送头信息，每个头信息都有一个&lsquo;HTTP_&rsquo;的前缀；这样如果一个客户端发送一个If-Modified-Since请求，就是这样的：<br /></p><div style="margin-left: 40px; font-style: italic"> HTTP_IF_MODIFIED_SINCE = Fri, 30 Oct 1998 14:19:41 GMT <br /></div><p> <br /> 参考一下<a href="http://www.mnot.net/cgi_buffer/">cgi_buffer</a>库，一个自动处理ETag的生成和校验的库，生成Content-Length属性和对内容进行gzip压缩。在Python脚本中也只需加入一行；<br /> <br /></p><h4> 服务器端包含 Server Side Includes</h4><p> SSI（经常使用.shtml扩展名）是网站发布者最早可以生成动态内容的方案。通过在页面中设置特别的标记，也成为一种嵌入HTML的脚本；<br />大部分SSI的实现无法设置校验器，于是无法缓存。但是Apache可以通过对特定文件的组执行权限设置实现允许用户设置那种SSI可以被缓存；结合XbitHack调整整个目录。更多文档请参考<a href="http://httpd.apache.org/docs/1.3/mod/mod_include.html">mod_include文档</a>。<br /></p><h4> PHP</h4><p> PHP是一个内建在web服务器中的服务器端脚本语言，当做为HTML嵌入式脚本，很像SSI，但是有更多的选项，PHP可以在各种Web服务器上设置为CGI模式运行，或者做为Apache的模块；<br /> 缺省PHP生成副本没有设置校验器，于是也无法缓存，但是开发者可以通过Header()函数来生成HTTP的头信息；<br /> 例如：以下代码会生成一个Cache-Control头信息，并设置为3天以后过期的Expires头信息；<br /></p><div style="margin-left: 40px"><span style="font-style: italic"> &lt;?php</span><br /><span style="font-style: italic"> &nbsp;Header(&quot;Cache-Control: must-revalidate&quot;);</span><br /><br /><span style="font-style: italic"> &nbsp;$offset = 60 * 60 * 24 * 3;</span><br /><span style="font-style: italic"> &nbsp;$ExpStr = &quot;Expires: &quot; . gmdate(&quot;D, d M Y H:i:s&quot;, time() + $offset) . &quot; GMT&quot;;</span><br /><span style="font-style: italic"> &nbsp;Header($ExpStr);</span><br /><span style="font-style: italic"> ?&gt;</span><br /></div><p>  记住： Header()的输出必须先于所有其他HTML的输出；<br /> 正如你看到的：你可以手工创建HTTP日期；PHP没有为你提供专门的函数（新版本已经让这个越来越容易了，请参考PHP的<a href="http://php.net/date">日期相关函数文档</a>），当然，最简单的还是设置Cache-Control: max-age头信息，而且对于大部分情况都比较适用；<br /> 更多信息，请参考<a href="http://www.php.net/manual/function.header.php3">header相关的文档</a>；<br /> 也请参考一下<a href="http://www.mnot.net/cgi_buffer/">cgi_buffer</a>库，自动处理ETag的生成和校验，Content-Length生成和内容的gzip压缩，PHP脚本只需包含1行代码；<br /></p><h4> Cold Fusion</h4><p><a href="http://www.adobe.com/products/coldfusion/"> Cold Fusion</a>是Macromedia的商业服务器端脚本引擎，并且支持多种Windows平台，Linux平台和多种Unix平台。Cold Fusion通过CFHEADER标记设置HTTP头信息相对容易。可惜的是：以下的Expires头信息的设置有些容易误导；<br /></p><div style="margin-left: 40px"><span style="font-style: italic">&lt;CFHEADER NAME=&quot;Expires&quot; VALUE=&quot;#Now()#&quot;&gt;</span><br /></div><p> 它并不像你想像的那样工作，因为时间（本例中为请求发起的时间）并不会被转换成一个符合HTTP时间，而且打印出副本的Cold fusion的日期/时间对象，大部分客户端会忽略或者将其转换成1970年1月1日。<br /> 但是：Cold Fusion另外提供了一套日期格式化函数， GetHttpTimeSTring. 结合DateAdd函数，就很容易设置过期时间了，这里我们设置一个Header声明副本在1个月以后过期；<br /></p><div style="margin-left: 40px"><span style="font-style: italic"> &lt;cfheader name=&quot;Expires&quot; value=&quot;#GetHttpTimeString(DateAdd('m', 1, Now()))#&quot;&gt;</span><br /></div><p> 你也可以使用CFHEADER标签来设置Cache-Control: max-age等其他头信息；<br /> 记住：Web服务器也会将头信息设置转给Cold Fusion(做为CGI运行的时候)，检查你的服务器设置并确定你是否可以利用服务器设置代替Cold Fusion。 <br /> <br /></p><h4> ASP和ASP.NET</h4><p> 在asp中设置HTTP头信息是：确认Response方法先于HTML内容输出前被调用，或者使用 Response.Buffer暂存输出；同样的：注意某些版本的IIS缺省设置会输出Cache-Control: private 头信息，必须声明成public才能被共享缓存服务器缓存。<br /> IIS的ASP和其他web服务器都允许你设置HTTP头信息，例如： 设置过期时间，你可以设置Response对象的属性；<br /></p><div style="margin-left: 40px"><span style="font-style: italic"> &lt;% Response.Expires=1440 %&gt;</span><br /></div><p> 设置请求的副本在输出的指定分钟后过期，类似的：也可以设置绝对的过期时间（确认你的HTTP日期格式正确）<br /></p><div style="margin-left: 40px"><span style="font-style: italic"> &lt;% Response.ExpiresAbsolute=#May 31,1996 13:30:15 GMT# %&gt;</span><br /></div><p> Cache-Control头信息可以这样设置：<br /></p><div style="margin-left: 40px; font-style: italic">&lt;% Response.CacheControl=&quot;public&quot; %&gt;<br /></div><p> 在ASP.NET中，Response.Expires 已经不推荐使用了，正确的方法是通过Response.Cache设置Cache相关的头信息；<br /></p><div style="margin-left: 40px"><span style="font-style: italic"> Response.Cache.SetExpires ( DateTime.Now.AddMinutes ( 60 ) ) ;</span><br /><span style="font-style: italic"> Response.Cache.SetCacheability ( HttpCacheability.Public ) ;</span><br /></div><p> 参考<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconaspoutputcache.asp">MSDN文档</a>可以找到更多相关新年系；<br /> <br /></p><h3> 参考文档和深入阅读</h3><h4><a target="_blank" href="http://www.ietf.org/rfc/rfc2616.txt"> HTTP 1.1 规范定义</a></h4><p> HTTP 1.1的规范有大量的扩展用于页面缓存，以及权威的接口实现指南，参考章节：13, 14.9, 14.21, 以及 14.25.<br /> <br /> </p><h4><a target="_blank" href="http://www.web-caching.com/">Web-Caching.com</a></h4><p> 非常精彩的介绍缓存相关概念，并介绍其他在线资源。<br /> <a target="_blank" href="http://www.goldmark.org/netrants/webstats/"><br /></a></p><h4><a target="_blank" href="http://www.goldmark.org/netrants/webstats/"> 关于非连续性访问统计</a></h4><p> Jeff Goldberg内容丰富的演说告诉你为什么不应该过度依赖访问统计和计数器；<br /> <br /> </p><h4><a href="http://www.mnot.net/cacheability/">可缓存性检测引擎</a></h4><p>可缓存的引擎设计，检测网页并确定其如何与Web缓存服务器交互， 这个引擎配合这篇指南是一个很好的调试工具，<br /> <br /> </p><h4><a href="http://www.mnot.net/cgi_buffer/">cgi_buffer库</a></h4><p> 包含库：用于CGI模式运行的Perl/Python/PHP脚本，自动处理ETag生成/校验，Content-Length生成和内容压缩。正确地。 Python版本也被用作其他大量的CGI脚本。<br /> <br /></p><h3> 关于本文档</h3><p> 本文版权属于Mark Nottingham &lt;<a href="mailto:mnot@pobox.com">mnot@pobox.com</a>&gt;，本作品遵循<a href="http://creativecommons.org/licenses/by-nc-nd/2.0/deed.zh">创作共用版权</a>。<br /> 如果你镜像本文，请通过以上邮件告知，这样你可以在更新时被通知；<br /> 所有的商标属于其所有人。<br /> 虽然作者确信内容在发布时的正确性，但不保证其应用或引申应用的正确性，如有误传，错误或其他需要澄清的问题请尽快告知作者；<br /> 本文最新版本可以从 <a href="http://www.mnot.net/cache_docs/">http://www.mnot.net/cache_docs/</a> 获得；<br /> 翻译版本包括： <a href="http://www.jakpsatweb.cz/clanky/caching-tutorial-czech-translation.html">捷克语版</a>，<a href="http://www.mnot.net/cache_docs/index.fr.html">法语版</a>和<a href="http://www.chedong.com/tech/cache_docs.html">中文版</a>。<br /> 版本： 1.81 - 2007年3月16日<br /><a href="http://creativecommons.org/licenses/by-nc-nd/2.0/deed.zh"> 创作共用版权声明</a><br />翻译： <a href="http://www.chedong.com/tech/">车东</a> 2007年9月6日 </p>]]>
   </content>
</entry>
<entry>
   <title>mod_gzip：Apache的HTTP压缩优化</title>
   <link rel="alternate" type="text/html" href="http://www.chedong.com/tech/compress.html" />
   <id>tag:www.chedong.com,2007:/test//10.1279</id>
   
   <published>2003-09-10T10:15:12Z</published>
   <updated>2007-04-12T03:42:31Z</updated>
   
   <summary>HTTP压缩对于纯文本内容可压缩至原大小的40％一下，从而提供60％以上的数据传输节约，虽然WEB服务器会因为压缩导致CPU占用的略微上升，但是可以节约大量用于传输的网络IO。对于数据压缩带来的用户浏览速度提升（让页面符合8秒定律），这点总体负载5%-10%上升是非常值得的。毕竟通过数据压缩会比通过不规范的HTML代码优化要方便得多。...</summary>
   <author>
      <name>车东</name>
      <uri>http://www.chedong.com</uri>
   </author>
   
   
   <content type="html" xml:lang="en" xml:base="http://www.chedong.com/tech/">
      HTTP压缩对于纯文本内容可压缩至原大小的40％一下，从而提供60％以上的数据传输节约，虽然WEB服务器会因为压缩导致CPU占用的略微上升，但是可以节约大量用于传输的网络IO。对于数据压缩带来的用户浏览速度提升（让页面符合8秒定律），这点总体负载5%-10%上升是非常值得的。毕竟通过数据压缩会比通过不规范的HTML代码优化要方便得多。
      <![CDATA[<p>mod_gzip的安装：</p>

<p>修改Makefile中的 apxs路径：然后make make install</p>
<p>配置：mod_gzip+mod_php<br>
LoadModule gzip_module modules/mod_gzip.so</p>
<p>...<br>
AddModule mod_gzip.c</p>
<p>...<br>
<i>&lt;IfModule mod_gzip.c&gt;<br>
mod_gzip_on Yes<br>
mod_gzip_minimum_file_size 1000<br>

mod_gzip_maximum_file_size 300000 <br>
mod_gzip_item_include file \.htm$<br>
mod_gzip_item_include file \.html$<br>
mod_gzip_item_include file \.php$<br>
mod_gzip_item_include file \.php3$<br>
mod_gzip_item_include mime text/.*<br>
mod_gzip_item_include mime httpd/unix-directory <br>
# mod_gzip的临时工作目录: mkdir /tmp/mod_gzip; chmod -R 777 mod_gzip<br>
mod_gzip_temp_dir /tmp/mod_gzip<br>

mod_gzip_dechunk Yes<br>
mod_gzip_keep_workfiles No<br>
&lt;/IfModule&gt;</i></p>
<p><i> </i>
mod_gzip和mod_php的配合：不要让mod_gzip和mod_php使用同一个临时目录，php_session存放目录可以通过
php.ini设置到session.save_path
= /tmp/php_sess<br>
<br>
mod_gzip和Resin配合：<br>
从resin的邮件列表上查到的：要让mod_gzip在mod_caucho后加载，否则mod_gzip不起作用<br>
...othr modules<br>

AddModule mod_so.c<br>
AddModule mod_caucho.c<br>
#notice: mod_gzip must load after mod_caucho<br>
AddModule mod_gzip.c<br>
AddModule mod_expires.c<br>
...</p>
<p>配置：mod_gzip + resin<br>
<i>&lt;IFModule mod_gzip.c&gt;<br>
mod_gzip_on Yes<br>

mod_gzip_dechunk yes<br>
mod_gzip_keep_workfiles No<br>
mod_gzip_minimum_file_size 3000<br>
mod_gzip_maximum_file_size 300000 <br>
mod_gzip_item_include file \.html$<br>
mod_gzip_item_include mime text/.*<br>
mod_gzip_item_include mime httpd/unix-directory<br>
mod_gzip_item_include handler caucho-request<br>
&lt;/IFModule&gt;<br>

</i></p>
<p>配置：mod_gzip + mod_proxy 反相代理加速并压缩 IIS<br>
注意要增加缺省的文件编码属性映射。<br>
AddType text/html .asp<br>
AddType text/html .aspx<br>
</p>
<p><i>&lt;IFModule mod_gzip.c&gt;</i></p>
<p><i>AddType text/html .asp<br>
AddType text/html .aspx<br>
mod_gzip_on Yes<br>

mod_gzip_dechunk yes<br>
mod_gzip_keep_workfiles No<br>
mod_gzip_minimum_file_size 3000<br>
mod_gzip_maximum_file_size 300000 <br>
mod_gzip_item_include file \.html$<br>
mod_gzip_item_include file \.asp$<br>
mod_gzip_item_include file \.aspx$<br>
mod_gzip_item_include mime text/.*<br>
mod_gzip_item_include mime httpd/unix-directory<br>

mod_gzip_item_include handler proxy-server<br>
&lt;/IFModule&gt;</i></p>
<p>参考资料：</p>
<a href="http://sourceforge.net/projects/mod-gzip/">mod_gzip的下载</a><br>
http://sourceforge.net/projects/mod-gzip/<br>
<p><a href="http://www.schroepl.net/projekte/mod_gzip/">mod_gzip项目首页</a><br>
http://www.schroepl.net/projekte/mod_gzip/<br>
</p>
<p><a href="http://httpd.apache.org/docs-2.0/mod/mod_deflate.html">Apache2
中的mod_deflate：压缩率比mod_gzip略低</a><br>

http://httpd.apache.org/docs-2.0/mod/mod_deflate.html<br>
</p>
<p><a href="http://www.chedong.com/tech/apache_install.html">模块化安装</a><a
 href="http://www.chedong.com/tech/apache_install.html">Apache</a><br>
http://www.chedong.com/tech/apache_install.html<br>
</p>]]>
   </content>
</entry>
<entry>
   <title>ACDSee的HTML相册生成</title>
   <link rel="alternate" type="text/html" href="http://www.chedong.com/tech/acdsee.html" />
   <id>tag:www.chedong.com,2007:/test//10.1269</id>
   
   <published>2003-09-09T06:41:27Z</published>
   <updated>2007-04-12T03:42:31Z</updated>
   
   <summary>内容摘要： 随着数码相机的普及，每次出游回来都会面对数量上百的照片整理，处理效率还是非常重要的因素。ACDSee 3.1（完整版）仍然是我目前最常用的照片查看/归档工具。以下是使用ACDSee进行照片整理和HTML相册生成的经验总结，大部分操作都可以完全只使 用键盘操作完成。...</summary>
   <author>
      <name>车东</name>
      <uri>http://www.chedong.com</uri>
   </author>
   
   
   <content type="html" xml:lang="en" xml:base="http://www.chedong.com/tech/">
      <![CDATA[<p>内容摘要：<br>
随着数码相机的普及，每次出游回来都会面对数量上百的照片整理，处理效率还是非常重要的因素。ACDSee
3.1（完整版）仍然是我目前最常用的照片查看/归档工具。以下是使用ACDSee进行照片整理和HTML相册生成的经验总结，大部分操作都可以完全只使
用键盘操作完成。<br>

</p>
]]>
      <![CDATA[<ol>
  <li><a href="#rename">照片的汇总和批量重命名：将多个相机中的图片按数字统一排序</a></li>
  <li><a href="#rotate">照片的编辑：无损的将JPEG图片进行翻转/反转</a></li>
  <li><a href="#html">HTML相册生成：自动生成缩略图和HTML浏览页面</a></li>
  <li><a href="#database">缩略图库清理：定期清理日常生成的缩略图库</a></li>
</ol>
<h2><a name="rename"></a>照片汇总和批量重命名</h2>

<p>可以先将所有的数码相机的照片汇总到一个目录下后，按照时间排序并批量重命名<br>
</p>
<ol>
  <li>按时间排序：在ACDSEE的浏览器模式下按：F12
按照详细资料列表模式浏览，如果列表字段中没有最后更新时间（modified）字段，则按 CTRL + 数字键盘上的4 显示，按“最后更新时间”列</li>
  <li>批量重命名：全选图片：&nbsp; Ctrl + A 然后按鼠标右键选择Rename series 或者 Alt + R
调出按数字批量重命名的界面，输入"###"将图片重命名成001.jpg 002.jpg... </li>
</ol>
<p> <img src="acdsee/rename.jpg" title="" alt="列表和重命名界面"
 style="width: 841px; height: 590px;"></p>
<p><br>
</p>

<h2><a name="rotate"></a>查看/调整照片</h2>
<ol>
  <li>切换到图片查看模式：双击一个文件，前一张：PageUp 后一张 PageUp 或 空格：</li>
  <li>删除一个图片：DEL</li>
  <li>翻转/反转图片：<span style="font-weight: bold;">JPEG无损转换</span>，照片处理中：最常用
的就是将竖幅面的照片切换成横幅，这个最好用JPEG
TRANSFORM（无损）而不是内置的图片处理工具Photo Enhancer： 因为：JPEG
TRANSFORM不会修改照片的最后修改时间，并且不影响分辨率，而Photo
Enhancer会修改照片的最后修改时间，并且存储时会有压缩率的选项。<br>
操作方法：通过菜单 Tools ==&gt; JPEG Transform 或者使用快捷键 Ctrl + J<br>

  </li>
</ol>
<p><img src="acdsee/rotate.jpg" title="" alt="列表和重命名界面"
 style="width: 726px; height: 520px;"><br>
&nbsp;&nbsp;&nbsp; <br>
<br>
</p>
<h2><a name="html"></a>HTML相册生成</h2>
<p>在浏览模式下：选定所有图片：Ctrl + A， 在菜单中选择Plug-ins ==&gt; HTML
Generator，输入标题和缩略图幅面设置后，就可以自动生成HTML相册了，推荐使用幅面200×150象素，3 * 2排列。<br>
</p>
<p><img src="acdsee/html.jpg" title="" alt="HTML相册生成"
 style="width: 801px; height: 626px;"><br>
本网站的很多相册都是用这个功能实现的：ACDSee会生成page_##.htm这样的一系列页面<br>

<a href="http://www.chedong.com/99_10_1/page_01.htm">http://www.chedong.com/99_10_1/page_01.htm</a><br>
</p>
<h2><a name="database"></a>后台缩略图库垃圾处理<br>
</h2>
<p>经常使用图片处理的机器上ACDSEE为了提高浏览速度，会生成很多缩略图库，使用一段之后，这个库可能会变得非常大（上百M），因此需要通过缩略
图库管理工具经常清理。<br>
操作界面：菜单 ==&gt; Database ==&gt;
Maintanence找到，为了节省空间删除相应数据库目录节点即可。<br>
<img src="acdsee/database.jpg" title="" alt="缩略图数据库清理"
 style="width: 802px; height: 523px;"><br>
</p>
<p><br>

</p>
<p><br>
最常用键盘操作快速参考：<br>
<br>
浏览模式：<br>
</p>
<ul>
  <li>浏览模式切换：缩略图模式：F8&nbsp; 详细资料列表模式：F12</li>
  <li>全选图片文件： Ctrl + A</li>

</ul>
<p><br>
查看浏览：<br>
</p>
<ul>
  <li>前一张： PageUp</li>
  <li>后一张： PageUp 或 空格</li>
  <li>全屏： Ctrl + F</li>
</ul>
<p><br>

编辑：<br>
</p>
<ul>
  <li>删除图片：DEL</li>
  <li>翻转/反转图片 Ctrl + J </li>
  <li>批量重命名：Alt + R</li>
</ul>
<p></p>
<p>参考资料：<br>

<a href="http://www.acdsystems.com/">ACDSee</a><br>
http://www.acdsystems.com/<br>
</p>
<p><a
 href="http://www.google.com/search?q=acdsee+3.1+full+retail+download">ACDSee
3.1 完整版下载</a><br>
http://www.google.com/search?q=acdsee+3.1+full+retail+download<br>]]>
   </content>
</entry>
<entry>
   <title>基于鼠标点击跟踪的用户点击行为分析</title>
   <link rel="alternate" type="text/html" href="http://www.chedong.com/tech/click.html" />
   <id>tag:www.chedong.com,2003:/test//10.1323</id>
   
   <published>2003-08-06T10:02:51Z</published>
   <updated>2007-05-11T12:47:23Z</updated>
   
   <summary><![CDATA[内容摘要： 在像网站首页这样的资源比较集中的页面中，那些栏目最经常被用户点击？居左居右对广告的点击率的影响是什么？ &ldquo;一切用数字说话&rdquo;：以上问题都可以通过跟踪浏览器客户端的鼠标行为，按区块对页面进行点击行为的分析。...]]></summary>
   <author>
      <name>车东</name>
      <uri>http://www.chedong.com</uri>
   </author>
   
   
   <content type="html" xml:lang="en" xml:base="http://www.chedong.com/tech/">
      <![CDATA[<p>内容摘要：<br /> 在像网站首页这样的资源比较集中的页面中，那些栏目最经常被用户点击？居左居右对广告的点击率的影响是什么？<br /> &ldquo;一切用数字说话&rdquo;：以上问题都可以通过跟踪浏览器客户端的鼠标行为，按区块对页面进行点击行为的分析。</p>]]>
      <![CDATA[<p>页面点击统计系统设计</p>
<p>输出：<br>
页面上不同区域的点击量统计。<br>
</p>
<p>数据采集：<br>
原理：<br>
通过JAVASCRIPT的鼠标触发事件，动态将当前鼠标的坐标，客户端的分辨率传递到统计服务器上。</p>
<p>如果要往服务器端发请求，做计数器，插入一个图片是最简单的方法，这里是一个简单的例子：<br>
<br>
</p>

<pre>/* (C) 2003 - 2004 www.chedong.com <br>
 * Free for all users, but leave in this  header<br>
 * click based user analysis:<br> * usage: touch a empty click.gif or create a static page on at server<br> * including following script into your html page<br> */<br><br>document.onclick = clickStat;<br><br>function clickStat() {<br>    // create a new empty element<br>    var image = document.createElement("&lt;img&gt;&lt;/img&gt;");<br>    <br>    // record client screen size and mouse coordinate<br>    tempX = event.clientX + document.body.scrollLeft;<br>    tempY = event.clientY + document.body.scrollTop;<br>    image.src = "http://www.chedong.com/click_stats.php?width=" + screen.width + "&amp;x=" <br>+ tempX + "&amp;y=" + tempY;<br>    image.height = 0;<br>    image.width = 0;<br>    <br>    //send request to stat server<br>    document.body.insertBefore(image);<br>    return true;<br>}<br></pre>

<p>通过全局的onClick事件，每次向统计服务器发一个请求：http:
//www.example.com/click_stat.php?width=1024&amp;x=345&amp;y=567<br>
其中：1024x768是屏幕分辨率，345是鼠标X坐标，567是鼠标Y坐标。<br>
点击统计程序click_stats.php会以上信息到日志文件中。</p>
<p>数据输出：<br>
从WEB日志中将相应统计提取出来。然后针对不同页面建立配置文件，将页面区块按照以下格式建立配置文件：<br>
#X<font size="-2">1</font> Y<font size="-2">1</font> X<font size="-2">2</font>

Y<font size="-2">2 </font>comments<br>
0 0 1024 100 navigator<br>
0 100 1024 200 top_story<br>
...<br>
</p>
<p>再利用用统计脚本根据指定区域的配置，将各个区域的点击量进行汇总。<br>
</p>]]>
   </content>
</entry>
<entry>
   <title>Google排名优化－面向搜速引擎的广告模式</title>
   <link rel="alternate" type="text/html" href="http://www.chedong.com/tech/google_ads.html" />
   <id>tag:www.chedong.com,2003:/test//10.1321</id>
   
   <published>2003-08-06T09:44:53Z</published>
   <updated>2007-04-12T03:42:31Z</updated>
   
   <summary>如果说新一代搜索引擎Google所依赖的PageRank技术更真实的突出了超链接(hyperlink)在互联网中互联互通的本质，大型门户网站是否也应该反思一下传统的广告投放/统计模式，也许让广告回归到最原始的静态链接形式，通过间接提升广告客户自身网站在大型搜索引擎中的排名这种模式也许更能突出大型门户网站自身的优势。 你完全不必耐心的看完后面所有的内容，因为结论无非以下一句话： 互联网上链接就是一切：来自其他网站相关主题的直接静态链接是唯一对提升自身站点在搜索引擎中的排名提升有长期作用的广告形式。...</summary>
   <author>
      <name>车东</name>
      <uri>http://www.chedong.com</uri>
   </author>
   
   
   <content type="html" xml:lang="en" xml:base="http://www.chedong.com/tech/">
      <![CDATA[<p>如果说新一代搜索引擎Google所依赖的PageRank技术更真实的突出了超链接(hyperlink)在互联网中互联互通的本质，大型门户网站是否也应该反思一下传统的广告投放/统计模式，也许让广告回归到最原始的静态链接形式，通过间接提升广告客户自身网站在大型搜索引擎中的排名这种模式也许更能突出大型门户网站自身的优势。</p>
<p>你完全不必耐心的看完后面所有的内容，因为结论无非以下一句话：
互联网上链接就是一切：来自其他网站相关主题的直接静态链接是唯一对提升自身站点在搜索引擎中的排名提升有长期作用的广告形式。</p>]]>
      <![CDATA[<h2>互联网广告业的发展历程回顾</h2>
<p><a href="http://www.doubleclick.net">DoubleClick</a>对NetGravity的收购标志着
“注意力经济”时期的传统门户网站广告模式已经发展的相当成熟了。当时的互联网广告推崇的优势在于很强目标性投放和来自第3方的客观统计，但由于来自用户
浏览器信息的局限性，广告投放要达到很高的目标性而且不影响投放效率的话，其投放成本也是非常高的，可以想象一下一个针对浏览者所在的地区（北京，上海）
进行的广告投放的难度：投放系统需要在几十毫秒内针对浏览器的IP信息映射出用户所在的地区，并从几百个正在运行的广告中找到相应的内容进行投放。</p>
<p>同样的，由于来自用户浏览器的信息的贫乏，统计结果对于大多数客户来说除了投放总量控制外几乎没有更多的意义。而广告客户自身往往缺乏对其进行深度
加工的知识和工具从而忽略了对投放统计的深度分析。之后的发展趋势大家也能感受的到：广告幅面越来越大，位置越来越扎眼，下载速度越来越慢……，可以说传
统互联网广告模式已经陷入了广告形式越来越“霸道”，但广告点击率越来越低的恶性循环。毕竟广告幅面的增加和广告位的增加都是有尽头的。</p>
<p>点击率的不断下降也促使广告客户在考虑：与其为10万个根本不关心我产品的用户花钱，不如为100个真正有需求的用户花钱。搜索引擎的关键词无疑比
用户的浏览器更直接的表达了用户的需求。以至于随后出现的以Oventure为代表的搜索引擎结果排名模式，以其更高的针对性投放机制和简洁的形式立刻成
为整个互联网广告行业中的亮点。毕竟来自搜索引擎的用户关键词统计比起传统广告的IP统计要有价值的多。</p>
<p>从<a href="http://www.yahoo.com">Yahoo!</a>对<a
 href="http://www.inktomi.com">Inktomi</a>的收购，<a
 href="http://www.overture.com">Overture</a>对<a href="http://www.av.com">AltaVista</a>的
收购来看，传统门户已经日益感受到了来自Google等新一代搜索引擎门户的威胁。而近2年Google的在用户使用的搜索引擎排名中的上升速度来看，
2003年Google的用户将超过Yahoo!几乎是必然的。</p>

<p>随着用户越来越多的通过搜速引擎来主动寻找需要的信息，对于大量急需推广自身的中小网站来说除了自身的界面设计要用户友好(User
Friendly)外，对搜索引擎友好度（Spider
friendly）也是一个必须考虑的问题。而且有越来越多的广告客户重视自身站点在大型搜索引擎中的排名和从中带来的流量。<br>
</p>
<p>在门户网站的广告投放和基于“付费排名”的广告是否能够提高广告客户自身在搜索引擎中的排名呢？答案都是否定的。<br>
</p>
<p>只要看一下各个门户网站的新闻页面的源代码就可以知道：大部分门户网站的广告其实是通过DoubleClick的广告投放系统进行的，其内容是一小
段在浏览器客户端运行的JavaScript脚本。其中的JavaScript脚本及其运行后所显示出来的文字其实是不可能被搜索引擎的Spider识别
并收录到索引中的。而且大部分广告的链接都是要先经过统计系统然后才转向到客户页面，因此这种通过动态发布/统计的广告其实对广告客户自身站点在所有搜索
引擎中的排名提升没有任何意义，如果搜索引擎的内容提取做的好的话，甚至页头页尾部分内容都根本不会进入到索引里，真正能够进入搜索引擎索引的只是新闻内
容本身的部分。<br>
</p>
<p>而付费排名更是如此：很多关键词根本没有可以让Spider查到的入口，而一个搜索引擎不会索引另外一个搜索引擎的搜索结果也是显而易见的。而且无
论是传统的广告模式还是付费排名模式对于直接用户来说都是比较反感的：商业化，反客观。2001的一个统计显示：“比
起富媒体(RichMedia)，消费者更钟情显示速度快的网站”。 </p>
<p>但反过来说：作为大型门户网站本身也应该意识到自己网站的内容本身对Google的排名算法的极大影响力，如果对这种影响力加以充分的利用也可能成
为一种很重要的广告资源。对于中小网站来说短时间内能大大提高自身站点在搜索引擎中排名的无疑是来自高PageRank的门户站点的直接静态链接。而门户
站点目前所富余的正是这些高PageRank，然而同时又大量浪费着广告投放资源而且广告投放率低下的内容页面（包括旧有的）。因此如果中小广告客户认
可：到被大型门户站点高PageRank的页面“直接链接”本身带来的搜索引擎排名提升的价值远比短期的用户点击统计有价值的多。那么基于静态链接的广告
就可以彻底放弃以前的广告模式中需要大量资源进行的面向用户浏览的动态发布系统和面向点击统计的动态转向统计系统。</p>
<p><b>回归最原始的静态链接形式广告：门户站点可以让自身拥有的大量高PageRank的页面成为间接帮助广告客户自身网站迅速提高在各种搜索引擎
中排名的资源。<br>
</b></p>
<p>注意：页面中的链接必须和被链接站点内容相关，因此，如果是关于汽车的广告链接，在新闻频道中出现是没有太多意义的。搜索引擎不简单的从当前内容页
面进行摘要统计，而且还会根据整个反向链接的内容进行内容摘要。<br>

</p>
<h2><b>DoubleClick模式、搜索引擎付费排名模式和面向主题的静态文字链接广告的比较</b></h2>
<table border="1" width="100%">
  <tbody>
    <tr>
      <td width="11%" align="right">对比项目</td>
      <td width="31%" align="center">DoubleClick模式</td>
      <td width="31%" align="center">付费排名式模式</td>

      <td width="27%" align="center">静态链接模式</td>
    </tr>
    <tr>
      <td width="11%" align="right">投放成本</td>
      <td width="31%">DoubleClick的DART广告投放系统设计无疑是完美的第3方统计，但是投放成本也是巨大的，以至
于如果广告的投放率达不到一定比例几乎连投放成本都无法收回。</td>
      <td width="31%">没有第3方统计，由搜索引擎或分类目录的提供商自身掌握，统计和对恶意点击的排除也是非常难控制的。</td>
      <td width="27%">不需要广告投放系统的动态发布；<br>

不做面向直接用户点击的统计；<br>
搜索引擎的排名提升相当于间接的第3方统计；</td>
    </tr>
    <tr>
      <td width="11%" align="right">投放目标性</td>
      <td width="31%">从用户端获得的信息极其有限：IP地域，浏览器的版本等……广告客户从中得到的报告统计也是乏味的。</td>
      <td width="31%">针对关键词的搜索引擎竞价排名投放无疑比传统广告的目标性强的多。<br>

明码标价点击也让搜索引擎用户知道“鲜花”的搜索结果大部分都是花钱买的位置。</td>
      <td width="27%">由于不是面向直接用户点击，因此广告形式可以使用最简单的纯文本形式链接（类似于报纸中缝的小广告），但可
以在几乎所有搜索引擎中搜索结果中排名靠前。</td>
    </tr>
    <tr>
      <td width="11%" align="right">用户接受程度</td>
      <td width="31%">现在各个门户网站首页广告幅面的增长和形式的“霸道”无异于对长期用户的“杀鸡取卵”
      <p>是无论投放系统的目标针对性如何强，用户可能当时都不关心广告的内容。</p>
      </td>

      <td width="31%">在用户最需要的时候再将广告内容推给用户，无疑用户的接受程度要比传统的广告形式高的多。而且明码标价式的
结果让用户知道那些条目是被购买的。</td>
      <td width="27%">由于是对广告客户自身网站在搜索引擎排名的间接影响。因此搜索引擎用户无法直接从搜索结果中知道那些是。</td>
    </tr>
    <tr>
      <td width="11%" align="right">资源利用率</td>
      <td width="31%">除了门户首页和频道首页外，其他具体内容页面因为投放成本问题而无法充分利用。</td>
      <td width="31%">真正有直接商业价值的关键词不会超过万分之一。</td>

      <td width="27%">如果把自己站点PageRank提高了，等于买下了自己页面上所有的关键词。因为无论查任何关键词，命中自
己页面后在结果中就会比其他站点高。</td>
    </tr>
    <tr>
      <td width="11%" align="right">时效性和<br>
影响范围</td>
      <td width="31%">过投放期失效</td>
      <td width="31%">过投放期失效</td>

      <td width="27%">被任何搜索引擎爬到，都能对客户站点在相应搜索引擎中的PageRank产生长期的影响。而且有可能对未来
新的搜索引擎起作用。</td>
    </tr>
  </tbody>
</table>
<p>大型门户网站和中小网站在“面向用户的注意力”方面有的只是量的优势，但在“面向搜索引擎的注意力”方面则同时拥有质和量的优势：</p>
<ol>
  <li>在搜索引擎中大型门户网站的页面PageRank非常高：可能随便一篇文章页面的PageRank就高达3，这个值已经超过多很多中小型网站
首页的PageRank值。</li>
  <li>拥有更高的索引更新频率：如果Google对一般站点的索引更新周期是3个星期左右，那么对门户站点就是是每5天，甚至对门户首页甚至是每天
更新。</li>

  <li>内容管理优势：目前大部分搜索引擎对动态网页是不索引或者少量索引的。和中小网站内容大部分使用动态网页发布不同，大部分大型门户网站的页面
都是通过发布系统生成的静态页面，并有长期的存储，非常适合搜索引擎抓取，</li>
  <li>成本降低：充分利用原先广告投放率及其低的内容页面：考虑到目前大部分门户网站在底层内容页面上的广告投放率远远低于5％，却占用了带宽和管
理成本的60％以上。而且面向主题的静态链接不是面向统计的：可以脱离目前成本极高的第3方动态广告投放量体系，大大降低门户网站的广告运营成本。</li>
</ol>
<p>从广告客户角度：</p>
<ol>
  <li>大投放量的首页客户：比如汽车，手机等是否真的很看重可怜的千分之5的点击率，而门户网站为了这千分之5的点击率，牺牲的是其他99.5%用
户的下载速度。</li>
  <li>中小投放量的广告客户是否认可在搜索引擎中长期的排名提升比短期的广告统计更有价值，客户是否愿意牺牲在门户站点的低点击率统计，换取在搜索
引擎中结果中长期的排名提升。即广告客户是否真的重视来自搜索引擎的潜在客户。</li>
</ol>

<p>从最终用户角度最直接的感受：<br>
&nbsp;
如果门户网站不想浪费带宽资源，图片广告应该减少，同时由于静态文字链接广告可以作为内容的一部分直接包含在页面中，也减少了对服务器的请求次数，纯文本
链接的形式会增加将大大提高用户的下载速度。</p>
<p>从搜索引擎服务商角度：<br>
毕竟以上所有的依据都是搜索引擎的排名算法策略，门户会更加依赖于搜索引擎的权威性，而且搜索引擎服务商甚至可以据此要求门户网站为自己的索引服务“竞
价”：比如增加索引更新频率，增大站点的索引范围等，以间接增加网页在结果中的出现几率和范围，在国外称之为付费索引服务：Paid
Inclusion Service。</p>
<p>此外，门户网站和搜索引擎服务商对用户搜索关键词的日志也是一种非常有潜力的资源。比如对汽车经销商来说，也许能从搜索引擎的关键词历史统计中得到
最近一段时间各种品牌车型的用户查询数，如果得到完整的WEB日志，甚至可以利用数据仓库工具对日志进行多维的分析挖掘，从而提前数月知道某种车型的销售
潜力等。进一步的甚至可以通过日志中的IP地址得到消费者的地域分布等。这种分析对于面向最终消费的商业用户将非常有吸引力。你可以从Google的年度
关键词统计中看出这方面的潜力：<br>
<a href="http://www.google.com/press/zeitgeist2002.html">http://www.google.com/press/zeitgeist2002.html<br>
</a></p>
<p><br>
</p>
<p>参考资料：</p>

<p>如何提高网站在Google中的排名——面向搜索引擎的网站设计<a
 href="http://www.chedong.com/tech/google.html"><br>
http://www.chedong.com/tech/google.html</a></p>
<p>Search Engine Watch<a href="http://www.searchenginewatch.com/"><br>
http://www.searchenginewatch.com</a></p>
<p>Link Farm是Blogger们最早开始使用的：利用Google的PageRank算法来迅速提高自己网页排名的方法<br>
<a href="http://e-comm.webopedia.com/TERM/L/link_farming.html">http://e-comm.webopedia.com/TERM/L/link_farming.html</a><br>
</p>
<p><a
 href="http://china.nikkeibp.co.jp/china/news/int/200212/int200212100100.html">“比起富媒体，消费者更钟情显示速度快的网站”</a><br>http://china.nikkeibp.co.jp/china/news/int/200212/int200212100100.html
</p>
<p>搜索引擎论坛：<br>

<a href="http://www.webmasterworld.com/category3.htm">http://www.webmasterworld.com/category3.htm</a><br>
<a href="http://www.searchengineworld.com/">http://www.searchengineworld.com/</a><br>
</p>]]>
   </content>
</entry>
<entry>
   <title>BBS2Blog—让BBS和Weblog互通</title>
   <link rel="alternate" type="text/html" href="http://www.chedong.com/tech/weblog.html" />
   <id>tag:www.chedong.com,2003:/test//10.1320</id>
   
   <published>2003-08-06T09:43:08Z</published>
   <updated>2007-04-12T03:42:31Z</updated>
   
   <summary>内容摘要： 拥有大量的历史积累的各种论坛系统中的内容往往很难被搜索引擎收录，BBS2BLOG是一个bbs改造思路：通过对现有BBS加入按“个人”的归档机制， 让这些丰富内容都可以成为整个可搜索互联网知识库的一部分。...</summary>
   <author>
      <name>车东</name>
      <uri>http://www.chedong.com</uri>
   </author>
   
   
   <content type="html" xml:lang="en" xml:base="http://www.chedong.com/tech/">
      <![CDATA[<p>内容摘要：<br>
拥有大量的历史积累的各种论坛系统中的内容往往很难被搜索引擎收录，BBS2BLOG是一个bbs改造思路：通过对现有BBS加入按“个人”的归档机制，
让这些丰富内容都可以成为整个可搜索互联网知识库的一部分。<br>
</p>
]]>
      <![CDATA[<p><span style="font-style: italic;">注：Blog是Weblog的简称</span><br
 style="font-style: italic;">
<span style="font-style: italic;">Blog本意是网志；作为知识过滤器的角度取其音将它称为“博客”；海峡对岸的
Blogger则根据Blog的社群性叫做部落格。</span><br>
</p>
<h2>面向搜索引擎友好(Search Engine Friendly)的重要性</h2>
虽说blogger大多数有点自恋倾向，但绝非“孤芳自赏”。由于Blog天然的search engine
friendly特征使得这些个人blogger通过Google获得了与大型网站一样（某些方面甚至更强）的影响力，因为在目前的搜索引擎中：谁被反相
链接次数多谁
就是权威是一个基本原则。<br>
<ul>
  <li>适合搜索引擎的机器人（spider）的遍历收录：<br>
    <pre>    树性结构的BBS系统 <br>    /      |     \ <br>  board1 board2  board3<br><br>            网状结构的Blog系统<br>   user1 &lt;-&gt; user2 &lt;-&gt; user3 &lt;-&gt; user4<br>      /        |          |         \<br>   user5 &lt;-&gt; user6 &lt;-&gt; user7 &lt;-&gt; user8 	<br></pre>

同样1万篇文章，由于搜索引擎的SPIDER的遍历深度是有限制的，所以如果从根目录开始抓取深度限制是10的话，分布在BBS的10个论坛也许只会抓取
其中的几百条记录，但如
果是500个用户的BLOG系统：由于属于一个人的内容一般不会像BBS论坛中的那样需要翻页很多，SPIDER不需要遍历很深就可以抓取完，因此
SPIDER可以抓取的
内容并且进入搜索的索引量可能比论坛高出一个数量级。</li>
  <li>网状引用容易获得高的PageRank：<br>
而且由于BLOG之间的相互引用，使得整个内容是网状的引用，相对于BBS单向的树状结构，blog内容的网状结构也非常适合从Google的索引
PageRank算法中获得比较高的权值。<br>
  </li>
  <li>内容关键词密度高：<br>
此外从内容上说：很多个人BLOG做的都是技术专家型的知识过滤，关注的内容相对集中，整个页面中的内容也比较容易获得比较高的关键词“密度”；而BBS
组织帖子(文章)是杂乱的，在帖子(文章)很多时，查找信息时，给您的可能是一大类无用的信息或是重复的信息；如果您在学习一门计算机技术或者进行一项研
究时,比如说Java或是asp,如果您是初学者,当您跑到论坛里面去,您会被论坛杂乱帖子搞得晕头
转向.而blog就不同了,它把学习技术的过程或者研究的过程记录下来,当您去读它时,您可以会受益非浅.也就是说bbs组织的内容相对杂乱,而blog
是个人知识的管理系统.<br>
  </li>
</ul>

我看了很多BLOG网站和自己的日志统计后，可以肯定的说：Google是大多数Blog网站最主要的用户来源。而且论坛系统和CMS都开始注意到
search engine friendly的重要性，比如：大多数SEO网站的论坛，链接已经完全静态化，连翻页都是通过URL
REWRITE进行参数传递；而Drupal内容管理系统中就有利用PATH_INFO进行的文章内容发布的选项。
<h2>KISS原则: Keep It Simple, Stupid<br>
</h2>
Blog是一种新兴的“个人”内容发布机制：<br>
<p>几年前，DEJA有最大的全球新闻组（NEWS）的WEB归档，网易社区把基于TELNET的BBS系统WEB化，而目前网上无数的MAILING
LIST的web归档，无一不体现了从用户发布手段从简单到更简单的趋势，而且用户使用这些信息发布工具学习成本越来越低。</p>
<p>原先做一个主页：新闻/评论系统，论坛/留言系统，都是需要用户分别学习使用的。而BLOG把以上所有形式都简化成了发表文章/他人评论的格式。甚
至很多BLOG对外的标题同步都是RSS（Really Simple Syndication
足够简单的标题/摘要同步）。这样接口甚至可以简化到用
手机发条短信就能在WEB上做内容发布的程度。<br>
</p>
<h2>基于BBS系统改造实现：BBS2Blog</h2>
BBS采用帖子固顶和发帖的时间顺序来组织帖子(文章)，并采用主题方式对帖子(文章)分类；而Blog则以作者为单位，按日历的方式来组织文章(帖子)
的。BBS2BLOG以现有BBS系统为数据源，将内容按个人BLOG方式进行发布：<br>
<ul>
  <li>根据作者，按时间的归档机制：增加个人发表文章的日历，按月归档，按日归档等<br>

  </li>
  <li>文章映射：用户在BBS中发表的每个主题作为一篇BLOG文章，而其他用户的回复作为BLOG评论。</li>
  <li>给每篇文章一个永久链接：BLOG上所有的内容最终都有一个永久链接PermaLink，便于他人长期引用。</li>
  <li>缺省按论坛将用户主题分类：省却用户自己进行文章分类的麻烦。</li>
</ul>
<p>注意：以上机制的实现一定要<a href="http://www.chedong.com/tech/google_url.html">通过
映射（URL REWRITING或者PATH_INFO）变成没有“?”的静态链接</a>。</p>
<p>引导用户通过目前的BBS发布转向BLOG发布还可以获得有以下几个方面的优势：<br>

</p>
<ul>
  <li>降低用户学习的成本：内容通过BBS发布，又能够以BLOG的面孔出现；</li>
  <li>利用BBS的人气，带来更多反馈：单纯的一个BLOG如果靠搜索引擎带来用户的话，可能很长时间后才能得到反馈，如果是已有一定群体的BBS
用户群落能够很好的帮助BLOGGER解
决初期反馈很少的问题；<br>
  </li>
</ul>
<p>总结：<br>
</p>
<p>如果把整个互联网看作是一个知识库的话，无论是新闻系统还是BBS系统都可以统都看作是内容管理系统（CMS），因为它们无非是内容的：标
题，内容，作者，时间等几维数据的不参数同的发布组合。</p>
<p>TODO：</p>

<p>Trackback ping等在BBS2BLOG系统中的实现<br>
</p>
<p>参考资料：<br>
</p>
<p><a href="http://www.cnblog.org">中文Blog心得集</a><br>
http://www.cnblog.org</p>
<p><a href="http://www.chedong.com/tech/google_url.html">基于URL
REWRITE和PATH_INFO的参数解析，实现的网页链接搜索引擎优化</a><br>
http://www.chedong.com/tech/google_url.html<br>
</p>]]>
   </content>
</entry>
<entry>
   <title>GNU工具箱</title>
   <link rel="alternate" type="text/html" href="http://www.chedong.com/tech/gnu.html" />
   <id>tag:www.chedong.com,2003:/test//10.1318</id>
   
   <published>2003-07-06T09:40:11Z</published>
   <updated>2007-04-12T03:42:31Z</updated>
   
   <summary>内容摘要： GNU很推崇“工具箱”哲学：很多复杂的问题都可以通过几个更简单的工具通过一定的组合加以解决的。 编辑器：vi pico 行处理：awk sed perl grep sort uniq 下载/解包：wget tar gzip shell 脚本本身的一些变量： $_ shell环境名称 如 /bin/sh ; $0 shell脚本本身，如 test.sh ; $1 $2 ..$9 命令行参数 test.sh -a -b 的$1 = -a $2 = -b...</summary>
   <author>
      <name>车东</name>
      <uri>http://www.chedong.com</uri>
   </author>
   
   
   <content type="html" xml:lang="en" xml:base="http://www.chedong.com/tech/">
      <![CDATA[<p>内容摘要：<br>
GNU很推崇“工具箱”哲学：很多复杂的问题都可以通过几个更简单的工具通过一定的组合加以解决的。<br>
</p>
<ul>
  <li><a href="#edit">编辑器：vi pico</a><br>
  </li>
  <li><a href="#line">行处理：awk sed perl grep sort uniq</a></li>
  <li><a href="#wget">下载/解包：wget tar gzip<br>

    </a></li>
</ul>
<p>shell 脚本本身的一些变量：  $_ shell环境名称 如 /bin/sh ;  $0 shell脚本本身，如 test.sh ; $1 $2 ..$9 命令行参数 test.sh -a -b 的$1 = -a  $2 = -b </p>
]]>
      <![CDATA[<h2><a name="edit"></a>编辑器：VI pico emacs<br>
</h2>
<p>vi中显示行号： :set nu<br>
去文件尾部：G<br>
去行尾 $<br>
添加 i a<br>
删除 x<br>

</p>
<h2><a name="line"></a>脚本和行文字处理<br>
</h2>
<p>给文件批量加前缀：<br>
先用awk生成命令列表：<br>
ls -1 *|awk '{print "uniq -c "$1" pre_"$1"|sort
-rn"}' &gt; batch_rename.sh</p>
<p>然后执行生成的脚本：<br>
sh batch_rename.sh <br>
</p>

<p>我的每月访问TOP10 统计脚本：<br>
awk -F '\t' '{print $4}' 2004_2.txt| grep chedong.com/tech/|sort |uniq -c|sort -rn|head -10
<br>
awk -F '\t' 用TAB分割；<br>
grep chedong.com/tech 只列出笔记目录下的文档；<br>
sort 排序<br>
uniq -c 汇总计数<br>
sort -rn 按数值排序<br>
head -10 TOP 10<br>
</p>

<p>我的每月来源TOP10统计脚本：<br>
grep --binary-files=text chedong.com 2004_2.txt |awk -F '\t' '{print $3}'| awk -F '/' '{print "http://"$3}'|grep -v chedong.com|sort|uniq -c |sort -rn|head -10<br />
grep --binary-files=text 强制按text文本处理<br>
awk -F '\t' 用TAB分割；<br>
awk -F '/' 获得域名；<br>
grep -v chedong.com 排除自身网站；<br>
sort 排序<br>
uniq -c 汇总计数<br>
sort -rn 按数值排序<br>

head -10 TOP 10<br>
</p>
<p>grep 打印上下文5行<br>
grep -A 5 -B 5 sometext my.file<br>
<br>
去掉#开头的注释，如：apache的httpd.conf<br>
grep -v "#" filename<br>
<br>
打印大文档中的某一行：<br>
sed -n 1234p access_log</p>

<p>将每4行数据变成一行<br>
pr -a -J -T --columns=4 source.log 
<br>
-a 横向输出
<br>-J 合并成行
<br>-T 忽略页头和页尾
<br>--columns=4 每4个单元一次
</p>
<p>已一些簡單的例子，解說 sed 的使用<br>
最後，還列出 sed 的 manual page<br>
<br>
---------------------------------------------------------------<br>
1. 將 filename 檔案內的 Giga 字串取代成 GigaRama<br>

&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp; sed s/Giga/GigaRama/ filename<br>
<br>
---------------------------------------------------------------<br>
2. 將 filename 檔案內的 xfish 字串那一行刪除<br>
<br>
&nbsp;&nbsp; sed /xfish/d filename<br>
<br>
---------------------------------------------------------------<br>

3. 指定哪一行，將之刪除<br>
&nbsp; <br>
&nbsp;&nbsp; sed '4d' filename<br>
<br>
---------------------------------------------------------------<br>
4. 或指定第一行到第幾行，將之刪除<br>
&nbsp; <br>
&nbsp;&nbsp; sed '1,4d' filename<br>

<br>
---------------------------------------------------------------<br>
5. 將第一行到第五行印出&nbsp; <br>
<br>
&nbsp;&nbsp; sed -n 1,5p filename<br>
<br>
---------------------------------------------------------------<br>
6. 將 file 檔案內的出現 xfish 字串的那一行單獨寫到 file2 內<br>
<br>
&nbsp;&nbsp; sed -n '/xfish/w file2' file<br>

<br>
---------------------------------------------------------------<br>
7. 萬用字元的使用，將 file 檔案內的 xfis? 哪一行寫到 file2 內<br>
<br>
&nbsp;&nbsp; sed '/xfis./w file2' file<br>
<br>
---------------------------------------------------------------<br>
8. 萬用字串的使用，將 file 檔案內的 xfis* 哪一行寫到 file2 內<br>
<br>
&nbsp;&nbsp; sed '/xfis*/w file2' file<br>

<br>
---------------------------------------------------------------<br>
9. 選定字元的使用，將 file 檔案內的 xfis[abcd] 哪一行寫到 file2 內<br>
<br>
&nbsp;&nbsp; sed '/xfis[abcd]/w file2' file<br>
<br>
---------------------------------------------------------------<br>
10. 特別符號的取消，利用 /<br>
<br>
&nbsp;&nbsp;&nbsp; sed s/\&lt;title\&gt;/\&lt;TITLE\&gt;/ file<br>

<br>
---------------------------------------------------------------<br>
11. 一行的起頭的取代，將 file 檔案的每一行起頭都加上 Hi..<br>
<br>
&nbsp;&nbsp;&nbsp; sed s/^/Hi.. / file<br>
<br>
---------------------------------------------------------------<br>
12. 一行的結尾的取代，將 file 檔案的每一行結尾都加上 Hi..<br>
<br>
&nbsp;&nbsp;&nbsp; sed s/$/Hi.. / file<br>

<br>
---------------------------------------------------------------<br>
13. 多重條件的指定，利用 -e 選項<br>
<br>
&nbsp;&nbsp;&nbsp; sed -e 's/Giga/GigaRama/' -e 's/^/Hi../' file<br>
<br>
---------------------------------------------------------------<br>
<br>
</p>
<h2><a name="wget"></a>下载解包：wget tar gz<br>
</h2>

<p>wget -P output_dir --cut-dirs=1 -nH -m
ftp://username:password@123.123.123.123:21/dir1/dir2/<br>
</p>
<p>选项说明：<br>
-P 指定输出目录名<br>
--cut-dirs=2 不创建目录层次 dir1/dir2/<br>
-nH 不创建域名目录：123.123.123.123/<br>
-m 镜像<br>
</p>
<p>例子：<br>
wget -P backup --cut-dir=1 -nH
ftp://myname:mypass@www.chedong.com:21/tech/<br>

</p>
<p>打包：使用GZ<br>
tar czf house.tgz house<br>
解包：使用gz<br>
tar xzf house.tgz<br>
打包：使用bz2<br>
tar cjf house.tbz2 house<br>
解包：使用bz2<br>
tar zjf house.tbz2<br>

<br>
ssh -p 12345 username@hostname.com<br>
sftp -oPort=12345 username@hostname.com<br>
<br>
<br>
</p>
<p>对开源软件的印象：开源社区很像一个基于互联网的原始丛林，那些经过近乎“物竞天择”式的发展并能够长期留存下来的工具/开发库往往都是非常“强
壮”的，GNU这些工具包的高效稳定给我留下了深刻印象，而且由于很多开源软件都来自资深工程师的实践，实际上可重用度也很高。如果从生态的角度来解释的
话，开源软件生存下去比同类商资软所需要的件要少。多<br>
</p>]]>
   </content>
</entry>
<entry>
   <title>NAT网关安装笔记</title>
   <link rel="alternate" type="text/html" href="http://www.chedong.com/tech/nat.html" />
   <id>tag:www.chedong.com,2003:/test//10.1272</id>
   
   <published>2003-06-09T07:14:20Z</published>
   <updated>2007-04-12T03:42:31Z</updated>
   
   <summary><![CDATA[ FreeBSD 4.7上的NAT网关安装笔记 RedHat 8上的NAT网关安装笔记 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!绝对不要远程调试防火墙配置!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 硬件需求： &nbsp;&nbsp;&nbsp; 双网卡 &nbsp;&nbsp;&nbsp; 内存 &gt; 64M &nbsp;&nbsp;&nbsp; 硬盘 &gt; 1G 注： NAT网关本身效率都很高，所以即使在配置很低的机器上运行效率也是足够的（仍建议尽可能多的增加内存 &gt; 256M）， 如果需要记录日志做分析，则会产生很大的I/O操作并占用大量硬盘空间，建议使用SCSI硬盘并做日志轮循。 假设2块网卡分别按照以下网段设置： 内网网卡IP地址：192.168.0.1/255.255.255.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 本身为网关 外网网卡IP地址：111.222.111.222/255.255.255.192 网关：111.222.111.1 安全策略： 作为网关，安全性非常重要，建议除了远程登录用的SSH外，尽可能多的停掉所有不相关服务。 本安装文档只是最简单的配置，没有任何安全过滤规则，更多安全过滤规则需要根据实际情况补充。...]]></summary>
   <author>
      <name>车东</name>
      <uri>http://www.chedong.com</uri>
   </author>
   
   
   <content type="html" xml:lang="en" xml:base="http://www.chedong.com/tech/">
      <![CDATA[<ul>
  <li><a href="#freebsd">FreeBSD 4.7上的NAT网关安装笔记</a></li>
  <li><a href="#iptables">RedHat 8上的NAT网关安装笔记</a></li>
</ul>
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!<br>
!!!绝对不要远程调试防火墙配置!!!<br>
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!<br>
<br>
硬件需求：<br>
&nbsp;&nbsp;&nbsp; 双网卡<br>
&nbsp;&nbsp;&nbsp; 内存 &gt; 64M<br>
&nbsp;&nbsp;&nbsp; 硬盘 &gt; 1G<br>
<br>
注：<br>
NAT网关本身效率都很高，所以即使在配置很低的机器上运行效率也是足够的（仍建议尽可能多的增加内存 &gt; 256M），<br>
如果需要记录日志做分析，则会产生很大的I/O操作并占用大量硬盘空间，建议使用SCSI硬盘并做日志轮循。<br />
假设2块网卡分别按照以下网段设置：<br>
内网网卡IP地址：192.168.0.1/255.255.255.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
本身为网关<br>
外网网卡IP地址：111.222.111.222/255.255.255.192 网关：111.222.111.1<br>
<br>
安全策略：<br>
<ul>
  <li> 作为网关，安全性非常重要，建议除了远程登录用的SSH外，尽可能多的停掉所有不相关服务。</li>

  <li>本安装文档只是最简单的配置，没有任何安全过滤规则，更多安全过滤规则需要根据实际情况补充。</li>
</ul>
]]>
      <![CDATA[<h2><a name="ipfirewall"></a>FreeBSD 4.7上用IPFIREWALL做NAT网关</h2>
安装FreeBSD系统时包含开发平台（gcc工具等），因为内核缺省不支持地址转发和防火墙，所以需要重新编译内核。<br>
<br>
内核编译<br>
========<br>
由于内核缺省不支持地址转发和防火墙，所以需要重新编译内核：<br>
#cd /usr/src/sys/i386/conf/<br>

#cp GENERIC GATEWAY<br>
#vi GATEWAY<br>
<br>
修改后的内核配置：修改了名称和增加了IPFIREWALL的相关选项：<br>
#diff GATEWAY GENERIC <br>
25c25<br>
&lt; ident&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GATEWAY<br>
---<br>

&gt; ident&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GENERIC<br>
62,64d61 加入IPFIREWALL选项<br>
&lt; options IPFIREWALL<br>
&lt; options IPFIREWALL_VERBOSE<br>
&lt; options IPDIVERT<br>
<br>

重新编译：大约需要30分钟左右<br>
#/usr/sbin/config GATEWAY<br>
#cd ../../compile/GATEWAY/<br>
#make depend; make; make install<br>
<br>
重启机器一次，确认新的KERNEL正常启动。<br>
<br>
修改rc.conf中的相关配置：假设内网使用网卡fxp0，外网网卡使用xl0<br>
###############################################<br>
gateway_enable="YES"<br>

<br>
ifconfig_fxp0="inet 192.168.0.1&nbsp; netmask 255.255.255.0"<br>
ifconfig_xl0="inet 111.222.111.222&nbsp; netmask 255.255.255.0"<br>
defaultrouter="111.222.111.1"<br>
<br>
natd_enable="YES"<br>
natd_interface="xl0"<br>
<br>

firewall_enable="YES"<br>
firewall_type="open"<br>
###############################################<br>
<br>
防火墙过滤规则设置<br>
==================<br>
ipfw的规则是通过运行/etc/rc.firewall这个脚本生效的，rc.firewall脚本会检查rc.conf中firewall_type等配置，然后根据firewall_type定义的模式"open"
"client" "simple"等切换到rc.firewall中相应部分执行。<br>
<br>
一个安全的防火墙本身是一个非常复杂的策略。为了方便配置，可以以rc.firewall文件为基础，在各种缺省模式的基础上加入自己的规则。缺省最简单的防火墙配置是在rc.conf里设置使用"open"模式，<br>
<br>

注意：修改rc.firewall配置建议从最简单的"open"模式开始，而且让修改生效前，一定将旧的成功运行的配置文件备份成rc.firewall.bak，便于以后的错误后恢复，如果防火墙配置错误可能导致远程无法登陆，因此修改防火墙配置一定要在服务器终端界面进行。<br>
<br>
日志记录<br>
========<br>
文件系统优化： 使用异步文件系统提高性能async<br>
vi /etc/fstab<br>
/dev/da0s1f&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/tmp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
ufs&nbsp;&nbsp;&nbsp;&nbsp;

rw,async&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2<br>
/dev/da0s1g&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/usr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
ufs&nbsp;&nbsp;&nbsp;&nbsp;
rw,async&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2<br>

<br>
修改rc.firewall中"open"模式中的配置：打开记录日志<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #${fwcmd} add 65000 pass all
from any to any<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ${fwcmd} add 65000 pass log
all from any to any<br>
<br>
修改/etc/newsyslog.conf 增加security日志的存储上限从100k到 10000K<br>
/var/log/security&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
600&nbsp; 10&nbsp;&nbsp;&nbsp;

10000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
*&nbsp;&nbsp;&nbsp;&nbsp; Z<br>
<br>
新的配置生效<br>
============<br>
修改防火墙配置后，可以用<br>
#sh /etc/rc.firewall<br>
让新的配置生效<br>

<br>
常用命令<br>
========<br>
ipfw list：显示目前的配置规则：<br>
#ipfw list<br>
00050 divert 8668 ip from any to any via xl0<br>
00100 allow ip from any to any via lo0<br>
00200 deny ip from any to 127.0.0.0/8<br>
00300 deny ip from 127.0.0.0/8 to any<br>

65000 allow log ip from any to any<br>
65535 deny ip from any to any<br>
<br>
ipfw show：显示各种规则的统计信息<br>
# ipfw show<br>
00050 1008267&nbsp; 632203534 divert 8668 ip from any to any via vr0<br>
00100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 allow ip from
any to any via lo0<br>

00200&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 deny ip from
any to 127.0.0.0/8<br>
00300&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 deny ip from
127.0.0.0/8 to any<br>
65000 1782079 1257247553 allow ip from any to any<br>
65535&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 36&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

31871 deny ip from any to any<br>
<h2><a name="iptables"></a>RedHat 8上用iptables做NAT网关<br>
</h2>
将下列内容加入/etc/rc.local文件中：eth0绑内网IP eth1绑外网IP<br>
################<br>
echo 1 &gt; /proc/sys/net/ipv4/ip_forward<br>
/sbin/modprobe ip_tables<br>
/sbin/modprobe iptable_filter<br>

/sbin/modprobe iptable_nat<br>
/sbin/modprobe ip_conntrack<br>
/sbin/modprobe ip_conntrack_ftp<br>
/sbin/modprobe ip_nat_ftp<br>
/sbin/iptables --flush INPUT<br>
/sbin/iptables --flush FORWARD<br>
/sbin/iptables --flush POSTROUTING --table&nbsp; nat<br>
/sbin/iptables --policy FORWARD DROP<br>

/sbin/iptables --table nat --append POSTROUTING --out-interface eth1
--source 192.168.0.0/24 --jump MASQUERADE<br>
/sbin/iptables --append FORWARD --in-interface eth1 --match state
--state ESTABLISHED,RELATED --jump ACCEPT<br>
/sbin/iptables --append FORWARD --source 192.168.0.0/24 --jump ACCEPT<br>
################<br>
<br>
iptables --list查看过滤表<br>
<br>
参考资料：<br>
<p>王波：FreeBSD使用大全<br>
<a href="http://tech.sina.com.cn/focus/FreeBSD/2000-01-19/196.shtml">http://tech.sina.com.cn/focus/FreeBSD/2000-01-19/196.shtml</a></p>

<p>FreeBSD IPFW-HOWTO<br>
<a href="http://www.freebsd-howto.com/HOWTO/Ipfw-HOWTO">http://www.freebsd-howto.com/HOWTO/Ipfw-HOWTO</a><br>
<br>
ipfw的命令参考：<br>
<a href="http://www.chedong.com/phpMan.php/man/ipfw">
http://www.chedong.com/phpMan.php/man/ipfw</a></p>
<p>《linux下如何用iptables做NAT上网》原文作者：upkill98<br>
<a
 href="http://it.rising.com.cn/newSite/Channels/Safety/SysSafety/Safe_Unix/200211/06-094108327.htm">http://it.rising.com.cn/newSite/Channels/Safety/SysSafety/Safe_Unix/200211/06-094108327.htm</a><br>
</p>
<p>IPTables的日志分析：<br>

<a href="http://www.linuxlinks.com/Software/Log_Analyzers/">
http://www.linuxlinks.com/Software/Log_Analyzers/</a><br>
<a href="http://freshmeat.net/projects/iptqlog/">iptqlog</a><br>
<br>
软盘防火墙制作：<br>
<a href="http://www.zelow.no/floppyfw"> http://www.zelow.no/floppyfw</a><br>
<a
 href="http://directory.google.com/Top/Computers/Software/Operating_Systems/Linux/Distributions/Tiny/Floppy_Sized/">
http://directory.google.com/Top/Computers/Software/Operating_Systems/Linux/Distributions/Tiny/Floppy_Sized/</a></p>]]>
   </content>
</entry>
<entry>
   <title>基于反相代理的Web缓存加速——可缓存的CMS系统设计</title>
   <link rel="alternate" type="text/html" href="http://www.chedong.com/tech/cache.html" />
   <id>tag:www.chedong.com,2003:/test//10.1314</id>
   
   <published>2003-06-06T09:27:18Z</published>
   <updated>2007-04-12T03:42:31Z</updated>
   
   <summary>内容摘要： 对于一个日访问量达到百万级的网站来说，速度很快就成为一个瓶颈。除了优化 内容发布系统的应用本身外，如果能把不需要实时更新的动态页面的输出结果转化成静态网页来发布，速度上的提升效果将是显著的，因为一个动态页面的速度往往 会比静态页面慢2－10倍，而静态网页的内容如果能被缓存 在内存里，访问速度甚至会比原有动态网页有2－3个数量级的提高。 动态缓存和静态缓存的比较 基于反向代理加速的站点规划 基于apache mod_proxy的反向代理加速实现 基于squid的反向代理加速实现 面向缓存的页面设计 应用的缓存兼容性设计： HTTP_HOST/SERVER_NAME和REMOTE_ADDR/REMOTE_HOST需要用 HTTP_X_FORWARDED_HOST/HTTP_X_FORWARDED_SERVER代替 后台的内容管理系统的页面输出遵守可缓存的设计，这样就可以把性能问题交给前台的缓存服务器来解决了，从而大大简化CMS系统本身的复杂程度。...</summary>
   <author>
      <name>车东</name>
      <uri>http://www.chedong.com</uri>
   </author>
   
   
   <content type="html" xml:lang="en" xml:base="http://www.chedong.com/tech/">
      <![CDATA[<p>内容摘要：<br>
对于一个日访问量达到百万级的网站来说，速度很快就成为一个瓶颈。除了优化
内容发布系统的应用本身外，如果能把不需要实时更新的动态页面的输出结果转化成静态网页来发布，速度上的提升效果将是显著的，因为一个动态页面的速度往往
会比静态页面慢2－10倍，而静态网页的内容如果能被缓存
在内存里，访问<a href="#test">速度甚至会比原有动态网页有2－3个数量级的提高</a>。<br>

</p>
<ul>
  <li><a href="#compare">动态缓存和静态缓存的比较</a></li>
  <li><a href="#site">基于反向代理加速的站点规划</a><br>
  </li>
  <li><a href="#apache">基于apache mod_proxy的反向代理加速实现</a></li>
  <li><a href="#squid">基于squid的反向代理加速实现</a></li>
  <li><a href="#page">面向缓存的页面设计</a></li>

  <li><a href="#compatible">应用的缓存兼容性设计</a>：<br>
HTTP_HOST/SERVER_NAME和REMOTE_ADDR/REMOTE_HOST需要用
HTTP_X_FORWARDED_HOST/HTTP_X_FORWARDED_SERVER代替</li>
</ul>
后台的内容管理系统的页面输出遵守可缓存的设计，这样就可以把性能问题交给前台的缓存服务器来解决了，从而大大简化CMS系统本身的复杂程度。<br>]]>
      <![CDATA[<h2><a name="compare"></a>静态缓存和动态缓存的比较 </h2>
<p>静态页面的缓存可能有2种形式：其实主要区别就是CMS是否自己负责关联内容的缓存更新管理。</p>
<ol>
  <li>静态缓存：是在新内容发布的同时就立刻生成相应内容的静态页面，比如：2003年3月22日，管理员通过后台内容管理界面录入一
篇文章后，就立刻生成http://www.chedong.com/tech/2003/03/22/001.html这个静态页面，并同步更新相关索
引页上的链接。<br style="font-style: italic;">

    <br>
  </li>
  <li>动态缓存：是在新内容发布以后，并不预先生成相应的静态页面，直到对相应内容发出请求时，如果前台缓存服务器找不到相应缓存，就向后台内容管
理服务器发出请求，后台系统会生成相应内容的静态页面，用户第一次访问页面时可能会慢一点，但是以后就是直接访问缓存了。<br>
    <span style="font-style: italic;"><br>
如果去ZDNet等国外网站会发现他们使用的基于</span><a href="http://www.vignette.com"
 style="font-style: italic;">Vignette</a><span
 style="font-style: italic;">内容管理系统都有这样的页面名称：0,22342566,300458.html。其实这里
的0,22342566,300458就是用逗号分割开的多个参数：</span><br style="font-style: italic;">
    <span style="font-style: italic;">第一次访问找不到页面后，相当于会在服务器端产生一个doc_type=
0&amp;doc_id=22342566&amp;doc_template=300458的查询，</span><br
 style="font-style: italic;">

    <span style="font-style: italic;">而查询结果会生成的缓存的静态页面：
0,22342566,300458.html</span><br>
  </li>
</ol>
<p>静态缓存的缺点：</p>
<ul>
  <li>复杂的触发更新机制：这两种机制在内容管理系统比较简单的时候都是非常适用的。但对于一个关系比较复杂的网站来说，页面之间的逻
辑引用关系就成为一个非常非常复杂的问题。最典型的例子就是一条新闻要同时出现在新闻首页和相关的3个新闻专题中，在静态缓存模式中，每发一篇新文章，除
了这篇新闻内容本身的页面外，还需要系统通过触发器生成多个新的相关静态页面，这些相关逻辑的触发也往往就会成为内容管理系统中最复杂的部分之一。</li>
  <li>旧内容的批量更新： 通过静态缓存发布的内容，对于以前生成的静态页面的内容很难修改，这样用户访问旧页面时，新的模板根本无法生效。</li>
</ul>
<p>在动态缓存模式中，每个动态页面只需要关心，而相关的其他页面能自动更新，从而大大减少了设计相关页面更新触发器的需要。<br>

</p>
<p><span style="font-style: italic;">以前做小型应用的时候也用过类似方式：应用首次访问以后将数据
库的查询结果在本地存成一个文件，下次请求时先检查本地缓存目录中是否有缓存文件，从而减少对后
台数据库的访问。虽然这样做也能承载比较大的负载，但这样的内容管理和缓存管理一体的系统是很难分离的，而且数据完整性也不是很好保存，内容更新时，应用
需要把相应内容的的缓存文件删除。但是这样的设计在缓存文件很多的时候往往还需要将缓存目录做一定的分布，否则一个目录下的文件节点超过3000，rm
*都会出错。</span><br>
</p>
<p>这时候，系统需要再次分工，把复杂的内容管理系统分解成：内容输入和缓存这2个相对简单的系统实现。<br>
</p>
<ul>
  <li>后台：内容管理系统，专心的将内容发布做好，比如：复杂的工作流管理，复杂的模板规则等……</li>
  <li>前台：页面的缓存管理则可以使用缓存系统实现<br>
  </li>
</ul>

<pre>______________________             ___________________<br>|Squid Software cache|             |F5 Hardware cache|<br>----------------------             -------------------<br>            \                    /<br>             \ ________________ /<br>               |ASP |JSP |PHP |<br>             Content Manage System<br>               ----------------</pre>
<p>所以分工后：内容管理和缓存管理2者，无论哪一方面可选的余地都是非常大的：软件（比如前台80端口使用SQUID对后台8080的内容发布管理系
统进行缓存），缓存硬件，甚至交给<a href="http://www.akamai.com/">akamai</a>这样的专业服务商。<br>
</p>
<h2><a name="site"></a>面向缓存的站点规划</h2>
一个利用SQUID对多个站点进行做WEB加速http acceleration方案：<br>
原先一个站点的规划可能是这样的：<br>
200.200.200.207 www.chedong.com <br>
200.200.200.208 news.chedong.com <br>
200.200.200.209 bbs.chedong.com <br>
200.200.200.205 images.chedong.com<br>
面向缓存服务器的设计中：所有站点都通过外部DNS指向到同一个IP：200.200.200.200/201这2台缓存服务器上（使用2台是为了
冗余备份）
<pre>                          _____________________   ________<br>www.chedong.com  请求  \ |       cache box     | |        |  / 192.168.0.4   www.chedong.com <br>news.chedong.com 请求   -| 200.200.200.200/201 |-|firewall| -  192.168.0.4   news.chedong.com <br>bbs.chedong.com  请求  / |   /etc/hosts        | |   box  |  \ 192.168.0.3   bbs.chedong.com<br>                          ---------------------   --------<br></pre>

工作原理：<br>
外部请求过来时，设置缓存根据配置文件进行转向解析。这样，服务器请求就可以转
发到我们指定的内部地址上。<br>
在处理多虚拟主机转向方面：mod_proxy比squid要简单一些：可以把不同服务转向后后台多个IP的不同端口上。<br>
而squid只能通过禁用DNS解析，然后根据本地的/etc/hosts文件根据请求的域名进行地址转发，后台多个服务器必须使用相同的端口。<br>
使用反向代理加速，我们不仅可以得到性能上的提升，而且还能获得额外的安全性和配置的灵活度：<br>
<ul>
  <li>配置灵活性提高：可以自己在内部服务器上控制后台服务器的DNS解析，当需要在服务器之间做迁移调整时，就不用大量修改外部DNS配置了，只
需要修改内部DNS实现服务的调整。</li>
  <li>数据安全性增加：所有后台服务器可以很方便的被保护在防火墙内。</li>

  <li>后
台应用设计复杂程度降低：原先为了效率常常需要建立专门的图片服务器images.chedong.com和负载比较高的应用服务器
bbs.chedong.com分离，在反向代理加速模式中，所有前台请求都通过缓存服务器：实际上就都是静态页面，这样，应用设计时就不用考虑
图片和应用本身分离了，也大大降低了后台内容发布系统设计的复杂程度，由于数据和应用都存放在一起，也方便了文件系统的维护和管理。<br>
  </li>
</ul>
<h2><a name="apache"></a>基于Apache mod_proxy的反向代理缓存加速实现</h2>
Apache包含了mod_proxy模块，可以用来实现代理服务器，针对后台服务器的反向加速<br>
安装apache 1.3.x 编译时：<br>
--enable-shared=max --enable-module=most<br>
<span style="font-style: italic;">注：Apache
2.x中mod_proxy已经被分离成mod_proxy和mod_cache：同时mod_cache有基于文件和基于内存的不同实现</span><br>
创建/var/www/proxy，设置apache服务所用户可写<br>

mod_proxy配置样例：反相代理缓存＋缓存<br>
架设前台的www.example.com反向代理后台的www.backend.com的8080端口服务。<br>
修改：httpd.conf<br>
&lt;VirtualHost *&gt;<br>
ServerName www.example.com<br>
ServerAdmin admin@example.com<br>
# reverse proxy setting<br>
ProxyPass / http://www.backend.com:8080/<br>
ProxyPassReverse / http://www.backend.com:8080/<br>

# cache dir root<br>
CacheRoot "/var/www/proxy"<br>
# max cache storage<br>
CacheSize 50000000<br>
# hour: every 4 hour <br>
CacheGcInterval 4<br>
# max page expire time: hour<br>
CacheMaxExpire 240<br>
# Expire time = (now - last_modified) * CacheLastModifiedFactor <br>

CacheLastModifiedFactor 0.1<br>
# defalt expire tag: hour<br>
CacheDefaultExpire 1<br>
# force complete after precent of content retrived: 60-90%<br>
CacheForceCompletion 80<br>
CustomLog /usr/local/apache/logs/dev_access_log combined<br>
&lt;/VirtualHost&gt;<br>
<h2><a name="squid"></a>基于Squid的反向代理加速实现</h2>
Squid是一个更专用的代理服务器，性能和效率会比Apache的mod_proxy高很多。<br>

如果需要combined格式日志补丁：<br>
<a
 href="http://www.squid-cache.org/mail-archive/squid-dev/200301/0164.html">http://www.squid-cache.org/mail-archive/squid-dev/200301/0164.html</a><br>
squid的编译：<br>
./configure --enable-useragent-log&nbsp; --enable-referer-log
--enable-default-err-language=Simplify_Chinese \
--enable-err-languages="Simplify_Chinese English"
--disable-internal-dns&nbsp; <br>
make<br>
#make install<br>
#cd /usr/local/squid<br>

make dir cache<br>
chown squid.squid *<br>
vi /usr/local/squid/etc/squid.conf<br>
在/etc/hosts中：加入内部的DNS解析，比如：<br>
192.168.0.4 www.chedong.com <br>
192.168.0.4 news.chedong.com<br>
192.168.0.3 bbs.chedong.com<br>
---------------------cut here----------------------------------<br>
# visible name<br>

visible_hostname cache.example.com<br>
# cache config: space use 1G and memory use 256M<br>
cache_dir ufs /usr/local/squid/cache 1024 16 256 <br>
cache_mem 256 MB<br>
cache_effective_user squid<br>
cache_effective_group squid<br>
<br>
http_port 80<br>
httpd_accel_host virtual<br>

httpd_accel_single_host off<br>
httpd_accel_port 80<br>
httpd_accel_uses_host_header on<br>
httpd_accel_with_proxy on<br>
# accelerater my domain only<br>
acl acceleratedHostA dstdomain .example1.com<br>
acl acceleratedHostB dstdomain .example2.com<br>
acl acceleratedHostC dstdomain .example3.com<br>
# accelerater http protocol on port 80<br>

acl acceleratedProtocol protocol HTTP<br>
acl acceleratedPort port 80<br>
# access arc<br>
acl all src 0.0.0.0/0.0.0.0<br>
# Allow requests when they are to the accelerated machine AND to the<br>
# right port with right protocol<br>
http_access allow acceleratedProtocol acceleratedPort acceleratedHostA<br>
http_access allow acceleratedProtocol acceleratedPort acceleratedHostB<br>
http_access allow acceleratedProtocol acceleratedPort acceleratedHostC<br>

# logging<br>
emulate_httpd_log on<br>
cache_store_log none<br>
# manager<br>
acl manager proto cache_object<br>
http_access allow manager all<br>
cachemgr_passwd pass all<br>
<br>
----------------------cut here---------------------------------<br>

创建缓存目录：<br>
/usr/local/squid/sbin/squid -z<br>
启动squid<br>
/usr/local/squid/sbin/squid<br>
停止squid：<br>
/usr/local/squid/sbin/squid -k shutdown<br>
启用新配置：<br>
/usr/local/squid/sbin/squid -k reconfig<br>
通过crontab每天0点截断/轮循日志：<br>

0 0 * * * (/usr/local/squid/sbin/squid -k rotate) <br>
<h2><a name="page"></a>可缓存的动态页面设计</h2>
什么样的页面能够比较好的被缓存服务器缓存呢？如果返回内容的HTTP
HEADER中有"Last-Modified"和"Expires"相关声明，比如：<br>
Last-Modified: Wed, 14 May 2003 13:06:17 GMT<br>
Expires: Fri, 16 Jun 2003 13:06:17 GMT<br>
前端缓存服务器在期间会将生成的页面缓存在本地：硬盘或者内存中，直至上述页面过期。<br>
因此，一个可缓存的页面：
<ul>
  <li>页面必须包含Last-Modified:
标记<br>

一般纯静态页面本身都会有Last-Modified信息，动态页面需要通过函数强制加上，比如在PHP中：<br>
// always modified now<br>
header("Last-Modified: " . gmdate("D, d M Y H:i:s")
. " GMT");<br>
    <br>
  </li>
  <li>必须有Expires或Cache-Control: max-age标记设置页面的过期时间：<br>
对于静态页面，通过apache的mod_expires根据页面的MIME类型设置缓存周期：比如图片缺省是1个月，HTML页面缺省是2天等。<br>
&lt;IfModule mod_expires.c&gt; <br>

&nbsp; &nbsp; ExpiresActive on<br>
&nbsp; &nbsp; ExpiresByType image/gif "access plus 1 month"<br>
&nbsp; &nbsp; ExpiresByType text/css "now plus 2 day"<br>
&nbsp; &nbsp; ExpiresDefault "now plus 1 day"<br>
&lt;/IfModule&gt;<br>

    <br>
对于动态页面，则可以直接通过写入HTTP返回的头信息，比如对于新闻首页index.php可以是20分钟，而对于具体的一条新闻页面可能是1天后过
期。比如：在php中加入了1个月后过期：<br>
// Expires one month later<br>
header("Expires: " .gmdate ("D, d M Y H:i:s", time()
+ 3600 * 24 * 30). " GMT");<br>
    <br>
  </li>
  <li>如果服务器端有基于HTTP的认证，必须有Cache-Control: public标记，允许前台</li>
</ul>
ASP应用的缓存改造 首先在公用的包含文件中(比如include.asp)加入以下公用函数：<br>

&lt;%<br>
' Set Expires Header in minutes<br>
Function SetExpiresHeader(ByVal minutes) <br>
&nbsp;&nbsp;&nbsp; ' set Page Last-Modified Header:<br>
&nbsp;&nbsp;&nbsp; ' Converts date (19991022 11:08:38) to http form
(Fri, 22 Oct 1999 12:08:38 GMT)<br>
&nbsp;&nbsp;&nbsp; Response.AddHeader "Last-Modified",
DateToHTTPDate(Now())<br>
&nbsp;&nbsp;&nbsp; <br>

&nbsp;&nbsp;&nbsp; ' The Page Expires in Minutes<br>
&nbsp;&nbsp;&nbsp; Response.Expires = minutes<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; ' Set cache control to externel applications<br>
&nbsp;&nbsp;&nbsp; Response.CacheControl = "public"<br>
End Function <br>
' Converts date (19991022 11:08:38) to http form (Fri, 22 Oct 1999
12:08:38 GMT)<br>

Function DateToHTTPDate(ByVal OleDATE)<br>
&nbsp; Const GMTdiff = #08:00:00#<br>
&nbsp; OleDATE = OleDATE - GMTdiff<br>
&nbsp; DateToHTTPDate = engWeekDayName(OleDATE) &amp; _<br>
&nbsp;&nbsp;&nbsp; ", " &amp; Right("0" &amp; Day(OleDATE),2) &amp; " "

&amp; engMonthName(OleDATE) &amp; _<br>
&nbsp;&nbsp;&nbsp; " " &amp; Year(OleDATE) &amp; " " &amp; Right("0"
&amp; Hour(OleDATE),2) &amp; _<br>

&nbsp;&nbsp;&nbsp; ":" &amp; Right("0" &amp; Minute(OleDATE),2) &amp;
":" &amp; Right("0" &amp; Second(OleDATE),2) &amp; " GMT"<br>
End Function <br>

Function engWeekDayName(dt)<br>
&nbsp;&nbsp;&nbsp; Dim Out<br>
&nbsp;&nbsp;&nbsp; Select Case WeekDay(dt,1)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 1:Out="Sun"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 2:Out="Mon"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 3:Out="Tue"<br>

&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 4:Out="Wed"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 5:Out="Thu"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 6:Out="Fri"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 7:Out="Sat"<br>
&nbsp;&nbsp;&nbsp; End Select<br>

&nbsp;&nbsp;&nbsp; engWeekDayName = Out<br>
End Function<br>
Function engMonthName(dt)<br>
&nbsp;&nbsp;&nbsp; Dim Out<br>
&nbsp;&nbsp;&nbsp; Select Case Month(dt)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 1:Out="Jan"<br>

&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 2:Out="Feb"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 3:Out="Mar"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 4:Out="Apr"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 5:Out="May"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 6:Out="Jun"<br>

&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 7:Out="Jul"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 8:Out="Aug"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 9:Out="Sep"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 10:Out="Oct"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 11:Out="Nov"<br>

&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Case 12:Out="Dec"<br>
&nbsp;&nbsp;&nbsp; End Select<br>
&nbsp;&nbsp;&nbsp; engMonthName = Out<br>
End Function<br>
%&gt;<br>
然后在具体的页面中，比如index.asp和news.asp的“最上面”加入以下代码：HTTP Header<br>
&lt;!--#include file="../include.asp"--&gt;<br>

&lt;%<br>
'页面将被设置20分钟后过期<br>
SetExpiresHeader(20)<br>
%&gt;<br>
<h2><a name="compatible"></a>应用的缓存兼容性设计</h2>
<br>
经过代理以后，由于在客户端和服务之间增加了中间层，因此服务器无法直接拿到客户端的IP，服务器端应用也无法直接通过转发请求的地址返回给客户端。但是
在转发请求的HTTD头信息中，增加了HTTP_X_FORWARDED_????信息。用以跟踪原有的客户端IP地址和原来客户端请求的服务器地址：<br>
下面是2个例子，用于说明缓存兼容性应用的设计原则：<br>
<pre>    '对于一个需要服务器名的地址的ASP应用：不要直接引用HTTP_HOST/SERVER_NAME，判断一下是否有HTTP_X_FORWARDED_SERVER<br>    function getHostName ()<br>        dim hostName as String = ""<br>        hostName = Request.ServerVariables("HTTP_HOST")<br>        if not isDBNull(Request.ServerVariables("HTTP_X_FORWARDED_HOST")) then<br>            if len(trim(Request.ServerVariables("HTTP_X_FORWARDED_HOST"))) &gt; 0 then<br>                hostName = Request.ServerVariables("HTTP_X_FORWARDED_HOST")<br>            end if<br>        end if<br>        return hostNmae<br>    end function<br><br>    //对于一个需要记录客户端IP的PHP应用：不要直接引用REMOTE_ADDR，而是要使用HTTP_X_FORWARDED_FOR，<br>    function getUserIP (){<br>        $user_ip = $_SERVER["REMOTE_ADDR"];<br>        if ($_SERVER["HTTP_X_FORWARDED_FOR"]) {<br>            $user_ip = $_SERVER["HTTP_X_FORWARDED_FOR"];<br>        }<br>    } <br></pre>

<br>
注意：HTTP_X_FORWARDED_FOR如果经过了多个中间代理服务器，有何能是逗号分割的多个地址，<br>
比如：200.28.7.155,200.10.225.77 unknown,219.101.137.3<br>
因此在很多旧的数据库设计中（比如BBS）往往用来记录客户端地址的字段被设置成20个字节就显得过小了。<br>
经常见到类似以下的错误信息：<br>
<font face="宋体" size="2"></font>
<p><font face="宋体" size="2">Microsoft JET Database Engine</font> <font
 face="宋体" size="2">错误 '80040e57'</font> </p>
<p><font face="宋体" size="2">字段太小而不能接受所要添加的数据的数量。试着插入或粘贴较少的数据。</font> </p>

<p><font face="宋体" size="2">/inc/char.asp</font><font face="宋体" size="2">，
行236</font> </p>
原因就是在设计客户端访问地址时，相关用户IP字段大小最好要设计到50个字节以上，当然经过3层以上代理的几率也非常小。<br>
如何检查目前站点页面的可缓存性（Cacheablility）呢？可以参考以下2个站点上的工具：<br>
<a href="http://www.ircache.net/cgi-bin/cacheability.py">http://www.ircache.net/cgi-bin/cacheability.py</a><br>
<h2><a name="test"></a> 附：SQUID性能测试试验</h2>
<br>
phpMan.php是一个基于php的man page server，每个man<br>
page需要调用后台的man命令和很多页面格式化工具，系统负载比较高，提供了Cache<br>

Friendly的URL，以下是针对同样的页面的性能测试资料：<br>
测试环境：Redhat 8 on Cyrix 266 / 192M Mem <br>
测试程序：使用apache的ab(apache benchmark)：<br>
测试条件：请求50次，并发50个连接<br>
测试项目：直接通过apache 1.3 (80端口) vs squid 2.5(8000端口：加速80端口) <br>
<br>
测试1：无CACHE的80端口动态输出：<br>
ab -n 100 -c 10 http://www.chedong.com:81/phpMan.php/man/kill/1<br>
This is ApacheBench, Version 1.3d &lt;$Revision: 1.2 $&gt; apache-1.3<br>

Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd,<br>
http://www.zeustech.net/<br>
Copyright (c) 1998-2001 The Apache Group, http://www.apache.org/<br>
<br>
Benchmarking localhost (be patient).....done<br>
Server Software:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
Apache/1.3.23&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
Server Hostname:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; localhost<br>

Server<br>
Port:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
80<br>
<br>
Document Path:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
/phpMan.php/man/kill/1<br>
Document Length:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4655 bytes<br>
<br>
Concurrency Level:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5<br>

Time taken for tests:&nbsp;&nbsp; 63.164 seconds<br>
Complete requests:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 50<br>
Failed requests:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0<br>
Broken pipe errors:&nbsp;&nbsp;&nbsp;&nbsp; 0<br>
Total transferred:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 245900 bytes<br>

HTML transferred:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 232750 bytes<br>
Requests per second:&nbsp;&nbsp;&nbsp; 0.79 [#/sec] (mean)<br>
Time per request:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6316.40 [ms]<br>
(mean)<br>
Time per request:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1263.28 [ms]<br>

(mean, across all concurrent requests)<br>
Transfer rate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
3.89 [Kbytes/sec] received<br>
<br>
Connnection Times (ms)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
min&nbsp; mean[+/-sd] median&nbsp;&nbsp; max<br>
Connect:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;<br>

29&nbsp; 106.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp; 553<br>
<span style="color: rgb(255, 0, 0);">Processing:&nbsp; 2942&nbsp; 6016<br>
1845.4&nbsp;&nbsp; 6227 10796</span><br style="color: rgb(255, 0, 0);">

<br>
<span style="color: rgb(255, 0, 0);">Waiting:&nbsp;&nbsp;&nbsp;&nbsp;<br>
2941&nbsp; 5999 1850.7&nbsp;&nbsp; 6226 10795</span><br
 style="color: rgb(255, 0, 0);">
<br>
<span style="color: rgb(255, 0, 0);">Total:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
2942&nbsp; 6045 1825.9&nbsp;&nbsp; 6227 10796</span><br>

<br>
Percentage of the requests served within a certain time (ms)<br>
&nbsp; 50%&nbsp;&nbsp; 6227<br>
&nbsp; 66%&nbsp;&nbsp; 7069<br>
&nbsp; 75%&nbsp;&nbsp; 7190<br>

&nbsp; 80%&nbsp;&nbsp; 7474<br>
&nbsp; 90%&nbsp;&nbsp; 8195<br>
&nbsp; 95%&nbsp;&nbsp; 8898<br>
&nbsp; 98%&nbsp;&nbsp; 9721<br>

&nbsp; 99%&nbsp; 10796<br>
&nbsp;100%&nbsp; 10796 (last request)<br>
<br>
测试2：SQUID缓存输出<br>
/home/apache/bin/ab -n50 -c5<br>
"http://localhost:8000/phpMan.php/man/kill/1"<br>
This is ApacheBench, Version 1.3d &lt;$Revision: 1.2 $&gt; apache-1.3<br>

Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd,<br>
http://www.zeustech.net/<br>
Copyright (c) 1998-2001 The Apache Group, http://www.apache.org/<br>
<br>
Benchmarking localhost (be patient).....done<br>
Server Software:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
Apache/1.3.23&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
Server Hostname:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; localhost<br>

Server<br>
Port:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
8000<br>
<br>
Document Path:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
/phpMan.php/man/kill/1<br>
Document Length:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4655 bytes<br>
<br>
Concurrency Level:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5<br>

Time taken for tests:&nbsp;&nbsp; 4.265 seconds<br>
Complete requests:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 50<br>
Failed requests:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0<br>
Broken pipe errors:&nbsp;&nbsp;&nbsp;&nbsp; 0<br>
Total transferred:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 248043 bytes<br>

HTML transferred:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 232750 bytes<br>
Requests per second:&nbsp;&nbsp;&nbsp; 11.72 [#/sec] (mean)<br>
Time per request:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 426.50 [ms] (mean)<br>
Time per request:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 85.30 [ms] (mean,<br>
across all concurrent requests)<br>

Transfer rate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
58.16 [Kbytes/sec] received<br>
<br>
Connnection Times (ms)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
min&nbsp; mean[+/-sd] median&nbsp;&nbsp; max<br>
Connect:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
0&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;<br>

9.5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp; 68<br>
<span style="color: rgb(255, 0, 0);">Processing:&nbsp;&nbsp;&nbsp;&nbsp;<br>
7&nbsp;&nbsp;&nbsp; 83&nbsp; 537.4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
7&nbsp; 3808</span><br style="color: rgb(255, 0, 0);">

<br>
<span style="color: rgb(255, 0, 0);">Waiting:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
5&nbsp;&nbsp;&nbsp; 81&nbsp; 529.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
6&nbsp; 3748</span><br style="color: rgb(255, 0, 0);">
<br>
<span style="color: rgb(255, 0, 0);">Total:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
7&nbsp;&nbsp;&nbsp; 84&nbsp; 547.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>

7&nbsp; 3876</span><br>
<br>
Percentage of the requests served within a certain time (ms)<br>
&nbsp; 50%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7<br>
&nbsp; 66%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7<br>

&nbsp; 75%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7<br>
&nbsp; 80%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7<br>
&nbsp; 90%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7<br>
&nbsp; 95%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7<br>

&nbsp; 98%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8<br>
&nbsp; 99%&nbsp;&nbsp; 3876<br>
&nbsp;100%&nbsp;&nbsp; 3876 (last request)<br>
<br>
结论：No Cache / Cache = 6045 / 84 = 70<br>

结论：对于可能被缓存请求的页面，服务器速度可以有2个数量级的提高，因为SQUID是把缓存页面放在内存里的（因此几乎没有硬盘I/O操作）。<br>
<br>
小节：<br>
<ul>
  <br>
  <li> 大访问量的网站应尽可能将动态网页生成静态页面作为缓存发布，甚至对于搜索引擎这样的动态应用来说，缓存机制也是非常非常重要的。</li>
  <br>
  <li>在动态页面中利用HTTP Header定义缓存更新策略。</li>

  <br>
  <li>利用缓存服务器获得额外的配置和安全性</li>
  <br>
  <li>日志非常重要：SQUID日志缺省不支持COMBINED日志，但对于需要REFERER日志的这个补丁非常重要：<a
 href="http://www.squid-cache.org/mail-archive/squid-dev/200301/0164.html">http://www.squid-cache.org/mail-archive/squid-dev/200301/0164.html</a><br>
    <br>
  </li>
  <br>

</ul>
<br>参考资料：<br><a href="http://vancouver-webpages.com/proxy.html">HTTP代理缓存</a>
<br>
http://vancouver-webpages.com/proxy.html</p>
<br>
<a
 href="http://linux.oreillynet.com/pub/a/linux/2002/02/28/cachefriendly.html">可缓存的页面设计</a><br>
http://linux.oreillynet.com/pub/a/linux/2002/02/28/cachefriendly.html<br>
<a href="http://www.zdnet.com.cn/developer/tech/story/0,2000081602,39110239-2,00.htm">运用ASP.NET的输出缓冲来存储动态页面 -&nbsp; 开发者 - ZDNet China</a><br>
http://www.zdnet.com.cn/developer/tech/story/0,2000081602,39110239-2,00.htm<br>相关RFC文档：<br>

<ul>
  <br>
  <li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">RFC<br>
2616</a>:<br>
    <ul>
      <br>
      <li><a
 href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13">section<br>
13</a> (Caching)</li>

      <br>
      <li><a
 href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9">section<br>
14.9</a> (Cache-Control header)</li>
      <br>
      <li><a
 href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21">section<br>
14.21</a> (Expires header)</li>

      <br>
      <li><a
 href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.32">section<br>
14.32</a> (Pragma: no-cache) is important if you are interacting with<br>
HTTP/1.0 caches</li>
      <br>
      <li><a
 href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.29">section<br>
14.29</a> (Last-Modified) is the most common validation method</li>

      <br>
      <li><a
 href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.11">section<br>
3.11</a>