<?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,2010:/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-05T15: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-10T09:15:12Z</published>
   <updated>2007-04-12T02: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-09T05:41:27Z</published>
   <updated>2007-04-12T02: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-06T09:02:51Z</published>
   <updated>2007-05-11T11: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-06T08:44:53Z</published>
   <updated>2007-04-12T02: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-06T08:43:08Z</published>
   <updated>2007-04-12T02: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-06T08:40:11Z</published>
   <updated>2007-04-12T02: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-09T06:14:20Z</published>
   <updated>2007-04-12T02: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-06T08:27:18Z</published>
   <updated>2007-04-12T02: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> (Entity Tags) covers the extra validation method</li>
      <br>
    </ul>
    <br>
  </li>

  <br>
</ul>
<br><a href="http://www.web-caching.com/cacheability.html">可缓存性检查</a><br>
http://www.web-caching.com/cacheability.html<br>
<a href="http://vancouver-webpages.com/CacheNow/detail.html">缓存设计要素</a><br>
http://vancouver-webpages.com/CacheNow/detail.html<br>
<br>
ZOPE上的几篇使用APACHE MOD_PROXY MOD_GZIP加速的文档<br>
<a href="http://www.zope.org/Members/anser/apache_zserver/">http://www.zope.org/Members/anser/apache_zserver/</a><br>
<a
 href="http://www.zope.org/Members/softsign/ZServer_and_Apache_mod_gzip">http://www.zope.org/Members/softsign/ZServer_and_Apache_mod_gzip</a><br>

<a href="http://www.zope.org/Members/rbeer/caching">http://www.zope.org/Members/rbeer/caching</a>]]>
   </content>
</entry>
<entry>
   <title>Google排名优化－面向Google(Search Engine Friendly)的URL设计</title>
   <link rel="alternate" type="text/html" href="http://www.chedong.com/tech/google_url.html" />
   <id>tag:www.chedong.com,2007:/test//10.1278</id>
   
   <published>2003-05-10T09:15:12Z</published>
   <updated>2007-04-12T02:42:31Z</updated>
   
   <summary><![CDATA[内容摘要：不得不承认，将动态网页链接rewriting成静态链接是最保险和稳定的面向搜索引擎优化方式 此外随着互联网上的内容以惊人速度的增长也越来越突出了搜索引擎的重要性，如果网站想更好地被搜索引擎收录，网站设计除了面向用户友好（User Friendly）外，搜索引擎友好 （Search Engine Friendly）的设计也是非常重要的。进入搜索引擎的页面内容越多，则被用户用不同的关键词找到的几率越大。在Google的算法调查一文 中提到一个站点被Google索引页面的数量其实对PageRank也是有一定影响的。由于Google 突出的是整个网络中相对静态的部分（动态网页索引量比较小）,链接地址相对固定的静态网页比较适合被Google索引（怪不得很多大网站的邮件列表归档和BLOG按日期归档的文档很容被搜的到），因此很多关于面向搜索引擎 URL设计优化(URI Pretty)的文章中提到了很多利用一定机制将动态网页参数变成像静态网页的形式： 比如可以将： http://phpunixman.sourceforge.net/index.php?mode=man&amp;parameter=ls 变成：http://phpunixman.sourceforge.net/index.php/man/ls...]]></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>内容摘要：不得不承认，将动态网页链接rewriting成静态链接是最保险和稳定的面向搜索引擎优化方式</p>
<p>此外随着互联网上的内容以惊人速度的增长也越来越突出了搜索引擎的重要性，如果网站想更好地被搜索引擎收录，网站设计除了面向用户友好（User
Friendly）外，<a href="http://www.chedong.com/tech/google.html">搜索引擎友好
（Search
Engine Friendly）的设计也是非常重要的</a>。进入搜索引擎的页面内容越多，则被用户用不同的关键词找到的几率越大。<a
 href="http://pr.efactory.de/e-number-of-pages.shtml">在Google的算法调查</a>一文
中提到一个站点被Google索引页面的数量其实对PageRank也是有一定影响的。由于Google
突出的是整个网络中相对静态的部分（动态网页索引量比较小）,链接地址相对固定的静态网页比较适合被Google索引（怪不得很多大网站的邮件列表归档和BLOG按日期归档的文档很容被搜的到），因此很多关于面向搜索引擎
URL设计优化(URI
Pretty)的文章中提到了很多利用一定机制将动态网页参数变成像静态网页的形式：<br>
比如可以将：<a href="http://phpunixman.sourceforge.net/index.php?mode=man&amp;parameter=ls"><br>
http://phpunixman.sourceforge.net/index.php?mode=man&amp;parameter=ls</a><br>

变成：<a href="http://phpunixman.sourceforge.net/index.php/man/ls">http://phpunixman.sourceforge.net/index.php/man/ls</a><br>
</p>
]]>
      <![CDATA[<p>实现方式主要有2种：<br>
</p>
<ul>
  <li><a href="#rewrite">基于url rewrite</a><br /><a href="http://www.helicontech.com/download/">IIS的ISAPI REWRITE下载（免费）</a></li>
  <li><a href="#path_info">基于path_info</a></li>
</ul>

<h2><a name="rewrite"></a>把URI地址用作参数传递：URL REWRITE<br>
</h2>
<p>最简单的是基于各种WEB服务器中的URL重写转向（Rewrite）模块的URL转换：<br>
这样几乎可以不修改程序的实现将 news.asp?id=234 这样的链接映射成
news/234.html，从外面看上去和静态链接一样。Apache服务器上有一个模块（非缺省）：mod_rewrite：URL
REWRITE功能之强大足够写上一本书。<br>
</p>
<p>当我需要将将news.asp?id=234的映射成news/234.html时，只需设置：<br>
RewriteRule /news/(\d+)\.html /news\.asp\?id=$1 [N,I]<br>
这样就把 /news/234.html 这样的请求映射成了 /news.asp?id=234<br>
当有对/news/234.html的请求时：web服务器会把实际请求转发给/news.asp?id=234<br>
</p>

<p>而在IIS也有相应的REWRITE模块：比如<a href="http://www.helicontech.com/">ISAPI
REWRITE</a>和<a href="http://www.qwerksoft.com/products/iisrewrite/">IIS
REWRITE</a>，语法都是基于正则表达式，因此配置几乎和apache的mod_rewrite是相同的：</p>
<p>比对于某一个简单应用可以是：<br>
RewriteRule /news/(\d+)\.html /news/news\.php\?id=$1 [N,I]<br>
这样就把 http://www.chedong.com/news/234.html 映射到了
http://www.chedong.com/news/news.php?id=234<br>
<br>
一个更通用的能够将所有的动态页面进行参数映射的表达式是：<br>
把 http://www.myhost.com/foo.php?a=A&amp;b=B&amp;c=C <br>

表现成
http://www.myhost.com/foo.php/a/A/b/B/c/C。<br>
RewriteRule (.*?\.php)(\?[^/]*)?/([^/]*)/([^/]*)(.+?)?$1(?2$2&amp;:\?)$3=$4?5$5: [N,I]
</p>
<p>以下是针对phpBB的一个Apache mod_rewrite配置样例：</p>
<pre>
    RewriteEngine On
    RewriteRule /forum/topic_(.+)\.html$  /forum/viewtopic.php?t=$1 [L]
    RewriteRule /forum/forum_(.+)\.html$ /forum/viewforum.php?f=$1 [L]
    RewriteRule /forum/user_(.+)\.html$  /forum/profile.php?mode=viewprofile&u=$1  [L]
</pre>
<p>这样设置后就可以通过topic_1234.html forum_2.html user_34.html这样的链接访问原来的动态页面了。</p>
<p>通过URL REWRITE还有一些好处：<br>mod_rewrite和isapirewrite基本兼容，但是还是有些不同，比如：isapirewrite中"?"需要转义成"\?"，mod_rewrite不用，isapirewrite支持 "\d+" （全部数字），mod_rewrite不支持
</p>

<ul>
  <li>隐藏后台实现：这在后台应用平台的迁移时非常有用：当从asp迁移到java平台
时，对于前台用户来说，根本感受不到后台应用的变化；</li>
  <li>简化数据校验：因为像(\d+)这样的参数，可以有效的控制数字的格式甚至位数；</li>
</ul>
<p>比如我们需要将应用从news.asp?id=234迁移成news.php?query=234时，前台的表现可以一直保持为
news/234.html。从实现应用和前台表现的分离：保持了URL的稳定性，而使用mod_rewrite甚至可以把请求转发到其他后台服务器上。<br>
</p>
<h2><a name="path_info"></a>基于PATH_INFO的URL美化</h2>
<p>Url美化的另外一个方式就是基于PATH_INFO：<br>
PATH_INFO是一个CGI 1.1的标准，经常发现很多跟在CGI后面的"/value_1/value_2"就是PATH_INFO参数：<br>

比如：<a href="http://phpunixman.sourceforge.net/index.php/man/ls">http://phpunixman.sourceforge.net/index.php/man/ls</a> 中：$PATH_INFO = "/man/ls"<br>
</p><p>
PATH_INFO是CGI标准，因此PHP Servlet等都有的支持。
比如Servlet中就有request.getPathInfo()方法。<br>
注意：/myapp/servlet/Hello/foo的
getPathInfo()返回的是/foo，而/myapp/dir/hello.jsp/foo的getPathInfo()将返回的
/hello.jsp，从这里你也可以知道jsp其实就是一个Servlet的PATH_INFO参数。ASP不支持PATH_INFO
<br>
PHP中基于PATH_INFO的参数解析的例子如下：<br>
//注意：参数按"/"分割，第一个参数是空的：从/param1/param2中解析出$param1 $param2这2个参数<br>
if ( isset($_SERVER["PATH_INFO"]) ) {<br>
&nbsp; &nbsp; list($nothing, $param1, $param2) = explode('/',
$_SERVER["PATH_INFO"]);<br>

}<br>
<br>
如何隐蔽应用：例如 .php，的扩展名：<br>
在APACHE中这样配置：<br>
&lt;FilesMatch "^app_name$"&gt;<br>
&nbsp; &nbsp; ForceType application/x-httpd-php<br>
&lt;/FilesMatch&gt;<br>
<br>
如何更像静态页面：app_name/my/app.html<br>

解析的PATH_INFO参数的时候，把最后一个参数的最后5个字符“.html”截断即可。<br>
注意：APACHE2中缺省是不允许PATH_INFO的，需要设置 AcceptPathInfo on<br>
<br>
特别是针对使用虚拟主机用户，无权安装和配置mod_rewrite的时候，PATH_INFO往往就成了唯一的选择。<br>
<br>
OK，这样以后看见类似于http://www.example.com/article/234这样的网页你就知道可能是
article/show.php?id=234这个php程序生成的动态网页，很多站点表面看上去可能有很多静态目录，其实很有可能都是使用1，2个程
序实现的内容发布。比如很多WIKIWIKI系统都使用了这个机制：整个系统就一个简单的wiki程序，而看上去的目录其实都是这个应用拿后面的地址作为
参数的查询结果。<br>
<br>
利用基于MOD_REWRITE/PATH_INFO ＋
CACHE服务器的解决方案对原有的动态发布系统进行改造，也可以大大降低旧有系统升级到新的内容管理系统的成本。并且方便了搜索引擎收录入索引。</p>
<h2><a name="page"></a>附：如何在IIS上利用PHP支持PATH_INFO</h2>
<p>PHP的ISAPI模式安装备忘：只试成 php-4.2.3-Win32<br>

<br>
解包目录<br>
========<br>
php-4.2.3-Win32.zip c:\php<br>
<br>
PHP.INI初始化文件<br>
=================<br>
复制：c:\php\php.ini-dist 到 c:\winnt\php.ini<br>
<br>
配置文件关联<br>

============<br>
按照install.txt中的说明配置文件关联<br>
<br>
运行库文件<br>
==========<br>
复制 c:\php\php4ts.dll 到 c:\winnt\system32\php4ts.dll<br>
<br>
这样运行后：会发现php把PATH_INFO映射到了物理路径上<br>
Warning: Unknown(C:\CheDong\Downloads\ariadne\www\test.php\path):
failed to create stream: No such file or directory in Unknown on line 0<br>
<br>

Warning: Unknown(): Failed opening
'C:\CheDong\Downloads\ariadne\www\test.php\path' for inclusion
(include_path='.;c:\php4\pear') in Unknown on line 0<br>
<br>
安装ariadne的PATCH<br>
==================<br>
停止IIS服务<br>
net stop iisadmin<br>
ftp://ftp.muze.nl/pub/ariadne/win/iis/php-4.2.3/php4isapi.dll<br>
覆盖原有的c:\php\sapi\php4isapi.dll<br>
<br>
注：<br>

ariadne是一个基于PATH_INFO的内容发布系统，<br>
PHP 4.3.2 RC2中CGI模式的PATH_INFO已经修正，照常安装即可。<br>
</p>
<p>参考资料：<br>
URL Rewrite文档：<br>
<a href="http://www.isapirewrite.com/docs/">ISAPI REWRITE文档</a><br>
<a href="http://www.isapirewrite.com/download/">IIS的ISAPI REWRITE下载（免费）</a><br>
<a href="http://httpd.apache.org/docs/mod/mod_rewrite.html">http://httpd.apache.org/docs/mod/mod_rewrite.html</a><br>
<a href="http://httpd.apache.org/docs-2.0/mod/mod_rewrite.html">http://httpd.apache.org/docs-2.0/mod/mod_rewrite.html</a><br>

</p>
<p>搜索引擎友好的URL设计<br>
<a href="http://www.sitepoint.com/article/485">http://www.sitepoint.com/article/485</a><br>
<span style="font-style: italic;">说不定这个URL原来就是articel.php?id=485<br>
</span></p>
<p>一个基于PATH_INFO的开源内容管理系统<br>
<a href="http://typo3.com/">http://typo3.com/</a><br>
</p>
<p>Google的PageRank算法说明：<br>
<a href="http://pr.efactory.de/">http://pr.efactory.de/</a><br>

</p>]]>
   </content>
</entry>
<entry>
   <title>基于Lucene/XML的站内全文检索解决方案：WebLucene</title>
   <link rel="alternate" type="text/html" href="http://www.chedong.com/tech/weblucene.html" />
   <id>tag:www.chedong.com,2003:/test//10.1328</id>
   
   <published>2003-05-06T09:28:08Z</published>
   <updated>2009-03-20T14:52:01Z</updated>
   
   <summary><![CDATA[内容摘要： 为Lucene做一个通用XML接口一直是我最大的心愿：更方便的在WEB应用中嵌入全文检索功能，2004年时类似应用还很不成熟，但现在也许应该优先试试以Lucene为核心的Solr全文应用引擎； 提供了XML的数据输入接口：适合将原有基于各种数据库的数据源导入到全文索引中，保证了数据源的平台无关性； 通过了基于XML的搜索结果输出：方便了通过XSLT进行前台的结果显示； MySQL \ / JSP Oracle - DB - ==&gt; XML ==&gt; (Lucene Index) ==&gt; XML - ASP MSSQL / - PHP MS Word / \ / XHTML PDF / =XSLT=&gt; - TEXT \ XML \_________WebLucene__________/ 使用过程如下：...]]></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 /> 为Lucene做一个通用XML接口一直是我最大的心愿：更方便的在WEB应用中嵌入全文检索功能，2004年时类似应用还很不成熟，但现在也许应该优先试试<a href="http://lucene.apache.org/solr/">以Lucene为核心的Solr</a>全文应用引擎；<a href="http://lucene.apache.org/solr/"><br /></a></p> <ul>   <li>提供了XML的数据输入接口：适合将原有基于各种数据库的数据源导入到全文索引中，保证了数据源的平台无关性；</li>    <li>通过了基于XML的搜索结果输出：方便了通过XSLT进行前台的结果显示；</li> </ul> <pre><br />    MySQL  \                                                  / JSP    <br />    Oracle - DB      -  ==&gt;   XML ==&gt; (Lucene Index) ==&gt; XML  -  ASP    <br />    MSSQL  /                                                  -  PHP            <br />             MS Word /                                        \         / XHTML<br />                 PDF /                                         =XSLT=&gt; -  TEXT<br />                                                                        \ XML                                                                     <br />                                \_________WebLucene__________/ <br />使用过程如下：<br /></pre>  <ol>   <li>将数据用脚本导出成XML格式；</li>   <li>将XML数据源导入LUCENE索引；</li>   <li>从WEB界面得到XML结果输出，并通过XSLT生成HTML页面</li> </ol> ]]>
      <![CDATA[<h2>站内全文检索的必要性</h2> 虽然大型搜索引擎的功能已经越来越强大了，很多站点都使用了<a href="http://www.google.com/services/free.html">Google的站内检索</a>site:domain.com代替了自己的站内数据库&ldquo;全文&rdquo;检索。 但依靠GOOGLE这样的大型搜索引擎做站内检索会有以下弊端：<br />  <ul>   <li>数量有限：搜索引擎并不会深度遍历一个网站，而将网站所有的内容都索引进去，比如Google就喜欢静态网页，而且是最新更新的，而不喜欢带?的动态网页，Google甚至会定期将缺少入口的网站内容逐渐抛弃；</li>   <li>更新慢：搜索引擎针对站点的更新频率也是有一定周期的，很多内容需要一定时间后才能进入GOOGLE的索引：目前Google Dance的周期是21天左右；</li>   <li>内容不精确：搜索引擎需要通过页面内容提取技术将导航条，页头页尾等内容过滤掉，反而不如直接从后台数据库提取数据来得直接，这种摘要和排重机制是很难实现的；</li>   <li>无法控制输出：也许有更多的输出需求，按时间排序，按价格，按点击量，按类目过滤等</li> </ul> <h2>系统的搭建</h2> 下载：<br />  <a href="http://sourceforge.net/projects/weblucene/">http://sourceforge.net/projects/weblucene/</a><br /> <br /> XML数据源的导入：<br /> <br /> 只要数据源可以导出成3层的XML结构，就都可以用IndexRunner这个命令行工具导入：<br /> <br /> 比如从数据库导出：news_dump.xml<br /> &lt;?xml version=&quot;1.0&quot; encoding=&quot;GB2312&quot;?&gt;<br /> &lt;Table&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;Record&gt;<br />  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;Title&gt;标题&lt;/Title&gt;<br /> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;Author&gt;作者&lt;/Author&gt;<br /> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;Content&gt;内容&lt;/Content&gt;<br />  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;PubTime&gt;2003-06-29&lt;/PubTime&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; <br /> &nbsp;&nbsp;&nbsp; &lt;/Record&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;Record&gt;<br /> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;Title&gt;My Title&lt;/Title&gt;<br />  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;Author&gt;chedong&lt;/Author&gt;<br /> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;Content&gt;abc&lt;/Content&gt;<br /> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;PubTime&gt;2003-06-30&lt;/PubTime&gt;<br />  &nbsp;&nbsp;&nbsp; &lt;/Record&gt;<br /> &nbsp;&nbsp;&nbsp; ...<br /> &lt;/Table&gt;<br /> <br /> IndexRunner -i news_dump.xml -o c:\index -t Title,Content -n Author <br /> -i news_dump.xml:&nbsp; 以news_dump.xml为数据源<br /> -o c:\index&nbsp;&nbsp; 索引库建立在c:\index目录下<br />  索引建立Title Author Content PubTime这几个字段外，按以下规则建立索引：<br /> -t Title,Content 一个进行分词的全文索引TokenIndex：数据是Title Content这2个字段<br /> -n Author&nbsp;&nbsp;&nbsp; 一个不分词的索引：NoTokenIndex：数据源是Author这个字段。<br /> <br /> 对于RSS数据源：<br /> &lt;?xml version=&quot;1.0&quot;?&gt;<br /> &lt;rss version=&quot;0.92&quot;&gt;<br /> &lt;channel&gt;<br />  &nbsp; &lt;title&gt;Amazon: Books Arts &amp;amp; Photography&lt;/title&gt;<br /> &nbsp; &lt;link&gt;http://www.lockergnome.com/&lt;/link&gt;<br /> &nbsp; &lt;description&gt;Amazon RSS Feed&lt;/description&gt;<br /> &nbsp; &lt;lastBuildDate&gt;Sun, 29 Jun 2003 01:05:01 GMT&lt;/lastBuildDate&gt;<br />  &nbsp; &lt;docs&gt;http://www.lockergnome.com/&lt;/docs&gt;<br /> &nbsp; &lt;webMaster&gt;amazonfeed@lockergnome.com (Lockergnome RSS Generator)&lt;/webMaster&gt;<br /> &nbsp; &lt;item&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;title&gt;The Artist's Way: A Spiritual Path to Higher Creativity - $11.17&lt;/title&gt;<br />  &nbsp;&nbsp;&nbsp; &lt;link&gt;http://www.amazon.com/exec/obidos/ASIN/1585421464/lockergnomedigit/?ref=nosim&amp;amp;dev-it=D34HUVGKB34YFX&lt;/link&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;description&gt;http://www.lockergnome.com/&nbsp;&nbsp;&nbsp; &lt;/description&gt;<br /> &nbsp; &lt;/item&gt;<br /> &nbsp; ...<br />  &lt;/channel&gt;<br /> <br /> IndexRunner -i http://www.example.com/rss.xml -o c:\index -t title,description -n link&nbsp; -l&nbsp;  4<br /> -l 4 表示拿第4层节点作为字段映射，<br /> <br /> IndexRunner还提供了-a -m这两个选项：用于增量索引和批量索引优化。<br /> -a&nbsp; 增量索引，表示在原有索引的基础上扩展<br />  -m&nbsp; mergeFactor 在Lucene中mergeFactor是一个针对批量索引的优化参数，控制多少条处理完多少条记录（Document）后，写入一次索引，写入频率越高，内存使用越少，但索引速度越慢，所以在大批量数据导入时需要增大文件写入的间隔，多让索引在内存中操作。<br /> <br /> 搜索结果输出：<br /> <br /> <br /> 以下是系统设计过程中一些设计的思路：<br /> <h2>做为工业标准的XML</h2> 记得以前有关于肯德基的炸薯条断顿的报道。从这个事件报道中我们可以看到一种更高效的管理体系：对于快餐店这样全球性的企业来说，要保证各地提供的薯条品质，成本最低的方法肯定是依靠机器而不是厨师，如果要求薯条机能够处理各种形状不一的土豆，机器的复杂程度和维护成本都会很高。所以土豆必须严格符合工业标准才能让结构比较简单的薯条机生产出符合标准的薯条，因此，薯条的加工机械会严格按照土豆协会的土豆工业标准设计。高质量的原料可以大大降低后期加工设备的成本，因此从总体成本上讲还是合算的。 <p>对于软件应用开发者来说：应用和应用之间，企业和企业之间交换的数据好比就是土豆，白菜，按照严格的XML标准设计的接口作为企业之间后台数据交换的工业标准，虽然不如简单的CSV格式高效，但缺能大大简化下游工序的后期加工成本。<br /> </p>  <p>不难想象为什么处理HTML的浏览器：IE和Mozilla等浏览器软件大小都在10M以上，但一般处理XML的解析器一般都在几百K。除了没有界面外，HTML浏览器需要为太多不规范的HTML代码提供大量容错处理也是一个很重要的原因，而语法严格，规则简单的XML处理器就可以做的很简短，高效，体积越&ldquo;小&rdquo;就意味着适应性越广：这点在手机这样的硬件配置比较低的设备环境中显得尤其重要。</p> <p>虽然XML在后台数据交换方面，有着巨大的潜力。在前台表现方面，XML并不会马上代替HTML，很多通过XSLT输出的HTML仍然需要结合CSS来进行表现。XML ==XSLT==&gt; HTML + CSS。但是由于太多的网页都是用HTML做的，相信XML没有必要马上代替这些已有的机制。<br /> <br /> 此外在应用的国际化支持方面XML和Java简直是绝配：XML数据源用Java解析后是UNICODE，这样无论是日文，繁体中文还是德文的内容我们都可以在一个索引库中同时进行搜索。这样针对其他语言的支持只是设计各种语言界面的问题了。</p> <pre>      GBK          \                                       / BIG5<br />      BIG5          -  UNICODE        ====&gt;       Unicode -  GB2312<br />      SJIS          -   (XML)                     (XML)   -  SJIS<br />      ISO-8859-1   /                                       \ ISO-8859-1</pre>  使用XML的另外一个额外好处在于：开发人员一般都没有仔细理解Java的字符集（其实上是JVM的缺省file.encoding属性）受系统本地化设置的影响，基于XML的输入使得数据的字符解码过程变得透明：不用再和用户解释需要如何解码，编码数据源。不过，XML的学习成本还是比较高的，假设你HTML的学习成本是1，XML则可能为10，而XSLT的学习成本则可能高达100。<br /> <h2>传统数据库应用的全文检索加速</h2> <h3>让数据库负责精确匹配，将模糊匹配用独立的系统实现</h3> 一个站点内容积累在万级以上，站内全文检索就会是用户定位最主要的手段，而关键词检索是用户最熟悉的方法。因此基于数据库的传统WEB应用在全文检索需求还是很大的。<br /> <br /> 但是可怕的%like%数据库操作可能会吃掉数据库服务器90%以上的CPU。Oracle MSSQL等数据库服务器中数据库内置的全文检索基本上都不太适合WEB应用。而数据库另外一个的弊端在于对于条件简单的查询返回结果集非常大：数据库并不知道如何面向用户最关心的的头100条结果进行优化。根据以前的统计：头100条结果往往已经可以满足95％以上用户需求。<br /> <br /> 需要缓存设计：根据我们的经验，在应用设计中没有必要进行内置的结果缓存设计：让前台的应用服务器内置的缓存机制或者反相代理缓存服务器进行缓存就够了。<br /> <h3>数据同步策略</h3> 总体上讲，全文检索和数据库其实是2种根本不同的应用模式，全文检索系统其实往往也没有必要和数据库那么高的实时同步机制，如果按照：低更新，高缓存的模式进行设计：数据库数据到全文索引的同步过程一般都可以通过脚本定期将数据库的数据导出成XML，然后进入Lucene的全文索引。而针对原有数据记录的更新和删除，其实一般可以通过定期的重建索引解决。WebLucene其中索引部分是一个IndexRunner的命令行程序实现的。<br />  <h3>结果排序策略</h3> 站内全文索引另外一个很重要的需求是可定制的排序：按时间，按价格，按点击量&hellip;&hellip;Lucene全文索引缺省只提供了根据关键词在原文中的匹配度排序，而任何根据某个字段的值进行排序的都无法避免再次遍历数据，从而导致性能有数量级的下降（等于又是做%Like%检索），而在索引中，除了匹配度SCORE外，唯一能用来排序的就是索引记录的ID，所以一个比较高效率实现定制排序的方法时：在索引时，让进入Lucene全文的顺序对应着一定规则：比如时间，然后在搜索时，让搜索结果按照索引记录的ID进行排序（或倒排）。<br /> <h3> 搜索结果关键词标引的实现</h3> 搜索结果中关键词通过红色或者黑体字标记出来，为了能够更恰当的显示相关上下文的问题，标引是通过限制了一个扫描范围，然后根据一个分析器将指定的词流式的读取出来，然后<br /> <h2>全文检索和其他应用的集成</h2> 其实核心的是一个Lucene的XML接口：SAX方式的数据导入和DOM方式的结果输出。<br /> <br /> XML的数据源定义：<br /> 只要是能够映射成表＝》记录＝》字段这样层次结构的都可以。因此WebLucene索引的设计比较灵活，甚至可以直接用来索引RSS。<br />  <br /> XML结果定义：参考了<a href="http://www.google.com/google.dtd">Google的XML接口的设计</a><br /> <br /> 如果没有SERVLET界面，提供XML输出的DOMSearcher也可以很方便集成到各种应用系统中。<br /> <a href="http://sourceforge.net/projects/weblucene/" /><br /> <p>参考资料：</p> <p>系统设计中使用的一些模块：<br /></p><ul><li> Jakarta Lucene: <a href="http://jakarta.apache.org/lucene/">http://jakarta.apache.org/lucene/</a></li><li>Xerces / Xalan <a href="http://xml.apache.org/">http://xml.apache.org/</a><br /> </li><li>Log4j <a href="http://jakarta.apache.org/log4j/">http://jakarta.apache.org/log4j/</a><br /> </li><li>Google的XML接口定义： <a href="http://www.google.com/google.dtd">http://www.google.com/google.dtd</a></li></ul><p>其他开发人员的一些反馈和改进</p><ul><li><a target="nw" href="http://www.taoer.com/2007/06/11/update-lucene-weblucene-note/">将<strong>WebLucene</strong>中的lucene部分升级到2.1</a></li><li><a href="http://blog.donews.com/dev2dev/archive/2006/08/29/1021739.aspx">WebLucene安装实习篇&nbsp;</a></li><li><a href="http://socolddai.spaces.live.com/Blog/cns!4A9992AF63EDFDDF!235.entry">WebLucene的安装经验</a></li></ul><a href="http://socolddai.spaces.live.com/Blog/cns!4A9992AF63EDFDDF!235.entry" /><a href="http://www.ginkgotek.com/">银杏咨询： 站内搜索引擎提供商，为点评，饭统网提供了站内全文检索服务；</a> <br />]]>
   </content>
</entry>
<entry>
   <title>多服务器的日志合并统计——apache日志的cronolog轮循</title>
   <link rel="alternate" type="text/html" href="http://www.chedong.com/tech/rotate_merge_log.html" />
   <id>tag:www.chedong.com,2007:/test//10.1335</id>
   
   <published>2003-04-12T02:38:26Z</published>
   <updated>2009-01-13T02:39:12Z</updated>
   
   <summary>内容摘要：你完全不必耐心地看完下面的所有内容，因为结论无非以下2点： 1 用 cronolog 干净，安全地轮循apache“日”志 2 用 sort -m 合并排序多个日志 或者用： clfmerge合并日志 根据个人的使用经历： 1 先介绍apache日志的合并方法； 2 然后根据由此引出的问题说明日志轮循的必要性和解决方法，介绍如何通过cronolog对apache日志进行轮循； 中间有很多在设计日志合并过程中一些相关工具的使用技巧和一些尝试的失败经历…… 我相信解决以上问题的路径不止这一条途径，以下方案肯定不是最简便或者说成本最低的，希望能和大家有更多的交流。...</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[内容摘要：你完全不必耐心地看完下面的所有内容，因为结论无非以下2点：<br>
1 用 cronolog 干净，安全地轮循apache“日”志<br>
2 用 sort -m 合并排序多个日志<br>
或者用： <a href="http://www.chedong.com/blog/archives/001280.html">clfmerge合并日志</a>
<br>
根据个人的使用经历：<br>
1 先介绍apache日志的合并方法；<br>
2 然后根据由此引出的问题说明日志轮循的必要性和解决方法，介绍如何通过cronolog对apache日志进行轮循；<br>
中间有很多在设计日志合并过程中一些相关工具的使用技巧和一些尝试的失败经历……<br>
我相信解决以上问题的路径不止这一条途径，以下方案肯定不是最简便或者说成本最低的，希望能和大家有更多的交流。<br>
<br>
<br>
</p>]]>
      <![CDATA[<h2><b>多服务器日志合并统计的必要性</b></h2>
<p><b> </b>

越来越多大型的WEB服务使用DNS轮循来实现负载均衡：使用多个同样角色的服务器做前台的WEB服务，这大大方便了服务的分布规划和扩展性，但多个服务
器的分布使得日志的分析统计也变得有些麻烦。如果使用webalizer等日志分析工具对每台机器分别做日志统计：<br>
1 会对数据的汇总带来很多麻烦，比如：统计的总访问量需要将SERVER1 SERVER2...上指定月份的数字相加。<br>
2 会大大影响统计结果中唯一访客数unique visits，唯一站点数unique
sites的等指标的统计，因为这几个指标并非几台机器的代数相加。<br>
<br>
统一日志统计所带来的好处是显而易见的，但如何把所有机器的统计合并到一个统计结果里呢？<br>
首先也许会想：多个服务器能不能将日志记录到同一个远程文件里呢？我们不考虑使用远程文件系统记录日志的问题，因为带来的麻烦远比你获得的方便多的多……<br>
因此，要统计的多个服务器的日志还是：分别记录=&gt;并通过一定方式定期同步到后台=&gt;合并=&gt;后用日志分析工具来进行分析。<br>
<br>

首先，要说明为什么要合并日志：因为webalizer没有将同一天的多个日志合并的功能<br>
先后运行<br>
webalizer log1<br>
webalizer log2<br>
webalizer log3<br>
这样最后的结果是：只有log3的结果。<br>
<br>
能不能将log1&lt;&lt;log2&lt;&lt;log3简单叠加呢？<br>

因为一个日志的分析工具不是将日志一次全部读取后进行分析，而且流式的读取日志并按一定时间间隔，保存阶段性的统计结果。因此时间跨度过大（比如2条日志
间隔超过5分钟），一些日志统计工具的算法就会将前面的结果“忘掉”。因此，
log1&lt;&lt;log2&lt;&lt;log3直接文件连接的统计结果还是：只有log3的统计结果。<br>
<br>
</p>
<h2><b><b><b>多台服务</b></b>日志合并问题：把多个日志中的记录按时间排序后合并成一个文件</b></h2>
<p><b> </b> 典型的多个日志文件的时间字段是这样的：<br>
log1 log2 log3<br>
00:15:00 00:14:00 00:11:00<br>

00:16:00 00:15:00 00:12:00<br>
00:17:00 00:18:00 00:13:00<br>
00:18:00 00:19:00 00:14:00<br>
14:18:00 11:19:00 10:14:00<br>
15:18:00 17:19:00 11:14:00<br>
23:18:00 23:19:00 23:14:00<br>
<br>
日志合并必须是按时间将多个日志的交叉合并。合并后的日志应该是：<br>
00:15:00 来自log1<br>

00:15:00 来自log2<br>
00:16:00 来自log1<br>
00:17:00 来自log3<br>
00:18:00 来自log2<br>
00:19:00 来自log1<br>
....<br>
<br>
如何合并多个日志文件？<br>
下面以标准的clf格式日志（apache）为例：<br>

apche的日志格式是这样的：<br>
%h %l %u %t \"%r\" %&gt;s %b<br>
具体的例子：<br>
111.222.111.222 - - [03/Apr/2002:10:30:17 +0800] "GET /index.html
HTTP/1.1" 200 419<br>
<br>
最简单的想法是将日志一一读出来，然后按日志中的时间字段排序<br>
cat log1 log2 log3 |sort -k 4 -t " "<br>
注释：<br>
-t " ": 日志字段分割符号是空格<br>

-k 4: 按第4个字段排序，也就是：[03/Apr/2002:10:30:17 +0800] 这个字段<br>
-o log_all: 输出到log_all这个文件中<br>
<br>
但这样的效率比较低，要知道。如果一个服务已经需要使用负载均衡，其服务的单机日志条数往往都超过了千万级，大小在几百M，这样要同时对多个几百M的日志
进行排序，机器的负载可想而之……<br>
其实有一个优化的途径，要知道：即使单个日志本身已经是一个“已经按照时间排好序“的文件了，而sort对于这种文件的排序合并提供了一个优化合并算法：
使用
-m merge合并选项，<br>
因此：合并这样格式的3个日志文件log1 log2 log3并输出到log_all中比较好方法是：<br>
sort -m -t " " -k 4 -o log_all log1 log2 log3<br>
注释：<br>
-m: 使用 merge优化算法<br>

<br>
注意：合并后的日志输出最好压缩以后再发给webalizer处理<br>
有的系统能处理2G的文件，有的不能。有的程序能处理大于2G的文件，有的不能。尽量避免大于2G的文件，除非确认所有参与处理的程序和操作系统都能处理
这样的文件。所以输出后的文件如果大于2G，最好将日志gzip后再发给webalizer处理：大于2G的文件分析过程中文件系统出错的可能性比较大，
并且gzip后也能大大降低分析期间的I/O操作。<br>
<br>
日志的按时间排序合并就是这样实现的。<br>
<br>
</p>
<h2><b> 日志的轮循机制</b></h2>
<p><b> </b>
让我们关心一下数据源问题：webalizer其实是一个按月统计的工具，支持增量统计：因此对于大型的服务，我可以按天将apache的日志合并后送给
webalizer统计。WEB日志是如何按天（比如每天子夜00:00:00）截断呢？<br>

如果你每天使用crontab：每天0点准时将日志备份成access_log_yesterday<br>
mv /path/to/apache/log/access_log
/path/to/apache/log/access_log_yesterday<br>
的话：你还需要：马上运行一下：apache restart
否则：apache会因为的日志文件句柄丢失不知道将日志记录到哪里去了。这样归档每天子夜重启apache服务会受到影响。<br>
比较简便不影响服务的方法是：先复制，后清空<br>
cp /path/to/apache/log/access_log
/path/to/apache/log/access_log_yesterday<br>
echo &gt;/path/to/apache/log/access_log<br>
<br>
严肃的分析员会这样做发现一个问题：<br>
但cp不可能严格保证严格的0点截断。加入复制过程用了6秒，截断的access_log_yesterday日志中会出现复制过程到00:00:06期
间的日志。对于单个日志统计这些每天多出来几百行日志是没有问题的。但对于多个日志在跨月的1天会有一个合并的排序问题：<br>

[31/Mar/2002:59:59:59 +0800]<br>
[31/Mar/2002:23:59:59 +0800]<br>
[01/Apr/2002:00:00:00 +0800]<br>
[01/Apr/2002:00:00:00 +0800]<br>
<br>
要知道[01/Apr/2002:00:00:00
这个字段是不可以进行“跨天排序”的。因为日期中使用了dd/mm/yyyy，月份还是英文名，如果按照字母排序，很有可能是这样的结果：排序导致了日志
的错误<br>
[01/Apr/2002:00:00:00 +0800]<br>
[01/Apr/2002:00:00:00 +0800]<br>
[01/Apr/2002:00:00:00 +0800]<br>

[01/Apr/2002:00:00:00 +0800]<br>
[01/Apr/2002:00:00:00 +0800]<br>
[01/Apr/2002:00:00:00 +0800]<br>
[01/Apr/2002:00:00:00 +0800]<br>
[31/Mar/2002:59:59:59 +0800]<br>
[31/Mar/2002:59:59:59 +0800]<br>
[31/Mar/2002:23:59:59 +0800]<br>
[31/Mar/2002:59:59:59 +0800]<br>
[31/Mar/2002:23:59:59 +0800]<br>

<br>
这些跨天过程中的非正常数据对于webalizer等分析工具来说简直就好像是吃了一个臭虫一样，运行的结果是：它可能会把前一个月所有的数据都丢失！因
此这样的数据会有很多风险出现在处理上月最后一天的数据的过程中。<br>
<br>
问题的解决有几个思路：<br>
1 事后处理：<br>
。所以一个事后的处理的方法是：用grep命令在每月第1天将日志跨月的日志去掉，比如：<br>
grep -v "01/Apr" access_log_04_01 &gt; access_log_new<br>
<br>
修改SORT后的日志:所有跨天的数据去掉。也许对日志的事后处理是一个途径，虽然sort命令中有对日期排序的特殊选项
-M（注意是：大写M），可以让指定字段按照英文月份排序而非字母顺序，但对于apache日志来说，用SORT命令切分出月份字段很麻烦。（我尝试过用
"/"做分割符，并且使用“月份”
“年:时间”这两个字段排序）。虽然用一些PERL的脚本肯定可以实现，但最终我还是放弃了。这不符合系统管理员的设计原则：通用性。
并且你需要一直问自己：有没有更简单的方法呢？<br>

还有就是将日志格式改成用TIMESTAMP（象SQUID的日志就没有这个问题，它的日志本身就是使用TIMESTAMP做时间时间戳的），但我无法保
证所有的日志工具都能识别你在日期这个字段使用了特别的格式。<br>
<br>
2 优化数据源：<br>
最好的办法还是优化数据源。将数据源保证按天轮循，同一天的日志中的数据都在同一天内。这样以后你无论使用什么工具（商业的，免费的）来分析日志，都不会
因为日志复杂的预处理机制受到影响。<br>
<br>
首先可能会想到的是控制截取日志的时间：比如严格从0点开始截取日志，但在子夜前1分钟还是后一分钟开始截取是没有区别的，你仍然无法控制一个日志中有跨
2天记录的问题，而且你也无法预测日志归档过程使用的时间。<br>
因此必须要好好考虑一下使用日志轮循工具的问题，这些日志轮循工具要符合：<br>
1 不中断WEB服务：不能停apache=&gt;移动日志=&gt;重启apache<br>
2 保证同一天日志能够按天轮循：每天一个日志00:00:00-23:59:59<br>

3 不受apache重启的影响：如果apache每次重启都会生成一个新的日志是不符合要求的<br>
4 安装配置简单<br>
<br>
首先考虑了apache/bin目录下自带的一个轮循工具：rotatelogs
这个工具基本是用来按时间或按大小控制日志的，无法控制何时截断和如何按天归档。<br>
然后考虑logrotate后台服务：logrotate是一个专门对各种系统日志（syslogd，mail）进行轮循的后台服务，比如SYSTEM
LOG，但其配置比较复杂，放弃，实际上它也是对相应服务进程发出一个-HUP重启命令来实现日志的截断归档的。<br>
<br>
在apache的FAQ中，推荐了经过近2年发展已经比较成熟的一个工具cronolog：安装很简单：configure=&gt;make=&gt;
make install<br>
<br>
他的一个配置的例子会让你了解它有多么适合日志按天轮循：对httpd.conf做一个很小的修改就能实现：<br>

TransferLog "|/usr/sbin/cronolog /web/logs/%Y/%m/%d/access.log"<br>
ErrorLog "|/usr/sbin/cronolog /web/logs/%Y/%m/%d/errors.log"<br>
<br>
然后：日志将写入<br>
/web/logs/2002/12/31/access.log<br>
/web/logs/2002/12/31/errors.log<br>
午夜过后：日志将写入<br>
/web/logs/2003/01/01/access.log<br>
/web/logs/2003/01/01/errors.log<br>

而2003 2003/01 和 2003/01/01 如果不存在的话，将自动创建<br>
<br>
所以，只要你不在0点调整系统时间之类的话，日志应该是完全按天存放的（00:00:00-23:59:59），后面日志分析中：
[31/Mar/2002:15:44:59这个字段就和日期无关了，只和时间有关。<br>
<br>
测试：考虑到系统硬盘容量，决定按星期轮循日志<br>
apache配置中加入：<br>
#%w weekday<br>
TransferLog "|/usr/sbin/cronolog /path/to/apache/logs/%w/access_log"<br>
<br>
重启apache后，除了原来的CustomLog
/path/to/apche/logs/access_log继续增长外，系统log目录下新建立了
3/目录（测试是在周3），过了一会儿，我忽然发现2个日志的增长速度居然不一样！<br>

分别tail了2个日志才发现：<br>
我设置CustomLog使用的是combined格式，就是包含（扩展信息的），而TransferLog使用的是缺省日志格式，看了apache的手
册才知道，TransferLog是用配置文件中离它自己最近的一个格式作为日志格式的。我的httpd.conf里写的是：<br>
LogFormat ..... combined<br>
LogFormat ... common<br>
...<br>
CustomLog ... combined<br>
TransferLog ...<br>
<br>
所以TrasferLog日志用的是缺省格式，手册里说要让TRANSFER日志使用指定的格式需要：<br>

LogFormat "%h %l %u %t \"%r\" %&gt;s %b \"%{Referer}i\"
\"%{User-Agent}i\""<br>
TransferLog "|/usr/local/sbin/cronolog
/path/to/apache/logs/%w/access_log"<br>
<br>
重启，OK，日志格式一样了。<br>
这样的设置结果其实是同时在logs目录下分别记录2个日志access_log和%w/access_log，能不能只记录%w/下的日志那？<br>
查apache手册，更简单的方法：直接让CustomLog输出到cronolog归档日志，并且还能指定格式。<br>
CustomLog "|/usr/local/sbin/cronolog
/path/to/apache/logs/%w/access_log" combined<br>
<br>
最后是一个日志同步的问题。<br>

<br>
任务：每天凌晨找到前1天的日志，另存一个文件准备发送到服务器上。<br>
比如我要保留前1周的日志：每天复制前1天的日志到指定目录，等待日志服务器来抓取：<br>
/bin/cp -f /path/to/apache/logs/`date -v-1d +%w`/access_log
/path/for/backup/logs/access_log_yesterday<br>
<br>
在FREEBSD上使用以下命令<br>
date -v-1d +%w<br>
注释：<br>
-v-1d: 前1天，而在GNU/Linux上这个选项应该是date -d yesterday<br>
+%w: weekday，由于使用的都是标准时间函数库，所有工具中的WEEKDAY定义都是一样的 0-6 =&gt; 周日－周六<br>

<br>
注意：<br>
写到CRONTAB里的时候"%"前面需要加一个"\"转义：每天0点5分进行一次日志归档，<br>
另外一个问题就是在cront中需要用：rm -f {} ; 而不是rm -f {}\;<br>
5 0 * * * /bin/cp /path/to/logs/`date -v-1d +\%w`/access_log
/path/to/for_sync/logs/access_yesterday<br>
37 10 * * * /usr/bin/find /home/apache/logs/ -name access_log -mtime +1
-exec /bin/rm -f {} ; <br>
</p>
<p> 首次开始cronolog日志统计是周3，一周以后日志又将轮循回3/access_log<br>
但这次日志是追加到3/access_log还是重新创建一个文件呢？&gt;&gt;access_log or &gt;access_log？<br>

我测试的结果是日志将被追加：<br>
[01/Apr/2002:23:59:59 +0800]<br>
[01/Apr/2002:23:59:59 +0800]<br>
[08/Apr/2002:00:00:00 +0800]<br>
[08/Apr/2002:00:00:00 +0800]<br>
<br>
肯定是不希望每次日志还带着上周的数据的并重复统计一次的（虽然对结果没影响），而且这样%w/下的日志不是也越来越多了吗？<br>
解决方法1 把每天的cp改成mv<br>
解决方法2 每天复制完成后：删除6天以前的access_log日志<br>

find /path/to/apache/logs -name access_log -mtime +6 -exec rm -f {}\;<br>
多保留几天的日志还是有必要的：万一日志分析服务器坏了一天呢？</p>
<p>以下是把apache安装在/home/apache下每天统计的一个脚本文件：<br>
#!/bin/sh<br>
<br>
#backup old log<br>
/bin/cp -f /home/apache/logs/`date -d yesterday +%w`/access_log
/home/apache/logs/access_log_yesterday<br>
<br>
#remove old log<br>
/usr/bin/find /home/apache/logs -name access_log -mtime +6 -exec rm -f
{}\;<br>

<br>
#analysis with webalizer<br>
/usr/local/sbin/webalizer<br>
<br>
总结：<br>
1 用 cronolog 干净，安全地轮循日志<br>
2 用 sort -m 排序合并多个日志<br>
<br>
<br>
参考资料：<br>
<br>

日志分析统计工具：<br>
<a
 href="http://directory.google.com/Top/Computers/Software/Internet/Site_Management/Log_Analysis/">http://directory.google.com/Top/Computers/Software/Internet/Site_Management/Log_Analysis/</a></p>
<p>Apche的日志设置：<br>
<a href="http://httpd.apache.org/docs/mod/mod_log_config.html">http://httpd.apache.org/docs/mod/mod_log_config.html</a></p>
<p>Apache的日志轮循：<br>
<a href="http://httpd.apache.org/docs/misc/FAQ.html#rotate">http://httpd.apache.org/docs/misc/FAQ.html#rotate</a><br>
<br>
Cronolog<br>
<a href="http://www.cronolog.org">http://www.cronolog.org<br>

</a></p>
<p>Webalizer<br>
<a href="http://www.mrunix.net/webalizer/">http://www.mrunix.net/webalizer/</a><br>
Webalzer的Windows版<br>
<a href="http://www.medasys-lille.com/webalizer/">http://www.medasys-lille.com/webalizer/</a><br>
</p>
<p>AWStats的使用简介<br>
<a href="http://www.chedong.com/tech/awstats.html">http://www.chedong.com/tech/awstats.html</a></p>]]>
   </content>
</entry>
<entry>
   <title>AWStats简介：Apache/Windows IIS的日志分析工具的下载，安装，配置样例和使用（含6.9中文定义补丁）</title>
   <link rel="alternate" type="text/html" href="http://www.chedong.com/tech/awstats.html" />
   <id>tag:www.chedong.com,2003:/test//10.1277</id>
   
   <published>2003-04-09T07:45:38Z</published>
   <updated>2009-07-10T02:07:42Z</updated>
   
   <summary><![CDATA[你完全不必耐心看完所有内容：简要安装说明如下 安装 http://sourceforge.net/projects/awstats/ 下载安装包后： GNU/Linux：tar zxf awstats-version.tgz awstats的脚本和静态文件缺省都在wwwroot目录下：将cgi-bin目录下的文件都部署到 cgi-bin/目录下：/home/apache/cgi-bin/awstats/ mv awstats-version/wwwroot/cgi-bin /path/to/apache/cgi-bin/awstats 把图标等文件目录复制到WEB的HTML文件发布目录下，例如：/home/apache/htdocs/ 下发布 更多的批量更新脚本等在tools 目录下，可以一并放到cgi-bin/awstats/ 目录下 升级国内主要搜索引擎和蜘蛛定义，安装GeoIP的应用库：Chttp://www.maxmind.com/download/geoip/api/c/ 解包，编译安装perl -MCPAN -e 'install &quot;Geo::IP&quot;' 或者使用纯Perl包&nbsp; perl -MCPAN -e 'install &quot;Geo::IP::PurePerl&quot;'下载GeoIP/GeoIPCityLite包：解包并部署到awstats目录下:wget&nbsp; http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gzwget&nbsp; http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz 配置 将缺省awstats.model.conf 命名成common.conf 修改其中的一些配置选项： LoadPlugin=&quot;decodeutfkeys&quot;LoadPlugin=&quot;geoip GEOIP_STANDARD /home/apache/chedong.com/cgi-bin/awstats/GeoIP.dat&quot;LoadPlugin=&quot;geoip_city_maxmind GEOIP_STANDARD /home/apache/chedong.com/cgi-bin/awstats/GeoLiteCity.dat&quot;...]]></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 /> <strong>安装</strong><br /> http://sourceforge.net/projects/awstats/ 下载安装包后：<br /> GNU/Linux：tar zxf awstats-version.tgz<br /> awstats的脚本和静态文件缺省都在wwwroot目录下：将cgi-bin目录下的文件都部署到 cgi-bin/目录下：/home/apache/cgi-bin/awstats/ <br /> mv awstats-version/wwwroot/cgi-bin /path/to/apache/cgi-bin/awstats<br /> 把图标等文件目录复制到WEB的HTML文件发布目录下，例如：/home/apache/htdocs/ 下发布<br />  更多的批量更新脚本等在tools 目录下，可以一并放到cgi-bin/awstats/ 目录下<br /> 升级国内主要<a href="http://www.chedong.com/tech/lib.tgz">搜索引擎和蜘蛛定义</a>，安装GeoIP的应用库：C<br /><a href="http://geolite.maxmind.com/download/geoip/api/c/GeoIP.tar.gz">http://www.maxmind.com/download/geoip/api/c/</a> 解包，编译安装<br />perl -MCPAN -e 'install &quot;Geo::IP&quot;' 或者使用纯Perl包&nbsp; perl -MCPAN -e 'install &quot;Geo::IP::PurePerl&quot;'<br />下载GeoIP/GeoIPCityLite包：解包并部署到awstats目录下:<br /></p><blockquote>wget&nbsp; <a href="http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz">http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz</a><br />wget&nbsp; <a href="http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz">http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz</a><br /></blockquote><p> <strong>配置</strong><br /> 将缺省awstats.model.conf 命名成common.conf<br /> 修改其中的一些配置选项：<br /> LoadPlugin=&quot;decodeutfkeys&quot;<br />LoadPlugin=&quot;geoip GEOIP_STANDARD /home/apache/chedong.com/cgi-bin/awstats/GeoIP.dat&quot;<br />LoadPlugin=&quot;geoip_city_maxmind GEOIP_STANDARD /home/apache/chedong.com/cgi-bin/awstats/GeoLiteCity.dat&quot;<br /> <br /> 创建awstats下创建：data 目录用于统计数据输出，缺省的统计输出是按月汇总的；对于日志非常大的最好选择<a href="http://www.chedong.com/blog/archives/001293.html">按天统计输出</a>，并<a href="http://www.chedong.com/blog/archives/001452.html">修改awstats.pl: 设置LIMITFLUSH加10倍</a>；<br />$LIMITFLUSH =<br />&nbsp; <span style="font-weight: bold">50000</span>;&nbsp;&nbsp; # Nb of records in data arrays after how we need to flush data on disk<br />可以有效提高统计的速度（减少磁盘IO），并避免按月汇总数据导致的统计文件过大；</p><p>按照一下样例设置配置文件：<br /> Include &quot;common.conf&quot;<br /> LogFile=&quot;/home/apache/logs/access_log.%YYYY-24%MM-24%DD-24&quot;<br /> SiteDomain=&quot;www.chedong.com&quot;<br /> HostAliases=&quot;chedong.com&quot;<br /> DefaultFile=&quot;index.html&quot;<br /> DirData=&quot;/home/apache/cgi-bin/awstats/data/&quot; </p>]]>
      <![CDATA[<p>内容摘要：AWStats的使用简介和配置一些改进说明。很高兴看到在AWStats 6.3版本开始：中文用户基本上已经只需要将配置文件中将 LoadPlugin=&quot;decodeutfkeys&quot; 启用基本上就没有什么中文搜索引擎的统计问题了，目前增加了多个国内主要搜索引擎厂商。<a href="http://www.chedong.com/tech/lib.tgz">包含了针对国内主要搜索引擎和蜘蛛定义的补丁(解包后覆盖lib\目录下的原程序目录即可)，其中也包含了本站的样例配置文件</a></p>  <p style="font-style: italic">日志统计系统在站点的用户行为分析中扮演了重要的角色，尤其是对于来自搜索引擎的关键词 访问统计：是很有效的用户行为分析数据来源。随着互联网多年的发展，WEB日志统计工具已经越来越成熟，功能也越来越丰富。其中有很多是开放源代码的， AWStats就是其中非常优秀的一款。</p> <h2>AWStats: Advanced Web Statistics</h2> <p><a href="http://awstats.sourceforge.net/">AWStats</a>是在<a href="http://sourceforge.net/">Sourceforge</a>上发展很快的一个基于Perl的WEB日志分析工具。相对于另外一个非常优秀的开放源代码的日志分析工具<a href="http://www.webalizer.org">Webalizer</a>，AWStats的优势在于：<br /> </p> <ol>   <li>界面友好：可以根据浏览器直接调用相应语言界面（有简体中文版）<br /> 参考输出样例：<a href="http://www.chedong.com/cgi-bin/awstats/awstats.pl?config=chedong">http://www.chedong.com/cgi-bin/awstats/awstats.pl?config=chedong</a>    </li>   <li>基于Perl：并且很好的解决了跨平台问题，系统本身可以运行在GNU/Linux上或Windows上（安装了<a href="http://www.activestate.com/">ActivePerl</a>后）；分析的日志直接支持Apache格式 (combined)和IIS格式(需要修改)。Webalizer虽然也有<a href="http://linux1.netconx.de/klaus/webalizer/">Windows平台版</a>，但目前已经缺乏 维护；<br /> AWStats完全可以实现用一套系统完成对自身站点不同WEB服务器：GNU/Linux/Apache和Windows/IIS服务器的统一统计。</li>   <li>效率比较高：AWStats输出统计项目比Webalizer丰富了很多，速度仍可以达到Webalizer的1/3左右，对于一个日访问量 百万级的站点，这个速度都是足够的；<br />   </li>   <li>配置/定制方便：系统提供了足够灵活但缺省也很合理的配置规则，需要修改的缺省配置不超过3，4项就可以开始运行，而且修改和扩展的插件还是 比较多的；</li>    <li>AWStats的设计者是面向精确的&quot;Human visits&quot;设计的，因此很多搜索引擎的机器人访问都被过滤掉了，因此有可能比其他日志统计工具统计的数字要低，来自公司内部的访问也可以通过IP过滤 设置过滤掉。</li>   <li>提供了很多<a href="http://www.chedong.com/blog/archives/001073.html">扩展的参数统计</a>功能：使用ExtraXXXX系列配置生成针对具体应用的参数分析会对产品分析非常有用。<br />   </li> </ol> <p>更多与其他工具：Webalizer, analog的比较请参考：<br /> <a href="http://awstats.sourceforge.net/#COMPARISON">http://awstats.sourceforge.net/#COMPARISON<br /> </a></p> <h2>AWStats安装备忘</h2> <p>AWStats的运行模式是这样的：<br />  </p> <ol>   <li>分析日志：运行后将这样的日志统计结果归档到一个AWStats的数据库（纯文本）里；</li>   <li>然后是输出：分两种形式</li>   <ol>   </ol>   <ul>     <li>一种是通过cgi程序读取统计结果数据库输出；</li>      <li>一种是运行后台脚本将输出导出成静态文件；</li>   </ul>   <ol>   </ol> </ol> <p>以下是2个针对单个站点日志统计例子：<br /> 一个是在GNU/Linux上通过CGI方式的输出，<br /> 一个是在Windows 2000上的基于静态页面的导出<br /> </p>  <h3>下载/安装</h3> <a href="http://sourceforge.net/projects/awstats/">http://sourceforge.net/projects/awstats/</a> 下载安装包后：<br /> <p>GNU/Linux：tar zxf awstats-version.tgz<br /> awstats的脚本和静态文件缺省都在wwwroot目录下： 将cgi-bin目录下的文件都部署awstats.pl程序到/home/apache/cgi-bin/awstats/ 下<br /> mv awstats-version/wwwroot/cgi-bin /path/to/apache/cgi-bin/awstats<br /> #把图标等文件目录复制到WEB的HTML文件发布目录下：/home/apache/htdocs/ 下发布<br /> 更多的批量更新脚本等在tools 目录下，可以一并放到cgi-bin/awstats/ 目录下， </p> <p>Windows 2000：按照后台脚本模式运行，直接解包，然后移动到D:\AWStats目录下<br />  把图标icon目录复制到IIS的发布目录下：inetpub/icon<br /> </p> <h3>数据源日志格式和按天的截断规则<br /> </h3> <ol>   <li>对于Apache：日志格式好设置：设置成combined格式即可，日志截断麻烦一点：需要安装<a href="http://www.cronolog.org">cronolog</a>工具，将日志设置成按天截断：<br /> CustomLog &quot;|/usr/local/sbin/cronolog /path/to/apache/logs/access_log.%Y%m%d&quot; combined <br /> 比如：logs/access_log.20030326<br /> 日志是压缩格式，可以使用gzip -d &lt; /home/apache/logs/access_log.%YYYY-24%MM-24%DD-24.gz |  动态解压缩统计。</li>    <li>对于IIS：缺省有比较好的日志按天截断规则，但是IIS的日志格式比较不适合AWStats统计，<br /> 因此最好直接去掉所有日志字段，然后严格按照以下列表设置<br />     <ul>       <li> 日期 date</li>       <li> 时间 time</li>       <li> 客户IP地址 c-ip</li>        <li> 用户名 cs-username</li>       <li> 方法 cs-method</li>       <li> URI资源 cs-uri-stem</li>       <li> 协议状态 sc-status</li>       <li> 发送字节数 sc-bytes</li>        <li> 协议版本 cs-version</li>       <li> 用户代理 cs(User-Agent)</li>       <li> 参照 cs(Referer)</li>     </ul> 相比IIS缺省设置：<br />  减少的有：<br />      <ul>       <li> 服务器IP地址 </li>       <li> 服务器端口</li>       <li> URI查询</li>     </ul> 增加的有：<br />      <ul>       <li> 发送字节数</li>       <li> 协议版本</li>       <li> 参照&nbsp;</li>     </ul>    </li> </ol> <h3>配置文件的命名规则：awstats.sitename.conf</h3> <p>AWStats的主程序awstats.pl会自动根据站点名调用相应站点的配置文件：awstats.sitename.conf<br /> 比如：运行./awstats.pl -config=chedong 调用的就是同目录下的 awstats.chedong.conf 配置文件；<br /> 如果没有指定-config，还会找当前目录下的awstats.conf或者/etc/awstats.conf作为缺省配置文件。<br /> 所以最好把缺省的awstats.model.conf 重命名成 awstats.yoursite.conf；比如：awstats.chedong.conf，<br /> </p> <p>对于多个站点的统计，AWStats的配置文件包含功能还是非常有用的，我们可以把通用的配置放在一个文档中，然后用(5.4版本以后开始支持) Include配置将通用配置包含在各个具体配置文件的头部，然后用其他配置覆盖通用配置中的相应属性，比如：<br /> Include=&quot;common.conf&quot;<br />  LogFile=&quot;/path/to/bbs/access_log&quot;<br /> SiteName=&quot;bbs.chedong.com&quot;<br /> </p> <h3>最少的配置文件修改：LogFile SiteDomain&nbsp;LogFormat</h3> <p>对于在GNU/Linux上统计Apache日志只需修改：LogFile SiteDomain这2个选项<br /> </p> <ol>   <li>GNU/Linux LogFile=&quot;/path/to/apache/logs/access_log.%YYYY-24%MM-24%DD-24&quot;<br /> Windows 2000 LogFile=&quot;d:\iis_logs\W3SV3\ex%YY-24%MM-24%DD-24.log&quot;<br />  这个配置的意思是用24小时前的年份，月份，日期拼出的日志文件名；</li>   <li>SiteDomain=&quot;www.chedong.com&quot;<br /> 站点的名称，缺省是空的，如果为空，AWStats将拒绝运行；</li>   <li>对于统计IIS日志需要多修改一个：<br /> LogFormat=2<br /> 缺省值是1：Apache日志，2是IIS日志</li> </ol><p> 其他需要注意的事项：<br />  AWStats缺省不过滤swf文件，会把.swf算成PageView，所以如果站点上swf文件主要是广告的话最好还是要过滤掉：</p> <h3>日志分析</h3> <p>./awstats.pl -update -config=sitename -lang=cn<br /> 比如：./awstats.pl -update -config=<strong>chedong</strong><br /> 会自动调用awstats.<strong>chedong</strong>.conf这个配置文件</p> <h3>统计输出</h3> <p>GNU/Linux &nbsp;&nbsp;  http://localhost/cgi-bin/awstats/awstats.pl?config=chedong<br /> Windows 2000 http://localhost/awstats/awstats.chedong.html</p> <h3> 日志统计自动运行</h3> <p> GNU/Linux上：crontab -e: 每天8点10分运行<br /> #update awstats<br /> 10 8 * * * (cd /path/to/apache/cgi-bin/awstats/; ./awstats.pl －update -config=chedong)<br /> </p> <p>Windows 2000上：设置每天8点10分运行<br />  D:\Perl\bin\perl.exe d:\AWStats\tools\awstats_buildstaticpages.pl -update -config=chedong -lang=cn -dir=c:\inetpub\awstats\ -awstatsprog=d:\awstats\wwwroot\cgi-bin\awstats.pl<br /> </p> <h3>多站点日志统计</h3> <p>AWStats自带了一个批处理工具：tools/awstats_updateall.pl，可以批量地遍历一个目录下所有地配置文件并运行统 计。因此剩下的工作就主要是日志的同步问题了。<br /> </p> <p>针对多个站点，很多配置选项是重复的，如果每个配置文件都修改维护起来会很麻烦，AWStats从5.4版本开始提供了配置文件包含的功能，所以我们可 以配置一个通用配置，比如：common.conf</p> <p>然后其他站点的配置设置为：可以通过后面的选项覆盖和缺省不一致的配置。<br /> awstats.bbs.chedong.conf <br /> Include &quot;chedong.common.conf&quot;<br /> LogFile &quot;/path/to/bbs_log&quot;<br />  SiteName &quot;bbs.chedong.com&quot;</p> <p>awstats.www.chedong.conf<br /> Include &quot;chedong.common.conf&quot;<br /> LogFile &quot;/path/to/www_log&quot;<br /> SiteName &quot;www.chedong.com&quot;<br /> HostAliases=&quot;chedong.com&quot;&nbsp;<br /> </p> <h3>统计指标说明</h3> <ul>   <li>参观者：按来访者不重复的IP统计，一个IP代表一个参观者；</li>    <li>参观次数：一个参观者可能1天之内参观多次（比如：上午一次，下午一次），所以按一定时间内（比如：1个小时），不重复的IP数统计，参观者 的访问次数；</li>   <li>网页数：不包括图片，CSS, JavaScript文件等的纯页面访问总数，但如果一个页面使用了多个帧，每个帧都算一个页面请求；</li>   <li>文件数：来自浏览器客户端的文件请求总数，包括图片，CSS，JavaScript等，用户请求一个页面是，如果页面中包含图片等，所以对服 务器会发出多次文件请求，文件数一般远远大于文件数；</li>   <li>字节：传给客户端的数据总流量；</li>   <li>来自REFERER中的数据：日志中的参考（REFERER）字段，记录了访问相应网页之前地址，因此如果用户是通过搜索引擎的搜索结果点击 进入网站的，日志中就会有用户在相应搜索引擎的查询地址，这个地址中就可以通过解析将用户查询使用的关键词提取出来：<br /> 比如：<br />  2003-03-26 15:43:58 123.123.123.123 - GET /index.html 200 192 HTTP/1.1 Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+NT+5.0) http://www.google.com/search?q=chedong<br /> AWStats在搜索引擎的关键短语和关键词统计方面的功能还是比较完整的：可以对全世界3百多种机器爬虫进行识别，并且可以识别大部分主流国际化搜索引擎和很多地区的本地语言搜索引擎。<br />   </li> </ul> <h3>Hacking AWStats</h3> 基于地理信息的插件安装：<br /> <p>GeoIP 和 Geo::IPfree（awstats 5.5+）<br /> GeoIP和Geo::IPfree都免费的是国家/IP的影射表，比通过DNS反相解析域名得到的统计准确，而且速度快。GeoIP的API都是免费 的，缺省库是免 费的，收费的是它的数据更新服务。Geo::IPfree不仅代码是公开的，而且库数据也是公开的。<br /> </p> <p>GeoIP安装：<br />  先下载C库：<a href="http://www.maxmind.com/download/geoip/api/c/">GeoIP C</a>解包后 <br /> %./configure; make<br /> #make install<br /> <br /> 然后下载Perl库：<a href="http://www.maxmind.com/download/geoip/api/perl/">GeoIP Perl</a>解包后 <br /> %perl MakeFile.PL; make<br /> #make install<br />  </p> <p>Geo::IPfree安装：<br /> 下载<a href="http://search.cpan.org/author/GMPASSOS/Geo-IPfree-0.2/">Geo::IPfree</a>解 包后<br /> %perl Makefile<br /> %make<br /> #make install<br /> </p> <p>配置：通过在配置文件中启用GEOIP相关插件：</p><p>LoadPlugin=&quot;geoip GEOIP_STANDARD /home/apache/chedong.com/cgi-bin/awstats/GeoIP.dat&quot;<br />LoadPlugin=&quot;geoip_city_maxmind GEOIP_STANDARD /home/apache/chedong.com/cgi-bin/awstats/GeoLiteCity.dat&quot;<br /></p><p><a href="http://www.maxmind.com/">MaxMind</a>目前免费提供了GeoIP和GeoIPCityLite数据包：可以定期每个月从以下地址下载：<br /></p><blockquote>wget&nbsp; <a href="http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz">http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz</a><br /> wget&nbsp; <a href="http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz">http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz</a><br /></blockquote><p>从最近的统计来看一般为每月3日更新，此外：<a href="http://geolite.maxmind.com/download/geoip/database/">http://geolite.maxmind.com/download/geoip/database/</a>下也有CSV源文件提供；此外：利用<a href="http://www.chedong.com/blog/archives/001356.html">QQ的纯真库也能获得更详细的地理信息分布统计</a>；<a href="http://geolite.maxmind.com/download/geoip/database/"><br /></a></p>   参考资料：<br />   <ul><li><a href="http://directory.google.com/Top/Computers/Software/Internet/Site_Management/Log_Analysis/">AWStats开源项目： http://awstats.sourceforge.net/</a></li><li><a href="http://directory.google.com/Top/Computers/Software/Internet/Site_Management/Log_Analysis/">Webalizer开源项目：http://www.webalizer.org/<br /></a></li><li><a href="http://directory.google.com/Top/Computers/Software/Internet/Site_Management/Log_Analysis/">日 志分析工具：directory.google.com/Top/Computers/Software/Internet/Site_Management/Log_Analysis/</a><br /> </li><li><a href="http://directory.google.com/Top/Computers/Software/Internet/Site_Management/Log_Analysis/Commercial/">商 业日志统计/分析工具： directory.google.com/Top/Computers/Software/Internet/Site_Management/Log_Analysis/Commercial/</a><a href="http://directory.google.com/Top/Computers/Software/Internet/Site_Management/Log_Analysis/Commercial/"><br /> </a></li><li><a href="http://www.chedong.com/tech/rotate_merge_log.html">多站点的日志合并：www.chedong.com/tech/rotate_merge_log.html</a><br /> </li><li><a href="http://www.chedong.com/tech/google.html">日志统计对于分析搜索引擎对站点的影响具 有非常重要的意义：www.chedong.com/tech/google.html</a></li><li><a href="http://awstats.sourceforge.net/awstats_contrib.html">AWStats插件说明：awstats.sourceforge.net/awstats_contrib.html</a></li></ul>]]>
   </content>
</entry>
<entry>
   <title>基于Google的学习过程</title>
   <link rel="alternate" type="text/html" href="http://www.chedong.com/tech/study.html" />
   <id>tag:www.chedong.com,2003:/test//10.1319</id>
   
   <published>2003-04-06T08:41:58Z</published>
   <updated>2007-04-12T02:42:31Z</updated>
   
   <summary>内容摘要： Google的使用如此重要， O&apos;Reilly有本专门的书介绍了如何优化网站面向Google的设计，和使用Google的一些技巧： http://www.oreilly.com/catalog/googlehks/ 这里我很想把以前遇到类似问题时在Google上寻找资料的思路和大家分享一下：...</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>内容摘要：
</p>
<p><a href="http://www.oreilly.com/catalog/googlehks/">Google的使用如此重要，
O'Reilly有本专门的书介绍了如何优化网站面向Google的设计，和使用Google的一些技巧：<br>
http://www.oreilly.com/catalog/googlehks/</a> 这里我很想把以前遇到类似问题时在Google上寻找资料的思路和大家分享一下：</p>

]]>
      <![CDATA[<h2>足够“多”的特征关键词是快速定位的关键</h2>
<p><br>
有朋友问我：在<a href="http://www.chedong.com/tech/resin.html">比较慢的机器上Resin不能自动
启动问题</a>我是怎么找到在“启动脚本中加入15秒的延迟”这个解决方法的。我当时
遇到这个问题后：首先就是把错误日志中的"Can't connect to parent"字样复制下来，然后在google上查：resin2
"Can't connect to
parent"，从Google找到的资料大部分在Resin的BUG跟踪报告，FAQ和邮件列表中。虽然这些文档中没有给出一个比较直接的答案，但从中
我获得了大量的相关信息，从而方便我对问题的分析。整个查找/解决过程大约用了10个小时左右。<br>
<br>
如果用户理解了使用更多的关键词可以更快的定位到所需要的信息这一点的话，那么每次查询时用户使用的关键词个数就反映了用户的搜索引擎使用水平，根据在1997年，英语国家的用户平均每次上网查询键入2.1个单词，欧洲其他国家为1.5个单词；到1999年，英语国家是2.7个单词，欧洲国家是2个单词。英语国家用户的经验值要领先其他国家将近1年半的时间。中文搜索引擎也将经历一个用户经验值逐渐提高的过程。
<img src="http://www.pcworld.com.cn/2000/back_issues/2046/pics/004614_01_02.jpg" />
<br>从中我们可以想象在互联网资源的使用水平上中国和国际先进水平的差距。<br>
</p>
<h2>提高搜索结果质量的途径：使用英文专业术语、文件类型过滤、专业站点站内搜索</h2>
<p>2000年1月，Excite公司的科学家对全球约6.4亿的Internet网页进行了语言认证，发现其中英文信息内容占了71%，而日文是6.82%、德文是5.08%、法文是 1.75%、中文则为1.52%。如此丰富多彩的英文海量数据库，势必吸引着英语国家的上网用户不断应用搜索引擎去寻找那些有价值的信息内容。使用英文专业术语：<span style="font-weight: bold;">学会把自己的问题翻译成英文后再查</span>最近一次经历是找一个Linux应用的安装文档，但用中文关键词搜出的内容大部分很多都很旧，甚至有基于RedHat5.2的，而且绝大部分只是的把台湾开发人员写的繁体板HOWTO转成了简体中文，此外，由于一些计算机名次中文名称的翻译不一致也限制了搜索结果的数量和质量。所以目前来说，质量比较高的仍然基于是相
应领域英文关键词的搜索。比如，我在解决Perl<a
 href="http://www.chedong.com/tech/indent_tools.html">源代码格式美化</a>的过程中学到了
indent，pretty
print和source code beatufier这些术语。通过这些关键词，也方便我找到了其他开发语言的代码格式美化工具。<br>

</p>
<p>文件类型过滤：<br>
Google有对PDF, Word(Power Point, Excel),
PS文档的索引能力，由于这种文档的内容比一般的HTML经过了更多的整理，学术价值一般比较高，所以这些类型的文档天生就比一般的HTML类型的文档
PageRank要高。可以通过"filetype:pdf
keywords"这种格式过滤返回结果的文件类型，从而提高搜索结果的质量。 </p>
<p>利用站内搜索减小搜索范围：<br>
如果某个站点的结果数很多，Google会类聚成2条，并可以通过“www.example.com
站内的其它相关信息”执行站内检索，在查询的命令中其实就是"site:www.example.com
keywords"，所以很多时候可以进一步通过站内检索将搜索结果限制在某些专业站点的范围内，这样很多问题的资料往往可以从其官方站点的FAQ或邮件
列表HTML归档中查到。<br>
</p>
<p>此外Google本身也有按操作系统分类的主题搜索入口：<br>
<a href="http://www.google.com/linux">http://www.google.com/linux</a><br>
<a href="http://www.google.com/bsd"> http://www.google.com/bsd</a><br>

<a href="http://www.google.com/mac"> http://www.google.com/mac</a><br>
<a href="http://www.google.com/microsoft">http://www.google.com/microsoft</a><br>
</p>
<p>我的猜测：Google其实是针对有相应内容的WEB站点根据其服务器进行了类聚，要知道关于Office的内容如果跑在Linux服务器的
Apache上那么很有可能是OpenOffice，而关于Office
2000的文档项目肯定是跑在Windows服务器的IIS上的多。 </p>
<h2>BUG反馈/改进意见也是一种非常有价值的劳动<br>
</h2>
<p>
首先，如果发现了问题一定要进行主动的反馈：有朋友问我说他以前早就遇到过类似的问题，说明Resin在CPU比较慢的机器上自动启动这个问题应该是比较
普遍了，但为什么一致没有作为BUG提交上去呢？<br>
<br>
其次，如果找到了解决方法，千万不要为自己的一点小技巧沾沾自喜，像在<a
 href="http://www-900.ibm.com/developerWorks/cn/java/java_chinese/index.shtml">Java
编程技术中汉字问题的分析及解决</a>这篇文章中提到的那个的高手那样，虽然他自己知道了通过Hacking
Servert包的源文件解决中文字符集问题的方法，如果这真是一个正确的思路为什么不作为一个议程直接提交给JCP呢？<br>

<br>
所以我在找到解决Resin自动启动这个问题以后，在相应的BUG跟踪报告中提交了自己的方法，如果以后的版本中有了改进，大家安装使用中可以少考虑一个
问题不是更好吗。（虽然这个方法最后没有被采纳），有时候在反馈过程中你也许会发现让别人接受你的建议其实更难。尤其在中文支持问题上：但如果中文用户自
己不主动反馈，以后很多的设计中就会继续忽略中文用户的一些特殊需求。</p>
<p>事实上无论是BUG提交还是改进意见，对于软件的进步都是一种非常有价值的。虽然目前国内还没有很多人直接参与开源软件的开发，但通过以上这些方式
积极的参与也是在为开源软件加油。<br>
</p>
<p>更主动的反馈莫过于像Blogger一样的主动表达：把你的理解和想法通过互联网传播出去，由于在表达和交流过程中同时你也总结提炼了自己的思想，
所以<a href="http://www.cnblog.org/">“教授他人其实正是一个非常好的学习过程”</a>。<br>
</p>
<h2>GNU的“工具箱”哲学：问题的分解<br>
</h2>
虽然常常发现自己碰到的很多问题在国外几年前就有人遇到过了，而且往往能通过Google找到大量相关资源。而且类似需求非常多的话，往往还会有很多
Open
Source的解决方案发布在<a href="http://sourceforge.net">SourceForge.net</a> <a
 href="http://www.apache.org">Apache.org</a>上。<br>

<br>
但也不要指望所有问题都能够直接在互联网上找到答案，因为复杂问题本身的解决有可能利用其他一些工具组合解决完成的。比如：我在解决<a
 href="http://www.chedong.com/tech/rotate_merge_log.html">多台服务器之间的日志合并统计</a>过
程中找到的Apache的日志轮循工具cronolog，在<a
 href="http://www.chedong.com/tech/oe2html.html">OutLook
Express邮件的HTML归档</a>过程中找到的mbx2mbox+mhonarc，以及在<a
 href="http://www.chedong.com/tech/cvs_card.html">CVS的常用工具整理</a>过程中找到的大量
优秀应用等。<br>
<p>GNU很推崇“工具箱”哲学：因为很多复杂的问题都可以通过几个更简单的工具通过一定的组合加以解决的。而Perl往往就是粘合这些优秀工具的“胶
水语言”。这也是为什么Perl（或者说Perl的哲学）是任何一个程序员都因该学习并掌握的语言。<br>
</p>
如果一个问题在Google上也找不到，有时候反思一下是不是自身需求本身的问题，因为只有合理的需求是发展的源动力：如果你发现提出需求目前很多系统中
不支持，说明我们对其设计目标理解不够深入或者对问题的复杂度缺乏正确的估计造成的。比如：MySQL早期版本中没有外键和事务处理的支持，CVS没有文
件的锁定机制，但事实上经过很长时间的实践证明：这些功能并非必需，而且没有这些功能系统也是“够用”的，而且是高效的。<br>
<p> </p>
<h2>总结</h2>

<ol>
  <li>毕竟搜索引擎只是帮助我们把“模糊的”人类语言转换成立了计算机比较擅长的“精确”匹配，因此往往需要使用一些真正能够帮助去其他信息区分开
的特征关键词（不仅是多）才能够把自己真正需要的资源比较高效的提炼出来；</li>
  <li>而返回的结果不可能达到非常完美的程度，所以有时候除了一些技巧外，还是需要我们自己从头几十条比较相关的结果中进行一下归纳总结。“搜索=
=&gt;总结==&gt;再搜索……”，我想基于搜索引擎的学习基本上就是这么一个不断提炼过程吧；</li>
  <li>如果直接找不到问题的答案就想办法把问题分解，如果还找不到，就反思一下自己的需求是否合理；<br>
  </li>
  <li>把自己的经验通过互联网加以总结，反馈和推广，网志Weblog是一个不错的手段，善于把你的观点共享给别人；<br>

  </li>
</ol>
<p></p>
<p>相关资源：</p>
<p>Google搜索帮助<a href="http://www.google.com/help/"><br>
http://www.google.com/help/</a></p>
<p>NEC Research Institute CiteSeer<br>
<a href="http://citeseer.nj.nec.com">http://citeseer.nj.nec.com</a></p>
<p>The Apache Software Foundation<a href="http://www.apache.org/"><br>
http://www.apache.org/</a></p>

<p><a href="http://www.gnu.org">GNU项目</a><br>http://www.gnu.org</p>
<p>各种开源项目资源<br>
<a href="http://sourceforge.net">http://sourceforge.net<br>
http://freshmeat.net</a><br>
</p>]]>
   </content>
</entry>
<entry>
   <title>内容管理系统(CMS)的设计和选型</title>
   <link rel="alternate" type="text/html" href="http://www.chedong.com/tech/cms.html" />
   <id>tag:www.chedong.com,2003:/test//10.1325</id>
   
   <published>2003-03-06T10:05:51Z</published>
   <updated>2007-04-12T02:42:31Z</updated>
   
   <summary>内容摘要： 内容管理系统概述 内容管理系统的选型 广告管理系统的选型 论坛/社区系统的选型 所见即所得编辑器的选型 图片上传和文件管理组件...</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>
</p>
<ul>
  <li><a href="#intro">内容管理系统概述</a></li>
  <li><a href="#cms">内容管理系统的选型</a></li>
  <li><a href="#ads">广告管理系统的选型</a></li>
  <li><a href="#bbs">论坛/社区系统的选型</a><br>
  </li>

  <li><a href="#wysiwyg">所见即所得编辑器的选型</a><br>
  </li>
  <li><a href="#upload">图片上传和文件管理组件</a><br>
  </li>
</ul>
]]>
      <![CDATA[<h2><a name="intro"></a>内容管理系统概述</h2>
<br>
内容管理系统是一个很泛的概念：从商业门户网站的新闻系统到个人的Weblog都可以称作发布系统。<br>
<ul>

  <li>框架型：本身不包含任何应用实现，只是提供了底层框架，具体应用需要一定的二次开发，比如Cocoon，Vignette；</li>
  <li>应用型：本身是一个面向具体类型的应用实现，已经包含了新闻/评论管理，投票，论坛，WIKI等一些子系统。比如：<a
 href="http://www.postnuke.com">postNuke</a> <a
 href="http://www.xoops.org">xoops</a>等；<br>
  </li>
</ul>
<p>但无论如何，在发布系统选型之前，首先了解自己的实际需求是最重要的：想根据现成系统将自己的需求硬往上照搬是非常不可取的。访问量，权限控制和各
种功能需求。每个模块和功能自己都比较清晰一点以后，再去网上找找类似的实现：你会发现其实每个环节到目前上都有比较成熟的实现了，而且还在不断完善和发
展中，如果没有：你的需求太特殊，或者可以尝试分解成更小的系统组合实现。<br>
</p>
<p>内容管理系统被分离成以下几个层面：各个层面优先考虑的需求不同<br>

</p>
<ol>
  <li>后台业务子系统管理（管理优先：内容管理）：新闻录入系统，BBS论坛子系统，全文检索子系统等，针对不同系统的方便管理者的内容录入：所见
即所得的编辑管理界面等，清晰的业务逻辑：各种子系统的权限控制机制等；</li>
  <li>Portal系统（表现优先：模板管理）：大部分最终的输出页面：网站首页，子频道/专题页，新闻详情页一般就是各种后台子系统模块的各种组
合，这种发布组合逻辑是非常丰富的，Portal系统就是负责以上这些后台子系统的组合表现管理；</li>
  <li>前台发布（效率优先：发布管理）：面向最终用户的缓存发布，和搜索引擎spider的URL设计等……</li>
</ol>
内容管理和表现的分离：很多成套的CMS系统没有把后台各种子系统和Portal分离开设计，以至于在Portal层的模板表现管理和新闻子系统的内容管
理逻辑混合在一起，甚至和BBS等子系统的管理都耦合的非常高，整个系统会显得非常庞杂。而且这样的系统各个子系统捆绑的比较死，如果后台的模块很难改
变。但是如果把后台各种子系统内容管理逻辑和前台的表现/发布分离后，Portal和后台各个子系统之间只是数据传递的关系：Portal只决定后台各个
子系统数据的取舍和表现，而后台的各个子系统也都非常容易插拔。<br>
<br>
内容管理和数据分发的分离：需要要Portal系统设计的时候注意<a
 href="http://www.chedong.com/tech/cache.html">可缓存性（Cache
Friendly）性设计</a>：CMS后台管理和发布机制，本身不要过多考虑“效率”问题，只要最终页面输出设计的比较Cacheable，效率问题
可通
过更前端专门的缓存服务器解决。<br>

<br>
此外，就是除了面向最终浏览器用户外，还要注意面向<a
 href="http://www.chedong.com/tech/google_url.html">搜索引擎友好(Search
engine Friendly)的URL设计</a>：
通过URL
REWRITE转向或基于PATH_INFO的参数解析使得动态网页在链接（URI）形式上更像静态的目录结构，方便网站内容被搜索引擎收录；<br>
<br>
<pre>---------------    ---------------     ---------------                    <br>|新闻管理子系统|   | BBS论坛子系统|    | 商城子系统  |                    <br>---------------    ---------------     ---------------                    <br>      |       \     /    |     \           /   内                         <br>      |        ----------|---   \         /    容   &lt;== 业务子系统（零件生产）<br>      |           /      |   \   \       /     管                         <br>    ---------------      |    ---------------  理                         <br>    |专题制作子系统|     |    |全文检索子系统|                            <br>    ---------------      |    ---------------                             <br>                 \       |          /                                     <br>-------------------------|---------------------------------------------   <br>                   \     |        /            频                         <br>                   ---------------             道   &lt;== Portal系统（产品组装）<br>                   | Portal 系统 |             管                         <br>                   ---------------             理                         <br>                         |                                                <br>-------------------------|---------------------------------------------   <br>                         |                     前                         <br>                         |                     台   &lt;== 发布系统（分发代理）  <br>                  ---------------              发                         <br>                  |前台发布系统 |              布                         <br>                  ---------------                                         <br>                    /        \                                            <br>                   /          \                                           <br>      ---------------      ---------------                                <br>      | 用户浏览器   |     |Search Engine|                                <br>      ---------------      ---------------                                <br><br></pre>

这里，我把在内容发布系统选型中找到的一些资料总结如下：
<ol>
</ol>
<p> </p>
<h2><a name="cms"></a>内容管理系统的选型</h2>
<p> </p>
<p>关键词：CMS Content Manage System<br>
</p>
<p>CMS行业研究<br>
<a href="http://www.cmswatch.com">http://www.cmswatch.com</a><br>
<a href="http://www.cmsreview.com">http://www.cmsreview.com</a><br>

<a href="http://www.cmsinfo.org">http://www.cmsinfo.org</a><br>
</p>
CMS讨论邮件列表<br>
<a href="http://www.cms-list.org">http://www.cms-list.org</a>
<p>商业软件和开源项目列表：<br>
<a
 href="http://directory.google.com/Top/Computers/Software/Internet/Site_Management/Content_Management/">http://directory.google.com/Top/Computers/Software/Internet/Site_Management/Content_Management/</a><br>
</p>
<p>推荐：基于XML的发布框架<br>
<a href="http://cocoon.apache.org/">http://cocoon.apache.org/</a><br>
</p>

<p>具体实现复杂程度可能会根据需求的不同而不同，但越是大型的系统越是需要分工：将内容（数据），表现（模板）和应用逻辑（程序）尽可能分离和对这3
者的管理。<br>
</p>
<p>Portal---门户系统 <br>
Open source Projects: <br>
<a href="http://jportlet.sourceforge.net/">http://jportlet.sourceforge.net/</a>
<br>
Apache Software Foundation: Jakarta JetSpeed 1.3<br>
JetSpeed home page: <a
 href="http://jakarta.apache.org/jetspeed/site/index.html">http://jakarta.apache.org/jetspeed/site/index.html</a>
<br>
JetSpeed Portlet API: <a
 href="http://cvs.apache.org/viewcvs/jakarta-jetspeed/proposals/portletAPI/">http://cvs.apache.org/viewcvs/jakarta-jetspeed/proposals/portletAPI/</a><br>

<a href="http://www.liferay.com/home/index.jsp">http://www.liferay.com/home/index.jsp</a>
<br>
<a href="http://basicportal.com/">http://basicPortal.com/</a> <br>
<a href="http://www.jahia.org/">http://www.jahia.org/</a> <br>
<a href="http://jporta.sourceforge.net/">http://jporta.sourceforge.net/</a>
<br>
<br>
商业软件：<br>
BEA WebLogic Portal - <a
 href="http://edocs.bea.com/wlp/docs81/javadoc/com/bea/portal/model/Portlet.html">http://edocs.bea.com/wlp/docs81/javadoc/com/bea/Portal/model/Portlet.html</a>

<br>
IBM Websphere Portal - <a
 href="http://www.software.ibm.com/wsdd/zones/portal/">http://www.software.ibm.com/wsdd/zones/Portal/</a>
<br>
Oracle Portal Developer Kit - <a href="http://portalstudio.oracle.com/">http://Portalstudio.oracle.com/</a>
<br>
<br>
其它: <br>
PSML - <a href="http://jakarta.apache.org/jetspeed/site/psml.html">http://jakarta.apache.org/jetspeed/site/psml.html</a><br>
BEA: Web Logic Portal 4.0 <a
 href="http://www.bea.com/products/weblogic/portal/index.shtml">http://www.bea.com/products/weblogic/Portal/index.shtml</a><br>

IBM: WebSphere Portal 2.1 <a
 href="http://www-4.ibm.com/software/webservers/portal/">http://www-4.ibm.com/software/webservers/Portal/</a>
<br>
iPlanet: iPlanet Portal Server 3.0 <a
 href="http://www.iplanet.com/products/iplanet_portal/home_portal.html">http://www.iplanet.com/products/iplanet_Portal/home_Portal.html</a><br>
Oracle: Oracle 9i Portal <a
 href="http://www.oracle.com/ip/deploy/ias/portal/index.html">http://www.oracle.com/ip/deploy/ias/Portal/index.html</a><br>
SAP Portal: <a href="http://www.iviewstudio.com">http://www.iviewstudio.com</a><br>
Epicentric Portal: <a
 href="http://www.epicentric.com/solutions/products/efs/">http://www.epicentric.com/solutions/products/efs/</a><br>
<br>

参考：<br>
<a href="http://www.waferproject.org/index.html">Wafer：Java开发框架研究</a><br>
http://www.waferproject.org/index.html<br>
<br>
<a href="http://udoo.51.net/mt/archives/000011.html">门户(Portal)系统相关开发框架：</a><br>
http://udoo.51.net/mt/archives/000011.html<br>
</p>
<h2><a name="ads"></a>广告管理系统 </h2>
<p>关键词：ad server</p>
<p>广告系统和内容的分离，可以大大降低系统之间的关联度。<br>

&nbsp;<br>
专业行业研究网站：<br>
<a href="http://adres.internet.com/">http://adres.internet.com</a><br>
<br>
相关厂商和开源项目：<br>
<a
 href="http://directory.google.com/Top/Computers/Programming/Languages/PHP/Scripts/Ad_Management/?il=1">http://directory.google.com/Top/Computers/Programming/Languages/PHP/Scripts/Ad_Management/?il=1</a><br>
<a
 href="http://directory.google.com/Top/Computers/Software/Internet/Servers/Advertising/?tc=1">http://directory.google.com/Top/Computers/Software/Internet/Servers/Advertising/?tc=1</a><br>
<a href="http://www.jspin.com/home/apps/admanage?cob=winedit">http://www.jspin.com/home/apps/admanage?cob=winedit</a><br>
<a href="http://www.scriptdex.com/dex/php_ad_management.shtml">http://www.scriptdex.com/dex/php_ad_management.shtml</a><br>
</p>

<p>推荐：<br>
<a href="http://www.phpadsnew.com/">http://www.phpadsnew.com/</a>
功能性比较强 <br>
<a href="http://oasis.sourceforge.net/">http://oasis.sourceforge.net/</a>
免费 基于日志记录和定期导入MYSQL统计，可以负载50万请求/每小时 以上<br>
<br>
如果看重广告的第3方特性，可以选择第三方服务：<br>
<a href="http://www.doubleclick.net/">http://www.doubleclick.net/</a><br>
<a href="http://www.allyes.com/">http://www.allyes.com/</a><br>

</p>
<h2><a name="bbs"></a>论坛/社区系统 </h2>
关键词： BBS FORUM<br>
<br>
论坛软件介绍：<br>
<a
 href="http://directory.google.com/Top/Computers/Internet/Web_Design_and_Development/Message_Boards/">http://directory.google.com/Top/Computers/Internet/Web_Design_and_Development/Message_Boards/</a><br>
<br>
推荐：<br>
<a href="http://www.phpBB.com">http://www.phpBB.com</a> PHP + MySQL
open source<br>

<a href="http://www.vbulletin.com/order/">http://www.vbulletin.com/order/</a>
PHP + MySQL&nbsp; 有付费的商业支持85－160$<br>
<br>
<a href="http://www.jivesoftware.com/products/pricing.jsp">http://www.jivesoftware.com/products/pricing.jsp</a>
商业论坛系统，1000$－2500$ 有知识库扩展应用<br>
<a href="http://yazd.yasna.com/features.jsp">http://yazd.yasna.com/features.jsp</a>
基于 Java<br>
<h2><a name="wysiwyg"></a>所见即所得（WYSIWYG）编辑器</h2>

在内容的录入管理方面，所见即所得是比较重要的，这样可以大大简化对系统中布局排版的需求。<br>
基于浏览器的WYSIWYG（所见即所得）编辑器是CMS设计中，编辑工具的主要考虑方面。目前主要是通过JAVASCRIPT调用IE或其他浏览器的内
置方法实现。其中基于IE5.5浏览器的实现最为简洁。这里有一个完整的例子：<br>
<a href="http://www.devarticles.com/c/a/HTML/Building-a-WYSIWYG-HTML-Editor-Part-1/">Building a WYSIWYG HTML Editor Part 1/2</a><br>
<a href="http://www.devarticles.com/c/a/HTML/Building-a-WYSIWYG-HTML-Editor-Part-2/">Building a WYSIWYG HTML Editor Part 2/2</a><br>
<br>
主要功能：<br>
<ul>
  <li>能够通过JAVASCRIPT实现的基本功能：加粗，斜体字，居中，添加链接，添加图片，模式切换：HTML和文本模式的切换，</li>
  <li>Word垃圾代码过滤</li>

  <li>图片上载接口：图片上载最好通过其他独立模块实现。</li>
</ul>
选型指标：<br>
<ul>
  <li>不依赖服务器端代码：只通过JAVASCRIPT或客户端控件实现代码，可以保证以后系统迁移的方便。</li>
  <li>WORD垃圾代码过滤</li>
</ul>
可视化编辑器大全：<br>
<a href="http://www.bris.ac.uk/is/projects/cms/ttw/ttw.html">http://www.bris.ac.uk/is/projects/cms/ttw/ttw.html</a><br>

<br>
推荐：<br>
<a href="http://www.aine.be/aynhtml/">http://www.aine.be/aynhtml/</a><br>
<br>
<h2><a name="upload"></a>图片/文件上传组建</h2>
图片和文件等非结构化数据还是分别使用另外的服务解决比较好。这样可以大大简化CMS本身的复杂程度。<br>
<br>
推荐：<br>
文件上传：<br>
<a href="http://jakarta.apache.org/commons/">Apache Commons项目</a><br>

http://jakarta.apache.org/commons/<br>
<br>
<a href="http://rsb.info.nih.gov/ij/">ImageJ：图片处理缩略图生成和水印等</a><br>
http://rsb.info.nih.gov/ij/<br>
<br>
关于Blog系统的选型，目前主流的基于PHP的包括：<br>
· Nucleus 3.0 <a href="http://www.nucleuscms.org">www.nucleuscms.org</a><br>
· pmachine 2.3 <a href="http://www.pmachine.com">www.pmachine.com</a><br>
· b2evolution 0.9.0.3 <a href="http://www.b2evolution.net">www.b2evolution.net</a><br>

· Serendipity 0.6 <a href="http://www.s9y.org">www.s9y.org</a><br>
· WordPress 1.2 <a href="http://www.wordpress.org">www.wordpress.org</a><br>
· bBlog 0.7.3 <a href="http://www.bblog.com">www.bblog.com</a><br>
· pLog 0.3.1 <a href="http://www.plogworld.org">www.plogworld.org</a><br>
· Simplog .9 <a href="http://www.simplog.org">www.simplog.org</a><br>
· Textpattern 1.18a <a href="http://www.textpattern.com">www.textpattern.com</a>
]]>
   </content>
</entry>

</feed>
