<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>robbin的自言自语</title>
    <description>范凯，JavaEye创办者</description>
    <link>http://robbin.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
          <item>
        <title>Spring Application Platform - SpringSource的应用服务器发布</title>
        <author>robbin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://robbin.javaeye.com">robbin</a>&nbsp;
                    链接：<a href="http://robbin.javaeye.com/blog/189825" style="color:red;">http://robbin.javaeye.com/blog/189825</a>&nbsp;
          发表时间: 2008年05月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          2008年的5.1劳动节，SpringSource发布了策划已久的开源应用服务器－SpringSource Application Platform。JavaEye的新闻频道也有报道：<br /><br /><a href="http://www.javaeye.com/news/2113" target="_blank">SpringSource 宣布发布 SpringSource Application Platform Beta</a><br /><br />总体来说，Spring的Application Platform就是一个根据Rod Johnson自己对于Java企业应用开发的理解，自行制订了一套应用服务器的标准，并且开发了这样一个专用的应用服务器出来。但是Spring的应用服务器也有自己的一些特色，让我们简单看看：<br /><br /><img src="http://blog.springsource.com/main/wp-content/uploads/2008/04/architecture.png" /><br /><br />这是Spring应用服务器的结构图。他的底层是用Equinox这个OSGi框架来搭建的，我们知道Equinox为底层框架搭建的应用软件还有Eclipse，他的特点是高度的模块化，可定制化和在线的部署和卸载，以及模块的版本管理、依赖管理等功能。<br /><br />Spring在Equinox的基础之上开发了DMK这样一个框架，即动态模块内核(Dynamic Module Kernel)，DMK封装了Equinox的很多底层操作，向上提供了更加方便的API和管理平台。<br /><br />在DMK之上，所有的功能统统以模块的方式运行在DMK之上，例如Tomcat就是以模块的方式部署在Spring应用服务器上，此外还集成了应用发布模块、系统管理模块等等。所有的模块都可以以标准的方式部署到Spring应用服务器上面，具体模块的信息，可以看看Spring应用服务器的repository目录下面的文件。<br /><br />Spring应用服务器给我的感觉和JBoss应用服务器很像。JBoss也是类似这样的结构，JBoss最核心的底层是JBoss Microkernel，即微内核，这个MicroKernel提供了JMX的接口，而JBoss应用服务器的所有其他功能，都是通过标准的JMX来插入到MicroKernel之上的，例如Tomcat、Hibernate3、EJB、Transaction，DB Pool等等，都是标准的SAR模块包。<br /><br />他们之间比较大的不同在于Spring应用服务器底层使用的是OSGi结构来进行模块化的管理和部署，而JBoss使用的是基于JMX的模块化管理。使用OSGi的一大好处就是可以在线的热部署和卸载，并且可以提供良好的模块版本管理。<br /><br />Spring应用服务器我从我初步的接触来看，我觉得有一些比较有特色的地方：<br /><br />一、轻量级和模块化<br /><br />Spring应用服务器本质上就是基于Equinox的Spring DMK，这DMK本身是很小的，在DMK上面可以部署各种各样的功能模块来扩展应用服务器的功能，模块化程度非常高，内核本身是很轻量级的。<br /><br />看Spring Applicaiton Platform自己的文档上面说，如果去掉Tomcat模块的话，启动应用服务器只占15MB内存(能用来干啥？)，其实目前Spring应用服务器并没有提供很多功能模块上来，只是一个web模块、一个部署模块和一个管理监控模块。但是计划在2.0版本增加更多的模块、例如群集支持模块、SOA模块等等。<br /><br />二、在线的热部署和卸载<br /><br />得益于Equinox，可以在服务器运行期增加功能模块、部署新的Web应用，或者更新、卸载Web应用，所有的这些操作都可以Online进行。这恐怕是比传统的Java应用服务器最领先的特色了。<br /><br />三、库的版本管理和依赖<br /><br />jar包的版本冲突和依赖是传统Java应用很头疼的一个方面，Spring应用服务器提出了自己的一套库版本管理和库依赖管理的机制，具体的原理我还没有仔细的研究，貌似也是利用了OSGi的功能。<br /><br />总结：<br /><br />Spring应用服务器和Spring框架并没有什么直接的关系。你用其他框架开发的Web应用也可以部署到spring应用服务器上来，只是Spring应用服务器提供了很多可能你觉得不错的功能，吸引你使用spring的应用服务器，而不是tomcat或者jboss。但是Spring应用服务器并不符合Java EE的标准，因此可以看成是一个完全无视JCP的应用服务器，也是Rod Johnson大胆甩开标准进军应用服务器市场的尝试。
          <br/>
          <span style="color:red;">
            <a href="http://robbin.javaeye.com/blog/189825#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 05 May 2008 17:04:49 +0800</pubDate>
        <link>http://robbin.javaeye.com/blog/189825</link>
        <guid>http://robbin.javaeye.com/blog/189825</guid>
      </item>
          <item>
        <title>mod_rails尝鲜</title>
        <author>robbin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://robbin.javaeye.com">robbin</a>&nbsp;
                    链接：<a href="http://robbin.javaeye.com/blog/182312" style="color:red;">http://robbin.javaeye.com/blog/182312</a>&nbsp;
          发表时间: 2008年04月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Passenger(俗称mod_rails)是最近刚刚发布的Apache module项目，刚一出来就得到了诸多好评，JavaEye新闻也有两篇报道：<br /><br /><a href="http://www.javaeye.com/news/1874" target="_blank">Rails部署也可以简单得像PHP一样</a><br /><a href="http://www.javaeye.com/news/1754" target="_blank">Passenger(mod_rails)新的RoR部署方式</a><br /><br />其中性能评测更加令人印象深刻<br /><br /><img src="http://izumi.plan99.net/blog/wp-content/uploads/2008/03/passenger_mongrel_thin_benchmark.png" /><br /><br />好像还有人称，未来RoR的主流部署方式将是mod_rails，而且这个项目的作者还貌似一个华人，叫做“赖洪礼”，所有的这一切都让人挺有兴趣，于是我在周末也简单的安装和测试了一把。<br /><br />如果已经安装好Apache和Ruby on Rails的环境，并且把Apache的bin目录和ruby的bin目录配置到PATH环境变量下面，那么安装Passenger倒也很简单：<br /><br /><pre name="code" class="ruby">
gem install passenger
passenger-install-apache2-module
</pre><br /><br />安装好以后，他会提示你如下配置Apache(具体环境可能稍有不同)：<br /><pre name="code" class="java">
LoadModule passenger_module /usr/local/ruby/lib/ruby/gems/1.8/gems/passenger-1.0.1/ext/apache2/mod_passenger.so
RailsSpawnServer /usr/local/ruby/lib/ruby/gems/1.8/gems/passenger-1.0.1/bin/passenger-spawn-server
RailsRuby /usr/local/ruby/bin/ruby

NameVirtualHost *:80

&lt;VirtualHost *:80>
    DocumentRoot "/home/webroot/demo/public"
    ServerName 192.168.0.3
    ErrorLog "logs/rails-error_log"
    CustomLog "logs/rails-access_log" common
&lt;/VirtualHost>
</pre><br /><br />前面三行是注册Apache的module，以及该module的相关启动脚本，后面就是标准的Apache虚拟主机配置方法了，指明rails项目的public路径就可以了。<br /><br />在Apache运行起来之后，Apache启动了一个Rails的Passenger进程，该进程是用来管理ruby进程的启动关闭以及响应请求的，如果访问量比较大，该进程还会陆续启动子进程，来提高更多的ruby进程管理，如下所示：<br /><br /><pre name="code" class="ruby">
root      5981  5980  0 13:37 ?        00:00:00 Passenger spawn server                                                       
root      6086  5981  0 13:40 ?        00:00:01 Passenger FrameworkSpawner: 2.0.2     
daemon    6350  6086  0 13:54 ?        00:00:00 Passenger ApplicationSpawner: /home/webroot/demo  
</pre><br /><br />以上的3个ruby进程是控制进程，此外，还会根据web请求的数量，启动相应数量的Ruby进程来处理Rails请求。这些ruby进程在控制进程的控制下，当web请求负载高的时候，会动态创建更多进程，当web请求负载低的时候，就会动态销毁，以节省内存。控制进程和Rails进程之间使用Unix Socket来通讯。<br /><br />mod_rails的大致原理就是这样的。这种运行方式有点类似Apache以mod_fastcgi方式来运行Rails，但因为通讯方式和控制进程都要好得多，因此不会出现mod_fastcgi的好多问题。<br /><br />mod_rails提供了apache上面另外一种可以选择的Rails部署方式，但是这种部署运行方式也不可避免的带有致命缺陷。正因为ruby进程是动态创建，而我们知道Rails进程启动的时候是非常消耗CPU的操作，因此黑客可以很容易的通过瞬时发起数量巨大的并发web动态请求让服务器因为忙于创建大量的Rails进程而陷于瘫痪。<br /><br />另外对于虚拟主机提供商来说，ruby进程的数量是根据请求量动态调整的，因此无法根据付费用户来分配限制相应的资源，这不像mongrel那样好控制用户使用的资源数量。因此预期Rails虚拟主机提供商也不会采用mod_rails。<br /><br />最后我个人觉得，随着Lighttpd和nginx的崛起，Apache真的已经可以淘汰了，Apache这种多进程web服务器实在太消耗服务器资源，也太容易被DOS攻击了，任何依赖Apache的部署方案都有点过时了。<br /><br />如果说要我推荐的话，Rails部署的性能首选还是Lighttpd+FastCGI，次选则可以考虑 nginx + thin/mongrel
          <br/>
          <span style="color:red;">
            <a href="http://robbin.javaeye.com/blog/182312#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 13 Apr 2008 14:32:25 +0800</pubDate>
        <link>http://robbin.javaeye.com/blog/182312</link>
        <guid>http://robbin.javaeye.com/blog/182312</guid>
      </item>
          <item>
        <title>关于技术人员创业入股的问题</title>
        <author>robbin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://robbin.javaeye.com">robbin</a>&nbsp;
                    链接：<a href="http://robbin.javaeye.com/blog/182246" style="color:red;">http://robbin.javaeye.com/blog/182246</a>&nbsp;
          发表时间: 2008年04月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          投资方原打算在前两年投入300万研发产品，如果算上后期的维护和市场推广，估计投资方在这个公司的投资预算大概在500万人民币左右。好了，那么楼主一不打算实际出资占有股份，二没有现成的产品折算成现金入股(X产品产权不是你的，Y产品不是这个行业的产品)，也就是说你现在只能以技术入股，即所谓的干股。<br /><br />干股意味着你没有实际的投入，也无需承担任何风险，随时都可以撤退，而且干股获得的股份实际上是对你未来创业期投入的预先支付，激励你在未来创业期发挥其应得股份的作用的，而不意味着你加入公司的第一天，就应该拿到这么多股份。记住一点：你应该占多少股份，取决于你付出了什么，而不是你预期对公司发挥多大作用。人家实际注资几百万，就该占有多少股份，而你干股入股的方式，人家就算只给你10%，也是合情合理。<br /><br />虽然楼主口口声声说不想再打工，只想有自己的事业云云。但我不得不打击你一下，无论最终你在这家公司拿到多少股份，即使你最终拿到自己期望的25%，也不意味着这个公司是你的事业。实际上由于你干股的身份、加上你完全对运作公司，市场推广、公司财务等方面一无所知，因此你在公司的地位是被动的，实际身份介于股东和打工者之间的形态，你以后会发现，就算你是股东，你实际出资的那个大股东仍然是你的老板，这一点无法改变，除非你也出资一二百万。<br /><br />至于薪水方面，你期望税后25万年薪，就一下暴露了自己抱定打工的心态，而不是创业心态。这个年薪在上海算很高了，现在即便外企都不见得能够给到你这个数字，更不要说创业公司，没有一家会给你这个数字。既然你是创业，就要记住一点：创业是要冒很大风险的，你拿这么高工资，一点收入的损失都没有，完全没有风险？就算你一分股份都不占，你也不吃亏阿，我看前面说到，好像你现在也无法立刻找到这么高的收入吧？想要在创业公司获得高收入，要靠你对公司业绩贡献特别大，而公司盈利情况非常好，那么年终奖你可以一下拿到十几万。任何公司的CEO/CTO的年收入主要都是靠业绩激励的奖金，而不是靠工资获得的，如果公司还在投入期，根本不赚钱，你作为股东为什么不能和公司共患难呢？<br /><br />我也不了解你的合作方，因此不清楚人家会怎么想。如果换了是我的话，我投资500万成立这样一家公司，我给你开的条件，年薪方面我只能给到税后10-15万，股份在10-20%之间，如果年薪要得高，股份就相应的低一些，反之依然。另外我会要求你做到两点：你需要实际出资10万现金入股，购买5%的股份，剩下的股份也不是一次性给予的，会分三年36个月，做满一个月，获得一个月的，干满三年，并且尽职完成自己的工作，才能拿到所有的股份，如果干不满36个月，干几个月就拿几个月的股份。<br /><br />你们现在的情况并不是大家都白手创业，而是有资本进来的，那就是资本说话，你干股的身份其实就是给资本打工。
          <br/>
          <span style="color:red;">
            <a href="http://robbin.javaeye.com/blog/182246#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 13 Apr 2008 09:15:23 +0800</pubDate>
        <link>http://robbin.javaeye.com/blog/182246</link>
        <guid>http://robbin.javaeye.com/blog/182246</guid>
      </item>
          <item>
        <title>以无法为有法，以无限为有限</title>
        <author>robbin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://robbin.javaeye.com">robbin</a>&nbsp;
                    链接：<a href="http://robbin.javaeye.com/blog/177084" style="color:red;">http://robbin.javaeye.com/blog/177084</a>&nbsp;
          发表时间: 2008年03月28日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          以无法为有法，以无限为有限   --- by 李小龙<br /><br /><a href="http://robbin.javaeye.com/blog/174594" target="_blank">关于JavaEye网站未来发展的思考</a>当中分析了一种现象：用户经常泡的网站会逐渐收敛到两三个，不会超过五个。如果深层次的探究下来，即便在一个网站内部，用户经常泡的功能也会逐渐收敛到两三个，不会超过五个。虽然在战略方面来说，JavaEye以后会做很多很多功能，但基本原则就是：功能可以五花八门，但是所有的功能都是为同一个目标服务的，目标不能多，不能发散。<br /><br />我每次看CSDN网站就觉得心浮气燥，很有挫折感，望而生畏，为什么呢？其中一个原因就是CSDN提供了太多功能了，想要实现的目标实在太多了。他要做下载、他要做开源、他要做项目外包、他要做视频远程教育、他还要做图书评论、他还要做招聘，他还要做SNS，如此多的目标导致了纷繁复杂、并且彼此独立的功能点。让你面对这样一个庞然大物产生了心理压迫感和畏惧，没有信心去掌握这个网站的使用方法。<br /><br />JavaEye的目标简单而清晰，对于非登陆会员来说，就是提供高质量内容，形式可以多样化，但是目标单一；对于长时间泡在网站上面的登陆用户，我们是提供加强的用户交流功能；最后对于资深用户和重度用户，我们会开放API，让他们自己DIY。这样非登陆会员他只看到技术文章就好了，不给他增加心理负担；登陆用户想多消磨时间的时候，给他更高级的应用，但不需要他自己开发那么麻烦；最后重度用户连网站所有功能都不满足的时候，就自己动手来干，给他足够的灵活性。<br /><br />总之，一个网站不应该越做越复杂，越做越分散；而应该越做越简约，越做越收敛。JavaEye网站为什么大家觉得用起来还比较舒适，一个很重要的原因在于：JavaEye网站是收敛的，整个网站虽然功能已经挺多的了，但是整个网站是浑然一体的，所以不会给用户压迫感。即便我们要做的知识库、精华频道也都是围绕同一个目标展开的不同形式，因此不会破坏网站的整体感。<br /><br />像项目外包、开源项目托管、图书评论这些功能，每个功能都有他自己独立的目标，而且和我们网站现在的目标是不同的。因此这些功能上线以后网站的整体感就被破坏了，网站的目标分散为好几个，用户就会立刻感觉到网站功能很复杂、网站不同频道的使用方式不一致、使用起来有压迫感。<br /><br />比方说豆瓣就是一个典型的例子，现在的豆瓣改版越改越让人看不清楚面目，越改越让人觉得网站复杂、庞大，难以亲近。究其原因在于豆瓣要实现好几个不同的目标：既要做书评影评乐评，又要做SNS，还要做同城交友，还想做城市娱乐生活向导，想做的事情太多了，就让用户无所适从了。<br /><br />facebook又是一个特别典型的例子，他唯一的目标就是提供交流工具的平台，自身提供的功能极度的少，但是平台容纳能力又极度的大，这才是网站的至高境界：化繁为简，以无招胜有招。
          <br/>
          <span style="color:red;">
            <a href="http://robbin.javaeye.com/blog/177084#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 28 Mar 2008 00:36:42 +0800</pubDate>
        <link>http://robbin.javaeye.com/blog/177084</link>
        <guid>http://robbin.javaeye.com/blog/177084</guid>
      </item>
          <item>
        <title>总结一下大家对JavaEye网站发展计划的建议</title>
        <author>robbin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://robbin.javaeye.com">robbin</a>&nbsp;
                    链接：<a href="http://robbin.javaeye.com/blog/175621" style="color:red;">http://robbin.javaeye.com/blog/175621</a>&nbsp;
          发表时间: 2008年03月25日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          前面一篇博客文章，我谈了一下JavaEye网站今明两年的发展战略，其实写这篇博客文章的主要目的其一是整理并且系统化自己考虑了很久的想法，并且将其记录下来；其二是将这个战略构思分享给我的两位partner，因为我觉得写下来会比我空对空说话印象更加深刻；其三就是把这个战略构思分享给大家，看看大家会有什么反应。<br /><br />有点出乎意料，大家对于这篇文章的反应很热烈，也提了很多好的建议和想法，我试着总结和归纳一下，作为勉励我们继续把JavaEye网站做好的鞭策，同时也回答一下大家的一些问题：<br /><br /><span style="color: red">一、JavaEye网站的商业模式是广告和招聘</span><br /><br />很多人关心JavaEye网站靠什么赚钱呢？其实在过去四年多时间里面我也在一直摸索，但是现在我可以回答大家，就是广告和招聘。能够把这两项业务同时做好，对于我们这样一个小网站小公司来说，已经非常赚钱了，我并不指望融资和上市，这不是我能力之所及的。<br /><br />一些朋友建议我们推出软件外包频道，并且认为这是一个很有前途的商业模式。的确现在有很多威客模式的网站，但是软件行业有其特殊性，在线外包在这里几乎走不通，有兴趣的可以看看JavaEye的两个接私活的讨论，所谓“珍惜生命，远离外包”，即便从软件开发人员的职业生涯角度来说，我也不建议大家接私活，更不要说JavaEye做这种连我自己都不认可的事情了。<br /><br /><a href="http://www.javaeye.com/topic/79507" target="_blank">私活就那么难搞定吗？</a><br /><a href="http://www.javaeye.com/topic/145931" target="_blank">都别装了，难道你们不想拉私活？</a><br /><br /><br /><span style="color: red">二、网站要在产品细节方面多下功夫、努力提高网站的易用性，追求更好的用户体验</span><br /><br />比方说JavaEye博客还有进一步改进的余地、论坛的规则也可以增加一些人性化的提示、以及网站每个角落的功能点都应该精益求精的改进，突出三个要点：简洁、易用、人性化。<br /><br />从JavaEye2.0版本开始，我们一直朝着这个目标在努力，并且到目前为止还取得了不错的效果。特别是今年元旦新的版本上线以后，大家一致好评，网站的流量也在稳步上升，到最近两周，JavaEye网站每天页面访问量已经突破80万(周末50-60万)。因此产品改进是我们不断追求的目标，我们希望JavaEye最终不要像传统的门户网站那样用户体验糟糕，广告满天飞，而是一个偏web2.0风格的、清新自然、简洁易用、让人有亲近感的网站。<br /><br /><br /><span style="color: red">三、追求高质量的专业内容是JavaEye永远的核心竞争力</span><br /><br />我看有些人表达了这方面的担忧，不过好在我们头脑很清醒，不会犯这种错误。精华频道和知识库频道就是我们隆重推出，突出强调专业内容、高质量内容的功能，坚持精品战略是JavaEye的核心竞争力。<br /><br />即便有了这两个频道，我们也不会丝毫放松对论坛发贴回贴质量的要求，而是一如既往的坚守论坛高质量讨论的底线。也许有些朋友对严格的要求有些丧气，不过问答频道就是为入门级别的朋友准备的，我们希望有效的分流一部分这方面的需求，以保证各种层次的用户和谐共处。<br /><br /><br /><span style="color: red">四、回答一些相关的问题</span><br /><br />1、JavaEye不打算发起开源项目、不打算提供SVN托管<br /><br />我们目前只有三个全职的创业人员，其中全职写代码的只有一人，没有这个精力做这件事情。但我们会利用JavaEye这个平台帮助优秀的开源项目作者宣传他的项目，提供在线资源，比方说GT-Grid、庖丁分词等等。至于SVN，为什么不在Google Code，Java.net，Sourceforge上面开呢？有生命力的开源项目一定要融入全球开源社区，局限在国内的开源项目不会有前途。至于说到组合流行的框架、提供整合的解决方案，其实并不需要发起啥开源项目、只要在知识库里面提供丰富的框架指导性文档和示例代码就已经足够了。<br /><br />2、JavaEye扩展内容需要循序渐进<br /><br />JavaEye网站要成为全面的软件开发者社区，从目前来说在移动平台开发、数据库开发、操作系统和底层开发方面存在不足。我们也希望能够面面俱到，但是需要时间的积累和内容的积累，慢慢来吧，总会有那么一天的。<br /><br />3、JavaEye会逐渐增加一些个性化和SNS的东西<br /><br />我在战略里面不止一次提到了facebook，到不是说JavaEye要转型搞SNS，而是facebook这种以人际关系组织的网站功能很值得我们借鉴，他的一些工具恰好可以弥补JavaEye网站在交流方面存在的不足。我们希望做到的三步是：第一步个人信息聚合、第二步是通过应用来实现交友互动、第三步是个性化的推荐。<br /><br />4、开发API是一个远期目标<br /><br />关于开发API，看来大家都有不少创意。但这是JavaEye的远期目标，因此我没有特别清晰的路线图，而只是一个模糊的想法，这要随着JavaEye网站顺利完成前两个阶段的任务以后，根据到时候的形势来随机应变了，当然大家也可以随时贡献一些创意。
          <br/>
          <span style="color:red;">
            <a href="http://robbin.javaeye.com/blog/175621#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 25 Mar 2008 00:54:39 +0800</pubDate>
        <link>http://robbin.javaeye.com/blog/175621</link>
        <guid>http://robbin.javaeye.com/blog/175621</guid>
      </item>
          <item>
        <title>关于JavaEye网站未来发展的思考</title>
        <author>robbin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://robbin.javaeye.com">robbin</a>&nbsp;
                    链接：<a href="http://robbin.javaeye.com/blog/174594" style="color:red;">http://robbin.javaeye.com/blog/174594</a>&nbsp;
          发表时间: 2008年03月21日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          曾经有好几次用户发贴调查软件开发者经常访问的网站，每次调查的结果都大同小异，绝大部分用户平常只访问两到三个网站而已，多的也不超过五个网站。我觉得这是一个很有意思的现象：<br /><br />一般说来，软件开发者平时上网的时间都极长，除了上班8小时上网以外，晚上在家也经常泡在网络上面，很多人一天上网超过12小时也不算奇怪；更有甚者，很多人一天到晚都需要泡在网上，如果不能上网，简直就无法正常工作了，比方说我就是这样的典型。<br /><br />但是对于这样一个每天泡网时间这么长的用户群体来说，为什么访问的网站这样少呢？以我自己为例，除了工具性质的Google以外，我每天上的网站也仅仅只有JavaEye和新浪而已，其他网站都仅仅在需要的时候用一下而已，像我这样的典型用户在软件开发者群体当中普遍存在。<br /><br />原因我觉得是因为人的精力是有限的，网络生活的展开不是发散型，而是逐渐趋于收敛的。虽然整个互联网网站的数量不断在稳步增加当中，但是作为一个用户个体，他每天访问的网站并不会同步增加，而是始终收敛于二三个网站当中。但作为他经常访问的那几个网站，他对网站的需求是逐渐趋于多样化的，希望网站不断能够提供更多的功能来满足他网络生活的多种需要。<br /><br />现在JavaEye网站已经成为很多软件开发者平时网络生活所依赖的网站，为什么我们不把它做得更好，让用户用的更爽呢，牢牢的粘下去呢？ 因此我觉得JavaEye网站应该成为为软件开发者提供全方位服务的网站，或者用一句庸俗的话来说：软件开发者的网络家园。<br /><br />就我自己的感觉来说，每天用Gmail收发邮件，用Google Reader阅读RSS，上新浪看一下时政要闻和体育新闻(曾经订阅新浪新闻RSS，结果被信息轰炸的无法阅读)，然后就是泡JavaEye了，但问题是JavaEye无法给我提供每天超过10小时的网络消磨方式，换句话来说就是：JavaEye还不足以承担网络生活家园这样一个目标。那么JavaEye要如何去做才能够达到这样的目标呢？我觉得需要分三个阶段来达到：<br /><br /><span style="color: red"><span style="font-size: large">第一阶段：以提供内容为主、扩大网站内容的来源和方式</span></span><br /><br />无论web1.0还是web2.0，只要不是Google那样的工具型应用、facebook那样的SNS应用、以及网络游戏，那么高质量的内容永远都是网站的核心吸引力，别人到你这个网站来就是因为有他需要的内容。因此需要解决的问题无非是：<br /><br />1、如何产生高质量的内容<br />2、如何有效的整理和展示这些内容<br /><br />目前JavaEye网站提供了“新闻”、“论坛”、“博客”和“圈子”这四种内容展示的方式，并且通过博客、论坛以及圈子的融合来打通应用之间的隔离，此外还通过全文检索来实现内容之间的关联性。但是我觉得这还远远不够，因此在JavaEye3.0的版本当中我们还将提供另外四种内容展示的方式：<br /><br />1、知识库<br />知识库可以提供真正结构化的内容、可以有效的归纳和整理知识、提高信息阅读的质量和有效性，知识库也是可以在很大程度上弥补论坛信息杂乱的一种很好的内容展示方式。当然我们仍然会通过全文检索的机制，让知识库的内容和其他类型的内容形成有效的关联，而不是割裂开来。<br /><br />2、招聘频道<br />招聘的内涵其实非常丰富，比方说如何进行职业生涯的规划、如果进行面试和笔试、常见的各种面试试题、应聘技巧这些知识性的招聘内容既是知识库的内容，同时也是招聘相关的内容。此外针对招聘者来说，公司黄页可以帮助他们了解公司的信息、个人简历展示可以帮助公司了解人才的信息。招聘内容的建设可以极大的丰富JavaEye网站的内容吸引力。<br /><br />3、问答频道<br />论坛并不是一个很好的提问解答途径，特别是JavaEye网站的论坛定位在交流为主，版规严格的情况下，并不利于提问解答这一基本需求的满足。因此，在保持论坛高质量的前提下，为了鼓励用户使用JavaEye网站，我们将提供另外一种形式的内容，即类似百度知道的问答频道，并且和知识库结合起来，专门面向求解答案的用户。<br /><br />4、精华频道<br />网站的核心竞争力在于高质量的内容、其实还有一个潜在的台词：高质量内容可以有效的树立一个网站的品牌和形象。随着2006年9月JavaEye2.0的上线，精华内容的产生渠道就已经相当分散了，用户不能够快速有效的从JavaEye整个网站每天的新闻、论坛、博客、圈子、以至于知识库、招聘和问答当中挑选出来真正的精华内容。于是对精华内容有偏执癖好的人来说，我们需要这一个精华频道，不求内容丰富，但求内容篇篇精华，可以咀嚼良久，余音绕梁。<br /><br />JavaEye3.0版本要完成的使命就是实现第一阶段的目标，建设完善的以内容为核心的综合性技术网站。今年上半年JavaEye的开发任务就是上面这四个新的频道上线，以及现有功能的不断完善和优化。并且希望JavaEye网站的页面访问量可以从目前的每天70万，提高到至少每天100万以上。<br /><br /><span style="color: red"><span style="font-size: large">第二阶段：以用户交互为主、提高用户交流的质量和频率</span></span><br /><br />实现第一阶段的目标也只是成为一个不错的技术网站而已，并不能成为软件开发者的网络家园。许多人之所以愿意整天泡在一个网站，并不单纯因为内容吸引人，从深层次的原因来说，是他熟悉了这个网站上面的人，他有和这些人进行交流的实际需要。<br /><br />用户之间交流的信息质量是和用户之间的熟悉程度成反比：如果两个人之间很陌生，一定是通过他写的高质量文章吸引了你，让你对他有所了解，产生了和他交流的话题和欲望；但是如果两个人之间很熟悉的话，交流的内容往往不是什么高深的技术话题，而是拉拉家常。所以高质量的内容仅仅是把软件开发者们拉到一起来进行有效交流的纽带，而一旦用户之间建立了密切的关系之后，维系他们的主要不是高质量内容，而是交流的场所和交流的形式。<br /><br />所以我们看到一种奇怪的现象，很多老会员可能平时并不经常发言，但是他会经常泡在JavaEye的海阔天空版，因为对他们来说，高质量的文章不是最吸引他们的地方，而是活跃在JavaEye的这些id和他们进行交流，这才是驱使他们泡JavaEye的理由。但很遗憾的是，除了在海阔天空交流场所进行灌水的交流形式之外，会员们找不到其他更加有效的交流场所和交流形式了。因此JavaEye第二个阶段的主要目标是提供丰富的用户交流场所和交流方式。因此JavaEye需要借鉴facebook网站，开发更好的用户交流功能：<br /><br />1、提供用户个性化信息聚合页面<br />类似用户一登陆facebook就可以看到各种和他有关的信息的profile页面，那么我们能不能够做到，用户点击页面右上角的“我的个性化网站”链接以后，看到用户自定义的各种信息的聚合呢？比方说哪些人回了他的帖子、他关注的哪些高手发表了什么新的言论、他的某某好友推荐了什么内容等等，一目了然。<br /><br />2、休闲交友的小应用<br />平常好友之间交流缺少的不是话题，而是一个“引题”，不在乎交流的内容，但是需要有个东西来引导大家进入交流的场景。所以你如果想和某个久不大招呼的朋友聊天，上来说“Hi，你吃了吗？”，其实你并不关心他吃没吃，只是你需要一个“引题”而已。制造引题的小应用有很多很多方式，只要看看facebook上面很受欢迎的小应用，就知道应该怎么做了。比方说facebook上面有一个小游戏是吸血鬼游戏，你咬更多的人你的等级就越高，高等级的吸血鬼还可以组织自己的军队，和朋友进行战斗，很简单的互动就可以让你和朋友保持不间断的联系。<br /><br />3、提供更加多样的交流方式<br />可以不仅仅局限于网页上面的交流，开发好友之间的基于IM、浏览器插件、AIR甚至IDE插件，把用户关心的信息直接推送到用户的桌面。<br /><br />第二个阶段的功能开发和运营则是今年下半年的主要目标。只有达到了这一目标，JavaEye网站才能真正具备足够的吸引力和强大的竞争力，才能真正发展成为一个规模足够大、能够支撑起来商业模式的技术网站。<br /><br /><br /><span style="color: red"><span style="font-size: large">第三阶段：以开放性为主、提供API，增加网站向外的信息整合能力</span></span><br /><br />互联网未来的发展趋势一定是网站之间的互相共享资源与合作，而不是像国内目前这样大家死把着自己的用户和内容，唯恐被别人偷去了。我相信JavaEye如果能够实现第二阶段目标，并且成长为行业内数一数二的大网站以后，就应该有一个更高的目标：整合行业网站资源，引领网站开放和合作的潮流，事实上facebook已经给所有人树立了一个高大的榜样。<br /><br />这第三个阶段则是JavaEye明年以后要努力的方向了，粗略的展望一下，我觉得应该做到这样两点：<br /><br />1、网站平台化，向外开放API<br />让用户能够自行开发应用扩充网站的功能，特别是面向软件开发者的网站，技术门槛并不是问题。如果网站只能够是用户提出需求，然后站方开发功能，实在有些无趣。想像一下用户自己开发应用，给网站添加功能，自己改造自己的个人空间是多么有意思的事情。<br /><br />2、网站聚合化，把外面信息聚合进来<br />这包括两个方面：聚合个人博客，聚合小型网站。比方说很多人更喜欢自己购买域名租赁空间架博客，但是他的博客流量很低，不能参与到一个大的技术交流圈子里面来。那么我们能不能够通过API接口，让用户自行编程把自己的博客以某种形式聚合到JavaEye网站上面来呢？对于小型网站也是这样，能不能让小型网站以某种方式整合到JavaEye网站的平台上来呢？双方合作的好处就是小网站可以获得大网站的平台资源，可以获得流量，而大网站更加平台化，能够整合更多的资源，变得更加强大。<br /><br />如果能够最终实现第三个阶段的目标，JavaEye会具备滚雪球般的自我发展能力，能够真正的在竞争当中立于不败之地，能够真正成为令软件开发者所每天依赖的那个网络家园。
          <br/>
          <span style="color:red;">
            <a href="http://robbin.javaeye.com/blog/174594#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 21 Mar 2008 18:23:52 +0800</pubDate>
        <link>http://robbin.javaeye.com/blog/174594</link>
        <guid>http://robbin.javaeye.com/blog/174594</guid>
      </item>
          <item>
        <title>Lighttpd和RoR安装配置的疑难解答</title>
        <author>robbin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://robbin.javaeye.com">robbin</a>&nbsp;
                    链接：<a href="http://robbin.javaeye.com/blog/168989" style="color:red;">http://robbin.javaeye.com/blog/168989</a>&nbsp;
          发表时间: 2008年03月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          之前写过一篇<a href="http://www.javaeye.com/topic/43228" target="_blank">在Linux平台上安装和配置Ruby on Rails详解</a>，可能是有点高估了Linux的普及和应用程度，无数安装和配置的问题都以各种方式向我涌过来。这里集中的提供一下疑难解答：<br /><br />一、到底我应该用Lighttpd，还是Nginx/Mongrel？<br /><br />现在Nginx/Mongrel的部署方式越来越受欢迎了，很多人置疑Lighttpd/FastCGI，并且现在也涌现了一些比Mongrel性能更好的例如Thin，ebb等ruby应用服务器，那Lighttpd/FastCGI真的过时了吗？<br /><br />大家有兴趣可以看一下我这篇文章：<a href="http://www.javaeye.com/topic/155542" target="_blank">RoR部署方案深度剖析</a>，Lighttpd提供了很多其他Web服务器不具备的优势，可以最大化FastCGI的性能。现在Mongrel/Thin/ebb都利用了一些多线程或者事件IO机制来提供并发性能，这是FastCGI所不具备的，但遗憾的是Rails框架是单线程的，最终还是必须单进程单线程来执行Rails请求，所以这些并发优势无用武之地。但一些其他Ruby的Web框架例如camping，weavers已经开始支持ruby多线程，提供了比Rails好得多的性能，mongrel/ebb只有在这些web框架上面才能发挥其性能优势。<br /><br />有人会问，Rails会不会改成多线程？我认为不可能：一来Rails的多进程被证明是一种古老的、但是高可靠性、高扩展性的部署方式，没有改的必要性；二来真要改成多线程，改动实在太大了，整个底层框架都要改。<br /><br />所以只要你还是用Rails框架，Lighttpd/FastCGI就是性能最好的部署方案。<br /><br />二、ubuntu Linux安装ruby碰到的缺少readline，zlib库的问题？<br /><br />有些人的ubuntu安装的库不全，比方说缺少readline库，缺少zlib库，可能会导致自己手工编译安装ruby的失败，那么就用apt-get先把库安装好。<br /><br />三、Lighttpd安装遇到的缺少pcre库的问题？<br /><br />RHEL/CentOS用户可能要用yum安装一下pcre/pcre-devel这两个库，ubuntu用户用apt-get安装一下，Linux熟手也可以自己下载源代码编译安装，Pcre是Perl兼容的正则表达式库，Lighttpd的Rewrite功能需要它。<br /><br />四、Lighttpd配置过程当中遇到的种种问题？<br /><br />1、我用的是ubuntu，你说的控制脚本rc.lighttpd我跑不了，执行就会报错<br /><br />rc.lighttpd这个脚本是针对SuSE Linux写的，此外还提供了一个rc.lighttpd.redhat是针对RedHat Linux写的，没有针对ubuntu的版本，但是你自己写一个控制脚本，也不过是举手之劳：<br /><br /><pre name="code" class="java">
#!/bin/sh

case "$1" in 
  start)         
    /usr/local/lighttpd/sbin/lighttpd -f /etc/lighttpd/lighttpd.conf > /dev/null 2>&1
    ;;
  stop) 
    killall lighttpd
    ;;
  restart) 
   $0 stop
   sleep 1
   $0 start 
   ;;
  *) 
  echo "Usage: lighttpd.sh {start|stop|restart}" 
  ;; 
esac

exit 0 
</pre><br /><br />创建一个shell脚本，内容如上，chmod u+x lighttpd.sh，这个脚本就可以用来启动关闭和重起lighttpd了<br /><br />2、启动Lighttpd的时候报错，说XXX目录找不到<br /><br />Lighttpd启动之后默认情况下会写access log，error log，如果你启动了压缩过程，还会把文件压缩过的版本放在压缩目录下面，所以检查一下你的lighttpd.conf配置文件，是不是这些目录还没有，或者路径不对。<br /><br />3、启动lighttpd可以访问，但如果配置了Rails，就无法启动<br /><br />如果无法启动，要学会自己看Lighttpd的error log和Rails项目的log目录下面的fastcgi crash log，在这两个log文件当中可以找到出错原因。其中一种常犯的错误是：Rails项目在Windows上面创建和开发，最后部署到Linux Server上面。这种情况下dispatch.fcgi这个脚本的ruby解析器路径是 #!c:/ruby/bin/ruby.exe 这个路径在Linux上面肯定是错误的，你可以改成#!/usr/bin/env ruby，或者干脆在Linux上面创建该Rails项目。此外在windows上面创建的Rails项目，dispatch.fcgi没有可执行权限，这也需要你在Linux上面先赋予可执行权限才行。你可以尝试着手工运行该脚本cd public && ./dispatch.fcgi，看看是否可以运行。<br /><br />4、启动lighttpd报错，说找不到socket路径<br /><br />我在前面安装文档中给出来的配置内容如下：<br /><br /><pre name="code" class="java">$HTTP["host"] == "www.xxx.com" {
 server.document-root = "/yourrails/public"
 server.error-handler-404 = "/dispatch.fcgi"
 fastcgi.server = (".fcgi" =>
    ("localhost" =>
      ("min-procs" => 10,
       "max-procs" => 10,
       "socket" => "/tmp/lighttpd/socket/rails.socket",
       "bin-path" => "/yourrails/public/dispatch.fcgi",
       "bin-environment" => ("RAILS_ENV" => "production")
      )
    )
 )
}</pre><br /><br />就算照抄你要改改路径吧？这个demo当中的socket路径是/tmp/lighttpd/socket/rails.socket，那你要照抄，先检查一下有没有/tmp/lighttpd/sock目录总是应该的吧？其实用啥路径都无妨，关键就是别照抄，领会原理，根据自己的环境做相应的调整。<br /><br />5、重起lighttpd以后，fastcgi进程不关闭，导致多次重起lighttpd之后，fastcgi进程堆积越来越多？<br /><br />正常情况下，关闭Lighttpd以后，dispatch进程就会销毁，但是在dispatch进程处理请求的时候关闭lighttpd，dispatch进程并不会马上关闭，而是处理完毕当前请求，才会关闭掉。一些极端情况下，可能会导致dispatch进程一直不关闭，dispatch进程就会越来越多。解决办法很简单 killall -9 dispatch.fcgi，只管杀进程就好了。<br /><br />6、我的lighttpd和FastCGI部署在不同的服务器，怎么配置呢？<br /><br />这种情况下，Lighttpd只是连接远程服务器的TCP端口，而不负责启动dispatch.fcgi进程，因此需要自己写脚本启动关闭dispatch.fcgi进程。lighttpd提供了一个spawn-fcgi的程序，可以用来启动dispatch.fcgi进程，监听TCP端口，你可以自己写一个shell脚本来完成这个工作。另外spawn-fcgi还可以启动dispatch.fcgi进程，创建本机的unix socket端口，和本机lighttpd通讯，例如：<br /><br />例如：<br /><pre name="code" class="java">
#!/bin/sh

DISPATCH_PATH=/yourrailsapp/public/dispatch.fcgi
SOCKET_PATH=/tmp/lighttpd/socket
RAILS_ENV=production
export RAILS_ENV

case "$1" in

  start)
    for num in 0 1 2 3 4 5 6 7 8 9
    do
     /usr/local/lighttpd/bin/spawn-fcgi -f $DISPATCH_PATH -s $SOCKET_PATH/rails.socket-$num
    done
    ;;

  stop)
    killall -9 dispatch.fcgi
    ;;

  restart)
    $0 stop
    $0 start
    ;;
  
  *) 
    echo "Usage: dispatch.sh {start|stop|restart}"
    ;;
  
esac

exit 0</pre><br /><br />执行 ./dispatch.sh start 将启动10个dispatch.fcgi进程，在/tmp/lighttpd/sock目录下面创建了10个unix socket文件，然后配置lighttpd去连接这10个socket文件：<br /><br /><pre name="code" class="java">$HTTP["host"] =~ "www.xxx.com$" {
  server.document-root = "/yourrails/public"
  server.error-handler-404 = "/dispatch.fcgi"
  fastcgi.server = (".fcgi" =>
    (
      ("socket"=>"/tmp/lighttpd/socket/rails.socket-0"),
      ("socket"=>"/tmp/lighttpd/socket/rails.socket-1"),
      ("socket"=>"/tmp/lighttpd/socket/rails.socket-2"),
      ("socket"=>"/tmp/lighttpd/socket/rails.socket-3"),
      ("socket"=>"/tmp/lighttpd/socket/rails.socket-4"),
      ("socket"=>"/tmp/lighttpd/socket/rails.socket-5"),
      ("socket"=>"/tmp/lighttpd/socket/rails.socket-6"),
      ("socket"=>"/tmp/lighttpd/socket/rails.socket-7"),
      ("socket"=>"/tmp/lighttpd/socket/rails.socket-8"),
      ("socket"=>"/tmp/lighttpd/socket/rails.socket-9")     
    )
  )
}</pre><br /><br />这样做的好处是，每次重新部署应用，就不需要重起lighttpd了，只需要执行自己的dispatch.sh来重起dispatch.fcgi进程就可以了。同时也可以很好的解决上一个fastcgi进程堆积的问题。<br /><br />如果远程部署，配置方式是一样的，就是lighttp连接的端口改为：<br /><br /><pre name="code" class="java">("host"=>"192.168.0.1, "port"=>3001),
("host"=>"192.168.0.1, "port"=>3002),
......</pre><br /><br />dispatch.sh创建dispatch.fcgi进程的时候，使用 -t 参数创建tcp端口，而不是 -s 创建unix socket文件即可。
          <br/>
          <span style="color:red;">
            <a href="http://robbin.javaeye.com/blog/168989#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 07 Mar 2008 11:09:21 +0800</pubDate>
        <link>http://robbin.javaeye.com/blog/168989</link>
        <guid>http://robbin.javaeye.com/blog/168989</guid>
      </item>
          <item>
        <title>SAAS(软件即服务) 离我们还有多远？</title>
        <author>robbin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://robbin.javaeye.com">robbin</a>&nbsp;
                    链接：<a href="http://robbin.javaeye.com/blog/168814" style="color:red;">http://robbin.javaeye.com/blog/168814</a>&nbsp;
          发表时间: 2008年03月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          最近在新闻上面看到了这样一条：Google公司的在线软件服务包Google Apps 2007年营业收入达到了4亿美元，然后在方军博客上面看到这样一段评论：<br /><br /><a href="http://www.mindmeters.com/showlog.asp?log_id=6942" target="_blank">http://www.mindmeters.com/showlog.asp?log_id=6942</a><br /><br /><div class="quote_title">方军博客 写道</div><div class="quote_div">有消息说，“Google Apps生成的营收在谷歌总营收中占到2%到3%的比例，2007年约为4亿美元，相当于2006年4000万美元的10倍。……假设Google Apps由一家独立的公司提供，按照Salesforce.com 10倍的市值营收比，这家独立公司的市值至少将达到40亿美元。”<br /><br />在我周围，Google Apps的用户并不多。我想，由于中国互联网用户仍处于接受信息的阶段、且免费的盗版软件四处可用，Google Apps在中国的总体用户量并不大。这可能是我们忽视Google Apps的原因，这可能是个很大的错误。<br /><br />在一年前，访问哈佛商学院创新教授克里斯滕森时，他认为Google Apps是他的理论中所分析的新市场创新，当时他说：“我在哈佛商学院的学生做文字处理时，他们用Google的Word，他们将文件存储在Google 的服务器上，而不是他们自己的电脑上。这是一个典型的新市场破坏，当互联网变得越来越快和更可依赖，用户正从桌面电脑上的软件应用转向基于互联网的应用。”<br /><br />克里斯滕森这段理论分析并不是印象最深刻的，印象最深刻的是他开玩笑说自己老了，不会采用Google Apps，但新一代学生们早已经把一切都放在网上。我也时时体会到，虽然信任别的备份方式，但实际上资料备份一份在Gmail里面是最方便的，几年以后要找资料的时候，那些在Gmail里面的最容易找出来。</div><br /><br />最令我动容的是最后这句话，你是信任自己电脑硬盘的备份呢？还是信任Gmail给你的备份呢？你是在自己电脑上面查找资料方便呢？还是在Gmail里面查找资料方便呢？更进一步，你觉得用outlook收公司的邮件放心呢？还是用Gmail收那些已经被Google扫描查过毒的邮件放心呢？<br /><br />当我问了自己上面这些问题以后，我发现至少在互联网消费领域，SAAS面临的最大障碍……信任问题已经悄悄发生了逆转：<br /><br />一、你信任桌面邮件软件还是Web邮件系统？<br /><br />记得多年前我还一直使用Foxmail的时候，整理和备份邮件对我来说是一件负担很重的事情，重新安装软件或者操作系统都意味着大批邮件内容的丢失，大批邮件地址的丢失，当然你还需要防备时不时不期而止的垃圾邮件和病毒附件。但自从我使用Gmail之后，所有的烦恼全部消失，想不起来某件事情，用Gmail一搜就搞定了，我已经离不开Gmail了。<br /><br />二、你信任自己的本地备份还是网络备份？<br /><br />我家里的台式机四年之内坏了四块硬盘：一块IBM，一块Maxtor，两块Seagate，备份光盘也有很多已经无法读出来了。但我在Gmail里面的文档随时随地都可以打开看，完全不用担心丢失问题。<br /><br />三、你觉得Microsoft Office方便还是Google Docs方便？<br /><br />不知道别人的方式是什么，我是定期整理自己的电脑硬盘，把文档进行分门别类的整理，存放，很麻烦，而且文档一多，实际上也很不好管理和查找。特别是需要和别人进行共享和编辑的文档，有n个版本，经常发生混乱的现象。但是一旦开始使用Google Docs，这些烦恼统统退散，备份、整理、查找、共享和版本管理变得异乎寻常的简单。<br /><br />四、你使用桌面便笺还是网络便笺？<br /><br />我曾经安装和试用了n个桌面便笺软件，没有找到一个令我觉得满意的，最后我发现了37sinals的Backpack在线个人日程管理软件，现在我已经把免费账号下面所有的Page都用光了。<br /><br />五、你还在电脑上面安装金山词霸吗？<br /><br />其实你可以随时使用金山的在线词霸查词了。<br /><br />这个列表还可以无休无止的列举下去，在我们不经意之间，网络已经是一个比我们桌面PC更加可靠、更加值得信赖的NPC，SAAS离我们还远吗？
          <br/>
          <span style="color:red;">
            <a href="http://robbin.javaeye.com/blog/168814#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 06 Mar 2008 16:16:31 +0800</pubDate>
        <link>http://robbin.javaeye.com/blog/168814</link>
        <guid>http://robbin.javaeye.com/blog/168814</guid>
      </item>
          <item>
        <title>Warp framework - 一个相当有前途的Java轻量级Web开发框架</title>
        <author>robbin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://robbin.javaeye.com">robbin</a>&nbsp;
                    链接：<a href="http://robbin.javaeye.com/blog/168780" style="color:red;">http://robbin.javaeye.com/blog/168780</a>&nbsp;
          发表时间: 2008年03月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Warp framework 是最近刚刚发布的、基于Google Guice的轻量级Web开发框架，我也是在JavaEye网站的新闻频道看到的这条新闻： <a href="http://www.javaeye.com/news/1363" target="_blank">warp-persist 1.0: 为Google Guice专门提供持久层与事务处理的框架</a>，通过这个新闻仔细阅读了Warp网站上面的文档，感觉到很振奋，Warp是一个相当棒的Java Web框架，而且前景非常看好。<br /><br />Warp框架充分利用了JDK5.0的Annotation和泛型机制，并且基于Google Guice这个IoC框架，提供了full-stack的Web开发设施，他主要包含了四个部分：<br /><br />warp-persist框架：封装Hibernate和JPA，提供事务管理和持久化资源管理<br />warp-dynamic-finder：提供了基于Annotation的动态查询功能，让数据库查询变得异常简单，不再需要DAO层<br />warp-mvc：借鉴了Tapestry5，提供了一个基于事件机制和组件化的Web层，并且组件注入方式高度IoC化<br />warp-servlet： 提供了一些Servlet的封装和附加的高级功能，例如URL过滤，和其他web框架集成等等<br /><br />这几年来，Java在Web开发框架方面的进步显得很有限，Spring/Hibernate组合对撼JBoss Seam形成两大竞争的主流态势，但是这两个Web框架在Web快速开发方面的创新还显得不够好：Spring是越来越臃肿了，配置文件也是越来越复杂难懂了；JBoss Seam门槛又过高，而且集成的JSF一向受人垢病，并非完美的解决方案，特别是在Ruby on Rails横空出世之后，Java社区对于简洁易用的快速web开发框架的企盼也是一直很高的。<br /><br />Warp在我看来是这方面做的最好的，它有以下几个鲜明的特点：<br /><br />一、充分利用JDK5的annotation，简化编程和配置文件<br /><br />Warp基于Google Guice并且发扬光大，自身无配置文件，所有功能完成均通过annotation，所以编程相当简洁<br /><br />二、大量使用JDK5的泛型编程，提供强类型安全保证<br /><br />虽说脚本语言的Duck Typing理念很流行，不过Java的优势也就是类型安全，Spring大量运用反射和XML配置等于是放弃了Java的优势。Warp在泛型方面做的很好，我相信在IDE的帮助下，Warp编程会更轻松<br /><br />三、Warp-persist提供了声明式的事务管理，终于可以取代Spring了<br /><br />Google Guice很好很强大，但是它没有事务管理能力和资源管理能力，所以无法取代spring，但是Warp-persist填补了这一缺憾，注入和管理Hibernate很容易：<br /><br /><pre name="code" class="java">
Injector injector = Guice.createInjector(..., PersistenceService
			.usingHibernate()
			.across(UnitOfWork.TRANSACTION)
			.buildModule());</pre><br /><br />要声明事务比spring可简单多了：<br /><br /><pre name="code" class="java">
public class MyService {
    @Inject Provider&lt;Session> session; 

    @Transactional 
    public void createNewPerson() {
        session.get().saveOrUpdate(new Person(...)); 
    } 
}</pre><br /><br />Warp支持Hibernate/JPA的所有事务管理策略，不但注入方式简单，而且声明事务方式更简单，代码看着简洁，写着更省心。<br /><br />四、Dynamic Finder实在很酷！<br /><br />还是直接看代码吧：<br /><br /><pre name="code" class="java">@Finder(query="from Person")
public List&lt;Person> listAll() { return null; }</pre><br />用annotation声明一下，一行查询代码都没有，你还要DAO干啥呢？<br /><br /><pre name="code" class="java">
@Finder(query="from Person where firstName = :firstName")
Person find(@Named("firstName") String name);</pre><br />带参数的绑定变量查询，还是一行代码不用写，DAO是啥？<br /><br /><pre name="code" class="java">@Finder(query="from Person")
List&lt;Person> listAll(@FirstResult int first, @MaxResults int max);</pre><br />带分页的查询，还是一行代码不用写，谁用DAO我跟谁急 ！<br /><br /><br />五、Web层也极其简单<br /><br />Warp-MVC模仿了Tapestry 5的架构，但是作者做了大量的改良和简化，作者解释了一下<a href="http://www.wideplay.com/warptapestrycompare" target="_blank">为什么不直接使用Tapestry，而是自己开发</a>的理由。<br /><br />Warp-MVC看起来像一个Tapestry的简化版，有组件的概念，事件响应的方式，但是非常易用，非常简洁，URL映射也通过annotation方式声明，作者在自己的博客上面提供了相关的简单示例，可以参考：<br /><br /><a href="http://www.jroller.com/dhanji/" target="_blank">http://www.jroller.com/dhanji/</a><br /><br />Warp框架是最近几年来，我看到的第一个走在正确发展方向上的Java Web框架：结构简单、易用使用、但充分发挥了Java自身的语法优势，非常值得期待！<br /><br />目前Warp框架还不是特别成熟，但是Warp-persistent已经相当稳定了，如果你是使用Hibernate/Spring/Struts来开发项目的话，不妨试试Warp，把spring换掉改成Hibernate/Warp/Struts2.0，也是一个不错的解决方案，全部运用annotation，让你的项目Zero Configuration。<br /><br />友情提醒：Warp官方网站无法直接访问，建议在FireFox浏览器上面安装gladder插件，跨越GFW。<br /><br /><a href="http://www.wideplay.com" target="_blank">Warp Framework - 官方网站</a>
          <br/>
          <span style="color:red;">
            <a href="http://robbin.javaeye.com/blog/168780#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 06 Mar 2008 15:24:19 +0800</pubDate>
        <link>http://robbin.javaeye.com/blog/168780</link>
        <guid>http://robbin.javaeye.com/blog/168780</guid>
      </item>
          <item>
        <title>memcache_engine + memcachedb = 高性能分布式内存数据库</title>
        <author>robbin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://robbin.javaeye.com">robbin</a>&nbsp;
                    链接：<a href="http://robbin.javaeye.com/blog/158275" style="color:red;">http://robbin.javaeye.com/blog/158275</a>&nbsp;
          发表时间: 2008年01月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://code.google.com/p/memcachedb/" target="_blank">memcachedb</a>是一个由新浪网的开发人员开放出来的开源项目，给memcached分布式缓存服务器添加了Berkeley DB的持久化存储机制和异步主辅复制机制，让memcached具备了事务恢复能力、持久化能力和分布式复制能力，非常适合于需要超高性能读写速度，但是不需要严格事务约束，能够被持久化保存的应用场景，例如memcachedb被应用在新浪博客上面。<br /><br />memcachedb给memcached添加了一些数据库才具备的特性，但是我们还不能说memcachedb已经是一个数据库了，这是因为memcached不支持内存对象的遍历操作，当然更加不能支持复杂的查询操作，只能支持根据已知的key去查询对应的value。因此如果想把memcachedb当成一个高性能的分布式内存数据库来使用的话，查询的问题就没有办法解决，只能在应用程序里面配合其他方案做一些折衷。<br /><br />然而memcached的另外一个开源项目完美的填补了这一个缺陷，就是<a href="http://tangent.org/506/memcache_engine.html" target="_blank">memcache_engine</a>。<br /><br />memcache_engine是一个MySQL数据库的存储引擎，目前只支持MySQL5.1数据库，他能够把memcachedb作为MySQL数据库的一个存储引擎和MySQL集成起来，让用户通过标准的SQL查询语句访问memcachedb中存放的数据，请看如下示例：<br /><br /><pre name="code" class="sql">CREATE TABLE `a` (
    `a` int(11) NOT NULL DEFAULT '0',
    `b` int(11) DEFAULT NULL,
    `c` int(11) DEFAULT NULL,
    PRIMARY KEY (`a`)
    ) ENGINE=MEMCACHE DEFAULT CHARSET=latin1
CONNECTION='localhost:6666\;localhost:6688';</pre><br /><br />创建表a，存放在分布式memcached server：localhost:6666和localhost:6688当中。然后我们就可以使用标准的SQL语句随意的进行CRUD操作去使用memcachedb了，这实在是太酷了！有了memcache_engine，我们就可以用SQL去访问memcached，有了memcachedb，我们就不必担心数据丢失问题，事务恢复问题了，简直是绝配，让memcached真正成为了一个高性能的分布式数据库系统了。目前memcache_engine项目还是早期试验阶段，让我们期待memcache_engine项目早日发布正式版本吧！<br /><br />顺便多说几句：最近一年来，特别是最近一个月以来，围绕memcached的开源项目发展的非常非常活跃：<br /><br />1、最近刚刚发布了memcached的新的高性能C客户端接口: <a href="http://tangent.org/552/libmemcached.html" target="_blank">libmemcached</a><br /><br />2、由于有了libmemcached，该组织又发布了memcache_engine存储引擎，cool！<br /><br />3、由于libmemcached的发布，不到一周时间，ruby的两个崭新的memcache client就问世了，他们是<a href="http://blog.methodmissing.com/2007/6/4/get-your-caffeine-on/" target="_blank">Caffeine</a>和<a href="http://blog.evanweaver.com/articles/2008/01/21/b-the-fastest-u-can-b-memcached/" target="_blank">New memcache-client</a>，让ruby访问memcached的速度大幅度提高，请看：<a href="http://www.javaeye.com/news/905" target="_blank">libmemcached发布了，ruby访问memcached提速20倍</a><br /><br />4、memcachedb发布了，这是中国的互联网公司贡献的开源项目<br /><br />以上几个项目都是在2008年1月发布的，真的不是一般的繁荣阿。再加上之前发布的新的支持异步访问的Java Memcached API和C#接口，可以说除了Python，其他主流非主流编程语言都可以使用memcached了。其实即便是Python还没有公布出来的开源接口，我们也知道国内的web2.0网站豆瓣就是使用Python访问memcached，并且支持了极大的访问量，因此目前围绕memcached的开源项目发展的情况非常的繁荣。<br /><br />memcached最近两年这么受欢迎，其实和互联网web2.0的流行有很大的关系，web2.0网站通常需要个性化页面，依赖于页面局部和数据细颗粒度的缓存来提升性能，并且web2.0网站流量都很大，因此memcached这种高性能分布式缓存服务器就大行其道了。<br /><br />当然我觉得最具有革命意义的还是memcache_engine和memcachedb这两个项目的发布，他们能够让memcached的用途不仅仅限于缓存服务器而已，而是能够真正充当分布式数据库来使用了，这无异是诸多大流量web2.0网站和开发人员的福音阿。
          <br/>
          <span style="color:red;">
            <a href="http://robbin.javaeye.com/blog/158275#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 22 Jan 2008 12:05:49 +0800</pubDate>
        <link>http://robbin.javaeye.com/blog/158275</link>
        <guid>http://robbin.javaeye.com/blog/158275</guid>
      </item>
          <item>
        <title>JavaEye网站的RoR性能优化经验谈</title>
        <author>robbin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://robbin.javaeye.com">robbin</a>&nbsp;
                    链接：<a href="http://robbin.javaeye.com/blog/157731" style="color:red;">http://robbin.javaeye.com/blog/157731</a>&nbsp;
          发表时间: 2008年01月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          JavaEye网站从2006年9月11日上线基于RoR的2.0版本开始，到现在已经运行了将近一年半了。在这一年半的时间里，JavaEye网站的每日PV从最开始的5万，缓慢增长到了现在的60万。随着网站负载的不断增加，我们也在不断尝试和调整网站的性能，积累了不少第一手RoR应用性能优化的实战经验。虽然我们并不是RoR性能优化的权威专家，我们所积累的经验也许并不是最优实践，但是作为国内最早涉足RoR商业运营的互联网网站之一，我们非常乐意分享和交流我们的实战经验，以帮助后来者节省必要的摸索时间。<br /><br />RoR惊人的开发速度恐怕是每个互联网创业者都梦寐以求的，但是随着网站流量的不断增大，可能大多数采用RoR的网站或迟或早会遇到RoR的性能瓶颈，我的一个朋友capitian说过一句很有意思的话：“RoR应用做到后来，总有自己修改底层的冲动”。就我所了解和掌握的情况来看，很多RoR网站都过早的遇到了性能瓶颈，一个很普遍的现象就是：RoR应用的CPU负载要远远高于数据库的负载。这是一个有点违背常理的现象，因为我们知道，硬盘IO速度要比内存慢得多，所以一般Web应用的性能瓶颈往往会出现在数据库IO上，因此优化数据库访问，进行对象缓存是非常有效的性能优化手段。但是一旦应用服务器负载比数据库还高的话，单纯的对象缓存就无用武之地了。下面我们从几个方面分别谈一谈如何进行RoR的性能优化：<br /><br /><br /><span style="font-size: x-large">应用的部署</span><br /><br />RoR应用的部署包括操作系统，Web服务器，应用服务器和数据库四个方面：<br /><br /><span style="font-size: large">一、操作系统</span><br /><br />1、发行版本<br /><br />RoR适合于部署在Unix类操作系统上面，通常比较多的人使用RHEL/CentOS/Ubuntu，我们比较偏爱SuSE Linux，对于我们服务器使用的AMD Opteron x86_64的CPU来说，SLES要比RHEL有更多的优化。另外应该尽量使用64位版本操作系统，以充分发挥x86_64 CPU的性能，并且x86_64的Linux很多Kernel参数也大很多，代价就是需要更多的物理内存。<br /><br />2、文件系统<br /><br />Linux最常用的文件系统是ext3，但我们使用的是Reiserfs文件系统。Reiserfs在读写大量小文件的目录性能非常高，即使处理目录下面直接存放10万个文件，性能仍然不会下降。我们知道默认情况Rails会对每个浏览器会话在硬盘生成session文件，一个繁忙的网站，临时文件目录下面有上万乃至几万个session文件是很常见的现象。对于这种目录下面几万个小文件的存取，reiserfs要比ext3性能高一个数量级。如果希望对session文件有更好的存取性能，可以把临时目录链接到Linux的内存文件系统/dev/shm目录下面，这样实际上session文件的存取都是直接内存操作了，这种方式唯一的问题在于不能支持群集部署。如果你已经升级到了Rails2.0，可以采取把session保存到Cookie里面的方式，既可以避免服务器处理session的开销，而且还支持群集部署，是大规模网站部署的首选方式。<br /><br />3、内核的网络参数调整<br /><br />对于流量很大的网站来说，默认的Linux内核网络参数偏小，因此如果你的网站流量非常大，或者上传下载大文件比较多，可以针对性的调整内核网络参数，扩大内核的TCP接收数据和发送数据的Buffer缓冲区大小，比方说：<br /><div class="quote_title">引用</div><div class="quote_div">net.core.rmem_default=262144<br />net.core.wmem_default=262144<br />net.core.rmem_max=262144<br />net.core.wmem_max=262144<br />net.ipv4.tcp_rmem=4096 65536 524288<br />net.ipv4.tcp_wmem=4096 65536 524288<br /></div><br />参数具体调整，可以Google相关的Linux内核参数的文档，这里不展开详谈。<br /><br /><br /><span style="font-size: large">二、Web服务器</span><br /><br />Web服务器首选Lighttpd，因为Lighttpd在和后端的应用服务器通讯方式上做了足够的优化：当POST大数据量的时候，Lighttpd在完整的接收客户端浏览器的数据之后，才会一次性发送给应用服务器；同样的，Lighttpd也是一次性把应用服务器处理的页面数据全部接收，不设置Buffer Size的限制。因此Lighttpd能够尽最大可能的减轻应用服务器的负担，减少应用服务器用于处理数据传输的延迟，更加有效的利用应用服务器资源。这方面的详细的论述请看：<a href="http://www.javaeye.com/topic/155542" target="_blank">RoR部署方案深度剖析</a>。<br /><br />关于Lighttpd的安装可以参考<a href="http://www.javaeye.com/topic/43228" target="_blank">在Linux平台上安装和配置Ruby on Rails详解</a>，这里仅谈Lighttpd的性能优化的几个要点：<br /><br />1、网络IO调度方式<br />Linux Kernel 2.6支持sysepoll方式调度网络IO，能够处理极高的并发连接请求，Lighttpd可以通过配置文件打开sysepoll支持：<br /><div class="quote_title">引用</div><div class="quote_div">server.event-handler = "linux-sysepoll"</div><br /><br />2、网络IO传输方式<br />Linux Kernel 2.6支持sendfile方式传输数据，Lighttpd可以通过配置文件打开sendfile支持：<br /><div class="quote_title">引用</div><div class="quote_div">server.network-backend = "linux-sendfile"</div><br />此外Lighttpd还支持应用服务器参与的文件下载控制X-sendfile，详细的论述请看：<a href="http://www.javaeye.com/topic/154538" target="_blank">RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能</a><br /><br />3、文件状态缓存<br />Lighttpd通过stat()调用获得文件被修改的信息，来决定当请求同一个静态文件资源的时候，是否需要再次读取硬盘文件。但是每次stat()调用也有一定的开销，Lighttpd支持通过Fam Server来减少stat调用。即每次当文件被修改之后，Kernel会发送一个消息通知Fam Server，而Lighttpd会通过进程间通讯连接Fam Server，可以知道文件是否被修改的信息，不必再每次调用stat()。<br /><div class="quote_title">引用</div><div class="quote_div">server.stat-cache-engine = "fam"</div><br /><br />4、限定POST Size<br />为了避免黑客恶意的攻击服务器，伪造超大Post数据包轰炸Web服务器和应用服务器，可以限制Request请求的大小，例如限制为10MB：<br /><div class="quote_title">引用</div><div class="quote_div">server.max-request-size = 10240</div><br /><br />5、日志文件<br />Lighttpd是单进程单线程的服务器，调度网络IO性能是极高的，但是在某些极端情况下，单进程服务器也有风险，即一旦被某操作系统调用挂住，整个服务器就没有办法响应请求了。比方说服务器其他进程导致的IO WAIT很高，操作系统的buffer又不够的时候，Lighttpd在大量的写access log就有被挂住的可能性。因此如果Lighttpd日志对你的参考价值不大，可以考虑关闭掉。像JavaEye网站每天Lighttpd产生430万条log，对硬盘IO也是一个不小的负担，既然已经开着Rais的production.log，那么Lighttpd的access log没什么参考价值了，那就关掉它。<br /><br />Lighttpd的性能优化请看其作者写的文章：<br /><a href="http://trac.lighttpd.net/trac/wiki/Docs%3APerformance" target="_blank">http://trac.lighttpd.net/trac/wiki/Docs%3APerformance</a><br /><br /><br /><span style="font-size: large">三、应用服务器</span><br /><br />Ruby的应用服务器可以使用FastCGI，或者Mongrel，如果我们使用Lighttpd的话，FastCGI是最好的搭配。<br /><br />1、FastCGI和Lighttpd的通讯方式<br /><br />如果FastCGI和Lighttpd是在同一台服务器，那么建议采用Unix Socket通讯，这种通讯方式比TCP要快一些，FastCGI可以通过Lighttpd自带的spawn-fcgi命令行工具启动，创建socket文件，而Lighttpd监听socket文件。如果两者不在同一台服务器，需要群集部署，那就必须采用TCP Socket通讯，方式是一样的。<br /><br />2、FastCGI进程应该开多少个合适？<br /><br />Rails是单进程方式运行的，理论上来说，开几个FastCGI进程，就只能并发响应几个请求。对于繁忙的网站来说，峰值期间每秒有几十个动态请求是很正常的事情，但实际上FastCGI进程并不需要开那么多。这是因为前端的Web服务器在处理用户浏览器连接，发送Request请求需要相当长的时间，在FastCGI处理完请求释放该连接以后，Web服务器还需要相当长的时间才能把页面数据完整的发送到客户端浏览器。用户在点击一个链接以后，等待1-2秒，页面内容就显示出来，这对用户的感觉来说已经是非常快的了，而FastCGI用于处理该请求可能只需要0.1秒，那么一个FastCGI进程虽然并不能够真正的并发运行，但实际上的效果是他可以在1秒之内处理10个请求，让10个用户在同时访问网站的过程当中感觉不到明显的延迟。<br /><br />因此FastCGI需要开多少个，取决于你的网站峰值期间每秒有多少个用户请求过来，而你的FastCGI又能够以多快的速度处理请求。比方说你的网站峰值期间每秒有50个动态请求，FastCGI在峰值期间处理每个请求需要0.2秒，那么实际上你只需要开10个FastCGI进程就足够了，为了应付突发的峰值请求，你可以在这个计算量上面增加一些余量，比方说15-20个进程，肯定是绰绰有余了。<br /><br />关于FastCGI的性能优化，可以参考Lighttpd作者的文章，虽然他是针对PHP跑FastCGI写的，但对RoR也有参考价值：<br /><a href="http://trac.lighttpd.net/trac/wiki/Docs%3APerformanceFastCGI" target="_blank">http://trac.lighttpd.net/trac/wiki/Docs%3APerformanceFastCGI</a><br /><br /><br /><br /><span style="font-size: large">四、数据库</span><br /><br />JavaEye网站使用MySQL5.0.XX版本，数据库引擎是InnoDB。关于MySQL数据库的调优，推荐大家看<a href="http://www.mysqlperformanceblog.com/" target="_blank">MySQL Performance Blog</a>，作者是一个MySQL性能调优方面的专家，并且提供MySQL咨询服务。他的博客上面有很丰富的关于MySQL调优的文章和演讲文稿，特别是关于InnoDB方面，非常深入。JavaEye的数据库调优就是根据他的InnoDB演讲文稿来调整的，一般说来，有几个需要调整的参数：<br /><br />innodb_buffer_pool_size<br />这个参数很重要，越大越好，对于专用的数据库服务器一般建议开服务器内存的50%以上。<br /><br />query_cache_size<br />查询缓存，对于查询的性能提高有很大帮助，但不宜开得过大，查询缓存的过期可能很频繁，过大查询缓存反而降低性能，增加服务器开销<br /><br />innodb_flush_method = O_DIRECT<br />针对InnoDB的数据文件，关闭操作系统的文件缓冲，由于InnoDB自己有巨大的Buffer Pool，操作系统对文件的读写缓冲功能反而会降低MySQL的InnoDB的IO性能。<br /><br />最后针对数据库的SQL优化来说有两点原则：<br /><br />1、对数据库表要适当的创建索引<br />特别是出现在where查询条件当中字段，和关联查询当中的外键，要高度注意。<br /><br />2、尽量避免大表的全表扫描和数据库的硬盘IO<br />查询比较慢的SQL要explain一下，看看是否发生了全表扫描，采取各种措施减少或者避免大表的全表扫描问题，例如拆分表等等。<br /><br />最后针对MySQL数据库运行情况，我们可以用show status; 和 show innodb status\G 来监测。<br /><br /><br /><span style="font-size: x-large">Rails应用程序的优化</span><br /><br />Rails应用程序优化包括ruby解析器的优化，缓存的使用，以及应用代码级别的优化。Stefans Kaes曾经在Railsconf 2006有一个Rails应用程序优化的演讲，他的演讲PPT是极好的Rails性能优化指南，可以在这里下载:<a href="http://www.javaeye.com/topic/24508" target="_blank">http://www.javaeye.com/topic/24508</a>。他还编写了一个用于Rails性能测试的软件包RailsBench，大家可以参考。由于Stefans Kaes的代码优化文档已经写的非常详细了，因此我就不在一一复述，只提出几点对性能影响比较大的方面：<br /><br /><br /><span style="font-size: large">一、ruby解析器的优化</span><br /><br />ruby的解析器性能是很糟糕的，ruby早期的主要用途是取代perl写批量处理的脚本的，并不是为服务器应用编写的，因此在内存分配策略上非常不适合服务器应用。Stefans Kaes编写了一个ruby GC的补丁文件，在railsbench下载包里面提供了。虽然当前Railsbench提供的GC补丁只有针对ruby 1.8.4和1.8.5版本的，但是在ruby 18,6上面使用1.8.5的GC补丁也完全没有问题。GC补丁的作用主要是针对Rails应用开大了ruby的内存堆，可以有效提高内存堆的利用率，降低GC的频率。根据Stefans Kaes提供的测试数据，打补丁并且调整参数以后，GC的频率下降到只有原来的1/10还不到。降低GC频率尽管并不能够提高单个请求的执行速度，但是可以增加整体应用的负载能力。<br /><br />我们在JavaEye的服务器上也使用了GC补丁，并且根据推荐参数进行了调整。在使用GC补丁之后，Web服务器的CPU负载下降了大概15%左右，效果非常显著。当然开大内存堆的代价就是ruby进程会多消耗内存，在我们的服务器上，ruby打补丁之后多消耗了50%左右的物理内存。<br /><br /><br /><span style="font-size: large">二、缓存的使用</span><br /><br />1、对象缓存<br />JavaEye上面关于对象缓存的讨论很多，我们也提供了JavaEye这方面很多数据，因此不展开了。RoR可以使用两个对象缓存，一个是CachedModel，类似Hibernate，比较简单，对Model的CRUD操作自动进行缓存；另外一个是cache_fu，需要自己编码来添加对象缓存，但提供了更多高级机制，目前我们使用的是cache_fu。在使用对象缓存的情况下，应该把查询方法的:include去掉，避免关联查询无法利用缓存的现象。<br /><br />2、查询缓存<br />对于统计类耗时查询，如果不要求实时性，那么可以使用memcache-client将查询结果缓存到memcached里面，例如博客排行榜之类。<br /><br />3、页面局部缓存<br />对象缓存和查询缓存都是降低数据库访问负载的，但如果RoR的负载很高，那么只能依靠页面局部缓存了。传统的互联网web1.0网站很流行采用动态页面静态化技术来提高网站的负载，但是对于web2.0网站来说，每个页面都带有登陆用户的个人信息，页面的很多部分需要实时更新，例如投票，点击统计，digg，显示用户在线状态等等，动态页面静态化非常困难。当然如果你非要采用动态页面静态化，技术上也不是实现不了，可以通过AJAX请求来处理静态页面的动态部分，但是这种解决方案的开发成本过高，而且性能未必会有明显的改善，大家看看新浪和搜狐博客就知道这种技术被应用的有多糟糕了。<br /><br />web2.0网站比较常用使用页面局部缓存，一种情况是页面不需要实时更新的，那么只需要设置一个合理的过期时间就行了，这种情况我们目前使用的比较多；另外一种情况是虽然不需要实时更新，但是会在用户执行某些操作后需要缓存过期，比方说博客个人主页的很多页面，这种情况下缓存过期策略会比较复杂，考虑到合理的开发成本，我们尚未对这样的页面使用局部缓存。<br /><br />此外，Rails的页面局部缓存有一个缺点，就是和页面查询结果对应的Action当中的查询语句要放在View里面，否则每次action里面的查询还是会被执行，但是这样做会破坏程序代码良好的MVC结构。这种情况下，也可以采用另外一个Cache插件:<a href="http://blog.evanweaver.com/articles/2007/12/13/better-rails-caching" target="_blank"> better rails caching</a>，在缓存页面的同时可以缓存Action当中的查询语句。<br /><br /><br /><span style="font-size: large">三、应用代码的优化</span><br /><br />Stefans Kaes的文档里面对应用代码的优化进行了非常详细的介绍，因此我这里只提两个比较重要的注意事项：<br /><br />1、link_to<br />Rails的link_to是非常慢的，它的代码实现过于复杂，特别是Rails1.2引入了REST以后，大量的命名路由被使用，这些命名路由还需要通过一次method_missing，那就更加缓慢了。因此对于被频繁使用的内部URL地址，一定要自己用字符串拼接方式改写，可以很明显提高View的render性能。此外类似的helper还有很多，例如button_tag，image_tag啥啥的，如非必要，尽量不用他的helper<br /><br />2、正则表达式<br />ruby的正则表达式也是极慢，例如auto_fix这个helper的正则表达式就比较复杂，造成的结果就是一但大量使用auto_fix，View的render就明显变慢，类似依赖正则表达式进行字符串过滤的helper有很多，如果需要频繁大量使用，请先自行做benchmark。<br /><br /><br /><br /><span style="font-size: x-large">Rails应用程序的内存泄漏问题和解决</span><br /><br />内存泄漏是服务器端程序经常遇到的，有时候内存泄漏问题会让人很头疼，总体来说，Rails的内存泄漏问题比Java要少得多，这是因为Java内存泄漏最常见的三种情况在Rails当中不存在：<br /><br />1、HttpSession导致的内存泄漏<br />Java程序员喜欢往session里面丢很多东西，最糟糕的是竟然有很多框架软件也肆无忌惮往session里面丢状态数据，但Rails的session是不放在内存里面的，所以无此烦恼。<br /><br />2、数据库连接释放不彻底<br />Java的数据库连接池释放不彻底，以及查询游标释放不彻底，都必然导致内存泄漏。Rails没有数据库连接池，而是每个进程持有一个长连接，因此不存在这个问题，而且由于持有长连接，也不存在Java里面的OpenSessionInView的烦恼。<br /><br />3、用静态变量持有全局共享数据<br />Java程序员很喜欢通过静态全局变量来持有共享数据，但共享数据忘记清理的话，也很容易导致内存泄漏，Ruby是SNA架构，多进程服务器模式，进程间无法共享数据，反而避免了全局共享数据带来的麻烦。<br /><br />但是Rails应用有一种情况：在Ruby代码中调用C写的第三方ruby类库的时候，很容易导致内存泄漏，但这种内存泄漏反而在Java中极其罕见。Ruby本身有GC来管理内存堆，但是代码一旦调用C写的第三方ruby类库，内存堆的分配权就掌握在第三方C库的实现上面了，如果这个C库的代码质量不够好，内存泄漏就不可避免。由于ruby本身性能很差，因此计算量大的功能往往依赖底层的C库来实现，这下内存泄漏的潘多拉魔盒就打开了！而Java性能比较好，功能都是纯Java编写，基本上看不到需要依赖第三方C库的情况，因此比较安全。<br /><br />JavaEye也面临着内存泄漏的困扰，这方面困扰主要来自于Rmagic。Rmagick调用ImageMagick的C库来完成图片的操作，从我们的监测来看，RMagick大多数情况下会缓慢的泄漏内存，在某些特定的图片操作上会急剧的泄漏内存。解决办法就是用mini_magick替代Rmagick，mini_magick是直接调用ImageMagick的mogrify命令，另起一个进程来操作图片，操作完进程就结束了，绝无后患，由于Linux的fork进程开销不大，因此也不必担心性能问题。<br /><br />此外，调用第三方C库的ruby代码编写都需要高度小心，比方说JavaEye使用ferret实现全文检索，根据应用的需要调用ferret的API来编写自己的analyzer，其中在实现token_stream方法上面使用了XXXAnalyzer.new和XXXToken.new，XXXFilter.new，结果内存急剧泄漏，经过检查发现是Analyzer对象不能被反复创建，改成创建后缓存该对象就好了，但是Filter和Token对象却必须每次创建，此外ferret的PerAnalyzerFilter也有内存泄漏问题。由于类库是用C编写的，单纯看API文档或者看源代码片断一般无法判断出里面的内存泄漏陷阱的。<br /><br /><br />当遇到了难以解决和定位的内存泄漏问题，Ruby也有类似Java的内存Profiler工具：<br /><br />1、<a href="http://scottstuff.net/blog/articles/2006/08/17/memory-leak-profiling-with-rails" target="_blank">Memory Profiler</a><br />一个纯ruby编写的内存探测器，原理很简单，就是用ruby的对象引用计数器ObjectSpace.each_object去遍历内存堆中的每个ruby对象，进行统计和分析。用起来很简单，非常适合于开发环境下侦测内存泄漏问题，但不能用在生产环境下，极度影响Rails性能。<br /><br />2、<a href="http://blog.evanweaver.com/files/doc/fauna/bleak_house/files/README.html" target="_blank">Bleak_house</a><br />Bleak_house给Ruby解析器打了补丁，插入相关的指令，可以从底层探测整个ruby内存堆中对象的情况，然后你可以定期dump出来完整的内存堆里面的所有对象，再用bleak工具去分析dump文件，他比上面的工具分析的信息要全面，可以在测试环境和预发布环境下使用，但在生产环境下，也会对应用的性能产生很大的影响，要慎用。<br /><br />JavaEye网站在RoR性能方面的经验就全部分享给大家了，也希望做RoR的朋友都拿出来自己的经验和大家分享，共同学习和促进RoR的应用和普及。
          <br/>
          <span style="color:red;">
            <a href="http://robbin.javaeye.com/blog/157731#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 20 Jan 2008 16:11:36 +0800</pubDate>
        <link>http://robbin.javaeye.com/blog/157731</link>
        <guid>http://robbin.javaeye.com/blog/157731</guid>
      </item>
          <item>
        <title>豆瓣的程序性能真的很惊人，但...</title>
        <author>robbin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://robbin.javaeye.com">robbin</a>&nbsp;
                    链接：<a href="http://robbin.javaeye.com/blog/157104" style="color:red;">http://robbin.javaeye.com/blog/157104</a>&nbsp;
          发表时间: 2008年01月17日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://www.dbanotes.net/arch/douban_web_server.html" target="_blank">http://www.dbanotes.net/arch/douban_web_server.html</a><br /><br />在老冯同学的博客上看到的文章。里面介绍说豆瓣网站的情况如下：<br /><br />一台Web服务器运行Lighttpd，每天处理2500万个request，峰值每秒处理1000个request；<br />一台应用服务器运行Python，每天处理500万PV；<br />数据库服务器运行MySQL，负载情况没有介绍。<br /><br />我对比了一下JavaEye网站的服务器运行情况，我们是一台Web+应用服务器，一台数据库服务器，如下：<br /><br />Web服务器运行Lighttpd，每天处理430万个request，峰值每秒处理150个request，平均每秒处理50个request；<br />Web服务器运行Ruby 1.8.6 + Rails 1.2.6，每天处理70万动态请求(去掉404，301状态的请求，只统计200的)，如果算PV的话，去掉RSS订阅请求，AJAX请求，估计PV在60万左右；<br />数据库服务器运行MySQL，CPU负载不高，在5%-30%之间波动。<br /><br />豆瓣的Lighttpd峰值每秒处理1000个request，到不让人觉得意外，因为Lighttpd本身就是设计能够并发处理上万个request的。但是豆瓣用单台服务器支撑500万动态请求，确实是很惊人的数据！看阿北介绍说，豆瓣的应用服务器是一台单颗双核AMD Opteron，JavaEye的Web服务器是两路老的单核的AMD Opteron，主频是2GHz，豆瓣的应用服务器是新的单颗双核AMD Opteron，主频不详。<br /><br />目前JavaEye的Web服务器运行Lighttpd，Memcached，Email Server和Ruby的FastCGI，除了ruby之外，其他应用消耗的CPU资源都极少，Web服务器在峰值期间的CPU负载在35-50%之间波动，非峰值期间回落到20-30%。假设应用程序不做针对性优化，我估计这台服务器可以支撑到100万到120万PV，但要更高就很困难了。不过JavaEye要达到这样的访问量，估计还得一年时间。到那个时候再想办法也不迟。不过设想到这样的程度，我到宁愿加一台服务器立马解决问题，而不是投入人力去费时耗力的优化程序代码。<br /><br />豆瓣使用的Python性能要比Ruby好很多，但即便如此，在同样硬件条件下，用Python支撑到500万以上，也是非常困难的，可以想像的是大量运用了页面的局部缓存，以及对程序和框架的优化达到了极致，这一点，不得不佩服豆瓣的技术人员的性能优化水准和所下的功夫。<br /><br />不过，对于豆瓣只用一台应用服务器支撑500万PV，我觉得没有必要。豆瓣有2000万人民币的投资，增加一台服务器一次性开支不超过1.5万，每年托管费多支出0.5万而已，九牛一毛。但在今天一个资深程序员月薪都要超过1.5万的情况下，为了节省这点钱而需要对应用程序进行深度优化而投入的人力成本，远远超过2万元。豆瓣新版本刚上线的一段时间之内，网站访问速度非常缓慢，最近速度慢慢的提升上来了，似乎也从侧面证明了这一点。干吗不多部署几台应用服务器，让用户从一开始就享受良好的速度体验呢？而用一台应用服务器支撑，等着优化程序代码来提升访问速度呢？CSDN网站每天有600多万访问量，比豆瓣的访问量略高一些，CSDN有30多台服务器，其实服务器少不见得就有多好，服务器多也不见得就是什么坏事。用投入硬件的方式可以解决的性能问题，总是会比软件优化方式来得成本低。
          <br/>
          <span style="color:red;">
            <a href="http://robbin.javaeye.com/blog/157104#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 17 Jan 2008 22:42:24 +0800</pubDate>
        <link>http://robbin.javaeye.com/blog/157104</link>
        <guid>http://robbin.javaeye.com/blog/157104</guid>
      </item>
          <item>
        <title>RoR部署方案深度剖析</title>
        <author>robbin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://robbin.javaeye.com">robbin</a>&nbsp;
                    链接：<a href="http://robbin.javaeye.com/blog/155542" style="color:red;">http://robbin.javaeye.com/blog/155542</a>&nbsp;
          发表时间: 2008年01月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          RoR的部署方案可谓五花八门，有Apache/Fastcgi方式的，有Nginx/Mongrel方式的，还有lighttpd/Fastcgi方式，也有人使用HAProxy/Mongrel，各种部署方式都是众说纷纭，让人搞不清楚哪种方式更好一些。我的这篇文章就是希望结合我们运营JavaEye网站一年多以来的经验(通过统计Rails的production.log，JavaEye网站目前每天处理超过70万200 OK状态的Ruby动态请求，应该是国内目前负载量最大的RoR应用了)，为大家剖析RoR部署方案的优劣，帮助大家选择适合自己生产环境的RoR部署方式。<br /><br />在讨论部署方案之前，先让我们看一下RoR网站部署的简单架构：<br /><br /><img src="http://robbin.javaeye.com/upload/picture/pic/6947/c4720b28-77e9-3be7-b30e-846836016b42.jpg" /><br /><br />浏览器的HTTP访问请求首先达到Web服务器，充当Web服务器的一般是Lighttpd/Apache/Nginx，如果访问请求包含静态资源，那么Web服务器就会直接从本地硬盘读取静态资源文件，例如图片，JavaScript，CSS等等，返回给客户端浏览器；如果访问请求是动态请求，那么Web服务器把URL请求转发到后端的FastCGI/Mongrel来处理，等到FastCGI/Mongrel处理完请求，将生成的页面数据返回给Web服务器，最后Web服务器把页面数据发送到客户端的浏览器。<br /><br />从RoR的部署方式来看，主要由前端的Web服务器和后端的应用服务器构成：前端的Web服务器可以使用Apache，Lighttpd，Nginx和Litespeed，后端的应用服务器可以使用FastCGI和Mongrel，下面我们分门别类的介绍和剖析：<br /><br />一、介绍Web服务器<br />Web服务器的主要作用有两点：一是处理静态资源，二是将动态请求分发到后端应用服务器，然后接收后端应用服务器生成的页面数据，将其返回浏览器，充当了一个信息沟通的桥梁作用，在本文当中我们重点分析后者的作用。<br /><br />1、Apache 2.2<br /><br />Apache是全球互联网使用最广泛的Web服务器，但在处理静态资源文件上却不是性能最优秀的Web服务器，不过一般情况下，静态资源的访问并不是RoR网站的瓶颈，因此也不必过于在意这一点。<br /><br />Apache 2.2既支持HTTP Proxy方式连接后端的Mongrel应用服务器，也可以通过mod_fastcgi/mod_fcgid来连接FastCGI应用服务器：当以HTTP Proxy方式连接Mongrel的时候，Apache接收Mongrel返回的页面数据的buffer size最大只能开到8KB(默认是4KB或者8KB)，因此当页面数据超过8KB的时候，可能需要Apache和Mongrel之间发生多次交互；当以mod_fastcgi方式连接FastCGI应用服务器的时候，接收返回数据的Buffer size仍然只有8KB而已，如果使用mod_fcgid，那么buffer size为64KB，有了很大的改善。<br /><br />2、Nginx<br /><br />Nginx是俄国人出品的轻量级Web服务器，在处理静态资源方面，据说性能还略微超过Lighttpd，但是Nginx在性能消耗方面略微比Lighttpd要高一些。<br /><br />Nginx内置了良好的HTTP Proxy和FastCGI支持，因此即可以连接Mongrel，也可以连接FastCGI服务器，在这两种情况下，Nginx默认的接收应用服务器返回数据的Buffer Size也只有区区的8KB，但是你可以自行设置更大Buffer Size。<br /><br />3、Lighttpd<br /><br />Lighttpd是全球互联网排名第五的Web服务器，也是近两年来上升最快的Web服务器，特别是很受一些著名Web 2.0大网站的欢迎，例如wikipedia的某些服务器，youtube的视频服务器，在国内，豆瓣网站和JavaEye网站都是Lighttpd的绝对拥护者。在处理静态资源方面，Lighttpd性能远远超过Apache。<br /><br />Lighttpd既支持HTTP Proxy连接Mongrel，也支持FastCGI方式，但是Lighttpd的FastCGI支持在所有流行的Web服务器当中可能是最优秀的，所以用FastCGI的网站都很喜欢Lighttpd。Lighttpd在接收后端应用服务器返回数据的方式上和Apache/Nginx有非常大的区别：<br /><br />Apache/Nginx是针对每个应用服务器连接分配固定Size的Buffer，而且默认只开8KB，这个Size对于现在网页动辄50-100KB的情况来说，显得过于保守，如果应用服务器的返回数据无法一次填满Web服务器的Buffer，那么就会导致应用服务器和Web服务器之间多次数据传输，这对于RoR网站的性能会造成一些相关的影响，我们在后面会详细的分析。<br /><br />Lighttpd并不针对应用服务器的每个连接分配固定的Buffer，而是尽可能的把应用服务器返回的数据一次性接收下来，因此无论应用服务器返回多大的数据量，Lighttpd都是照单全收，胃口非常惊人。<br /><br />4、Litespeed<br /><br />Litespeed是一个商业收费的Web服务器，静态资源处理能力据它自己的评测数据比Lighttpd略高。Litespeed也同时支持HTTP Proxy连接Mongrel和FastCGI连接应用服务器。此外Litespeed专门为单机运行的RoR开发了一个lsapi协议，号称性能最好的RoR通讯协议，比HTTP Proxy和FastCGI都要好。但是lsapi的运行方式有很大缺陷：因为lsapi不是web server启动的时候启动固定数目的ruby进程，而是根据请求繁忙程度，动态创建和销毁ruby进程，貌似节省资源，实则留下很大的黑客攻击漏洞。只要黑客瞬时发起大量动态请求，就会让服务器忙于创建ruby进程而导致CPU资源耗尽，失去响应。<br /><br />由于Litespeed在运行RoR方面并没有表现出比Lighttpd优越之处，而且还是收费软件，企业版本售价在双核CPU上面每年收费499美元，并且也不开源，因此我们就不再把关注点放在Litespeed上面。当然Litespeed收费也不是白收的，它提供了非常好用的基于Web的服务器管理界面，以及非常多的安全性方面的设置参数。<br /><br />5、HAProxy<br /><br />HAProxy并不是一个Web服务器，他既不能处理静态资源，也不能充当浏览器和应用服务器之间的缓冲桥梁，他只是充当了一个请求分发的软件网关作用。ThoughtWorks公司的RubyWorks选择使用HAProxy + Mongrel Cluster的方式来部署RoR应用，不能不说是一个愚蠢的方案。这种方案其实相当于把n个Mongrel应用服务器捆绑起来，直接充当Web服务器，而Mongrel毕竟是一个Ruby写的服务器，无论是网络IO能力，还是静态资源的处理速度，无法和真正的Web服务器相提并论，让Mongrel直接处理静态资源和调度网络IO，会造成服务器资源毫无必要的极大开销，因此HAProxy也不在我们的考虑之列。<br /><br /><br />二、分析应用服务器的处理方式<br /><br />无论是Mongrel还是FastCGI，都能够良好的运行Rails服务器，但是他们在和Web服务器之间的数据传输方式上存在一些差别，而正是这些差别，对部署方式有重大的影响：<br /><br />1、Mongrel<br /><br />Mongrel本身可以直接充当Web服务器，但在这种情况下性能并不会好。因为Mongrel只有HTTP协议的解析部分是用C语言编写的，其余所有代码都是纯Ruby的。在处理静态资源下载上面，Mongrel的实现方式非常低效率，他只是简单的以16KB为单位，依次读入文件内容，再写出到网络Socket端口，其性能远远比不上传统的Web服务器调用操作系统的read()和write()库实现的静态文件下载速度，如果和<a href="http://www.javaeye.com/topic/154538" target="_blank">现代Web服务器实现的sendfile方式的“零拷贝”</a>下载相比，简直就是望尘莫及。<br /><br />Mongrel使用了Ruby的用户线程机制来实现多线程并发，并且使用了一个fastthread补丁，改善了Ruby用户线程的同步互斥锁问题。但是Ruby并不是本地线程，我们也不要对Mongrel的网络IO负载能力抱有什么不切实际的幻想。同时Rails本身也不是线程安全的，因此Mongrel在执行Rails代码的过程中，完全是加锁的状态，那和单进程其实也没有太大差别。<br /><br />因此，当我们使用Mongrel的时候，一般会在前端放置Web服务器，通过HTTP Proxy方式把请求转发给后端的Mongrel应用服务器。在这种情况下，Mongrel只处理动态请求，在运行Rails框架生成页面数据之后，把数据返回给Web服务器就可以了。但是在这种部署方案下，有一个很重要的细节被我们忽视了，Mongrel运行Rails生成的页面数据是怎么返回给Web服务器的呢？通过仔细钻研源代码我们可以搞清楚Mongrel处理Rails请求的细节：<br /><br />1)  Mongrel接收到请求以后，启动一个ruby线程解析请求信息<br />2)  加锁，调用Rails Dispatcher启动Rails框架<br />3)  Rails处理完毕，创建一个StringIO对象，把Rails生成的页面数据写入到StringIO中<br />4)  解锁，把StringIO的数据flush到Web服务器<br /><br />这个StringIO对象其实很重要！它充当了一个输出缓冲区的作用，我们设想一下，当Mongrel作为独立的Web服务器的时候，如果Rails生成的页面比较大，而客户端浏览器下载页面的速度又比较慢，假设没有这个StringIO对象，会发生什么问题？ Rails线程在执行render方法的时候就会被挂住！同步互斥锁没有解锁，Mongrel再也无法处理下一个动态请求了。<br /><br />当Mongrel仅仅作为应用服务器的时候，这个StringIO仍然很重要，为什么？我们前面提到过了，Apache/Nginx的接收缓冲区都只开了8KB，如果页面比较大，Mongrel就没有办法一次性把数据全部推给Web服务器，必须等到Web服务器把接收缓冲区的8K数据推到客户浏览器端以后，清空缓冲区，才能接收下一个8KB的数据。这种情况下，Mongrel必须和Web服务器之间进行多次数据传输，才能完成整个Web响应的过程，显然没有一次性把页面数据全部推给Web服务器快。如果Web服务器使用Lighttpd的话，情况会不一样。当Mongrel把StringIO的数据flush出去的时候，Lighttpd是一次性全部接收下来了，不需要多次交互，因此Lighttpd+Mongrel的RoR网站的实际速度要快于Apache/Nginx+Mongel。<br /><br />Mongrel使用StringIO对象缓存输出结果，在某些特殊的情况下会带来很大的安全隐忧。我们假设使用服务器端程序控制带权限的文件下载，某用户下载的是一个100MB的文件，该用户使用了多线程下载工具，他开了10个线程并发下载，那么每个线程Mongrel在响应之后，都会把整个文件读入到内存的StringIO对象当中，所以总共会创建出来10个StringIO对象保存10份文件内容，所以Mongrel的内存会一下暴涨到1GB以上。而且最可怕的是，即使当用户下载结束以后，Mongrel的内存都不会迅速回落，而是一直保持如此高的内存占用，这是因为Ruby的GC机制不好，不能够及时进行垃圾回收。<br /><br />也许你会觉得不太可能下载100MB那么大的附件，但是以JavaEye网站为例，圈子的共享文件最大允许10MB，只要用户在多台机器上面，每台机器开100个线程下载圈子共享文件，每个Mongrel的内存占用都会立刻超过1GB，用不了几分钟，服务器的物理内存就会被耗尽，网站失去响应。这个缺陷非常容易被别有用心的黑客利用，攻击网站。这也是JavaEye网站为什么始终不用mongrel的原因之一。<br /><br />通过上面的剖析，我们知道Mongrel在使用Lighttpd的时候，可以达到最快的RoR执行速度，但是Lighttpd当前的1.4.18版本的HTTP Proxy的负载均衡和故障切换功能有一些bug，因此一般很少有人会使用这种方式。大多数人都会采用Mongrel搭配Apache2.2或者Nginx，但是正如我们上面做分析的那样，Apache/Nginx的Buffer Size实在是一个很讨厌的限制，特别是Apache只能最大开8KB的Buffer，因此我建议使用Nginx搭配Mongrel，并且把Nginx的Proxy Buffer Size设置的大一些，比如说设置为64KB，以保证大多数页面输出结果可以一次性flush到Web服务器去。<br /><br />2、FastCGI<br /><br />很多人对FastCGI谈虎色变，仿佛FastCGI就是内存泄漏，性能故障的罪魁祸首，又或者嫌弃FastCGI太古老了，已经被淘汰掉的技术了，其实这是一个很大的误解。FastCGI本质上只是一种进程间通讯的协议，虽然是一个比较古老的协议，但是还是比HTTP协议年轻多了，HTTP协议不是照样现在很流行吗？ <br /><br />在PHP/ASP/JSP流行之前，FastCGI曾经非常普及，只不过那个时代的FastCGI程序是用C语言编写的，写起来太费劲，而PHP/ASP/JSP相比之下，写起来就太简单了，所以FastCGI就渐渐被丢到了历史的故纸堆里面。但是最近两年来，由于Ruby和Python的快速Web开发框架的强势崛起，FastCGI仿佛又咸鱼翻身了。<br /><br />当我们以FastCGI方式运行Rails应用服务器的时候，每个FastCGI进程都是单线程运行的，考虑到Rails本身不是线程安全的，所以和Mongrel运行Rails的实际效果是一样的，都是每个进程只能跑一个Rails实例。但是FastCGI在Rails生成页面数据返回给Web服务器的方式和Mongrel截然不同：<br /><br />前面我们说到Mongrel自己开了输出缓冲区，而FastCGI则完全不开任何缓冲区，当Rails执行render方法的时候，FastCGI实际执行的是FCGI::Stream.write方法调用，直接把数据写给Web服务器了。此时如果Web服务器是Apache/Nginx，会发生什么？ <br /><br />如果我们使用mod_fastcgi模块，那么Apache的接收缓冲区就是8KB；<br />如果我们使用mod_fcgid模块，那么Apache的接收缓冲区就是64KB；(mod_fcgid是中国人开发的取代mod_fastcgi的开源项目，在Apache社区很受欢迎，谁敢说中国人只是开源“消费”国？)<br />如果我们使用Nginx服务器，那么默认的接收缓冲区就是8KB，但是可以改得更大；<br /><br />如果页面数据比较大，超过8KB，会怎么样？ FastCGI进程被挂在render方法上！必须等到Web服务器的缓冲区清空，把页面数据全部接收下来以后，FastCGI进程才能结束本次Rails调用，处理下一个请求！所以千万别用Apache/Nginx搭配FastCGI应用服务器，否则你的RoR应用会死的很难看。根据我个人的测试数据表明，同样的测试负载，Apache搭配70个FastCGI进程挂掉，但是Lighttpd搭配30个FastCGI进程轻松跑完！<br /><br />当FastCGI搭配Lighttpd的时候，我们知道Lighttpd会一次性照单全收FastCGI送过来的页面数据，所以FastCGI进程并不会被挂住。如果我们对比一下Lighttpd搭配Mongrel和FastCGI会发现，Lighttpd搭配FastCGI性能最好，为什么呢？<br /><br />Mongrel首先自己会用StringIO缓冲页面数据，然后推送给Lighttpd以后，Lighttpd也在内存当中缓冲了一份页面数据，造成了毫无必要的double buffer的开销。这自然不如FastCGI不做任何缓冲，直接推给Lighttpd性能来得高，内存消耗少了。<br /><br />我们的方案分析到这里，大家应该自己心里有结论了，Lighttpd+FastCGI是性能最佳，服务器资源消耗最少的RoR部署方案，事实上目前RoR网站部署使用最多最流行的也是Lighttpd+FastCGI方式，而JavaEye网站，自然也是这种方式的部署。因此我们可以对各种方案进行一个性能优劣的排队：<br /><br /><div class="quote_title">引用</div><div class="quote_div"><span style="color: red"><strong>Lighttpd+FastCGI  >  Lighttpd+Mongrel  >  Nginx+Mongrel  >  Apache+Mongrel  >  Ngignx+FastCGI  >  Apache+FastCGI</strong></span></div><br /><br />其中Lighttpd+FastCGI是性能最佳方案，而Apache+FastCGI是性能最差方案。<br /><br /><br />有些细心的同学可能会产生一个新的疑问？你说到底，之所以Lighttpd跑RoR性能最好，还是在于Lighttpd接收数据不限定缓冲区的大小，而Apache/Nginx限定了缓冲区大小所至。那为什么Nginx要限制呢？Lighttpd如果不限制的话，会不会导致Lighttpd内存爆掉？<br /><br />Nginx限制Proxy Buffer Size其实也有道理，因为Nginx并不是为RoR量身打造的Web服务器，Nginx最广泛的用途还是高负载大访问量的代理服务器，在Nginx主要的应用场合，如果不做这样的限制，那Nginx端的资源消耗就相当高了，有可能会拖累所代理的服务速度。<br /><br />Lighttpd主要用途之一就是提供高性能的FastCGI支持的Web服务器，所以必须为FastCGI量身打造。Lighttpd端承担的负载越高，就越能有效的加快FastCGI执行速度。其实我们稍微心算一下，假设Lighttpd后面挂1000个FastCGI进程，每个FastCGI进程同时送过来50KB的页面数据，Lighttpd就是全部吃下来，也不过只消耗50MB的内存而已，而事实上1000个FastCGI进程足以支撑每日上千万的大网站了。<br /><br />只有当我们使用服务器端程序控制大文件下载的时候，有可能造成Lighttpd内存暴涨，例如某个用户使用100个线程并发下载JavaEye圈子的共享文件，在没有特殊处理的情况下，Lighttpd将全部吃下100个FastCGI进程送过来的10MB数据，就会立刻暴涨1GB的内存。这种情况怎么办呢？其实我们也有办法让Lighttpd一点内存都不吃， 请看我写的另外一篇文章：<a href="http://www.javaeye.com/topic/154538" target="_blank">RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能</a><br /><br />可能很多人看了我的文章，对结论觉得很诧异，既然Lighttpd+FastCGI这样好，为什么那么多人都推崇Mongrel，否定FastCGI呢？我想，不外乎几个原因：<br /><br />一、Lighttpd+FastCGI配置起来比较专业，而Mongrel配置简单<br /><br />尽管我当初第一次搭建Lighttpd+FastCGI环境没费什么周折，但是我观察到非常多的Ruby程序员很难成功搭建一个Lighttpd+FastCGI的环境出来，很多人连Lighttpd都无法独立的运行起来。这也许是因为很多程序员习惯了Windows开发环境，对于Unix上面通过源代码编译安装的方式过于陌生造成的。而我从97年开始使用Unix，至今已有10年历史，因此搭建这样简单的系统，对我来说不造成什么障碍。<br /><br />而Mongrel就简单了，gem install mongrel安装完毕，mongrel_rails start启动，哪个人不会？毕竟绝大多数开发人员和部署人员不是高手，他们熟悉哪种方式，自然就会推崇哪种方式。<br /><br /><br />二、Mongrel可以独立作为Web服务器运行，开发环境和部署环境统一<br /><br />一般来说，程序员肯定是尽量保持开发环境和部署环境的一致性，避免部署到生产环境出现不测的后果。既然在开发环境熟悉了Mongrel，当然更加愿意在生产环境使用Mongrel，而不愿意碰没有接触过的Lighttpd。<br /><br /><br />三、Mongrel支持HTTP协议，因此不论监控还是集成其他服务都比较简单，容易玩出更多的花活。<br /><br />HTTP协议要比FastCGI协议普及的多，因此通过HTTP方式的监控工具，群集管理工具，集成其他服务的工具都是一抓一大把。而支持FastCGI的第三方工具就少得可怜了。你要玩很多花活出来，用FastCGI的话，就难免得自己开发相应的工具，那当然不如使用Mongrel方便啦。<br /><br />最后，如果你看了这篇文章，想摩拳擦掌的安装一把Lighttpd+FastCGI的话，那么我的这篇文章就是最好的安装指南：<br /><br /><a href="http://www.javaeye.com/topic/43228" target="_blank">在Linux平台上安装和配置Ruby on Rails详解</a>
          <br/>
          <span style="color:red;">
            <a href="http://robbin.javaeye.com/blog/155542#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 14 Jan 2008 03:10:17 +0800</pubDate>
        <link>http://robbin.javaeye.com/blog/155542</link>
        <guid>http://robbin.javaeye.com/blog/155542</guid>
      </item>
          <item>
        <title>RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能</title>
        <author>robbin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://robbin.javaeye.com">robbin</a>&nbsp;
                    链接：<a href="http://robbin.javaeye.com/blog/154538" style="color:red;">http://robbin.javaeye.com/blog/154538</a>&nbsp;
          发表时间: 2008年01月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          传统的Web服务器在处理文件下载的时候，总是先读入文件内容到应用程序内存，然后再把内存当中的内容发送给客户端浏览器。这种方式在应付当今大负载网站，音频视频网站力不从心。sendfile是现代操作系统支持的一种高性能网络IO方式，操作系统内核的sendfile调用可以将文件内容直接推送到网卡的buffer当中，从而避免了Web服务器读写文件的开销，实现了“零拷贝”模式。<br /><br />作为最流行的轻量级Web服务器的翘楚，lighttpd提供了良好的sendfile支持，JavaEye网站服务器使用的就是lighttpd。在Linux操作系统上面，只需要在lighttpd.conf配置文件如下配置，lighttpd就会使用sendfile方式处理静态资源的下载，效率非常高：<br /><br /><div class="quote_title">引用</div><div class="quote_div">server.network-backend = "linux-sendfile"</div><br /><br />但是在某些情况下，我们却无法直接让lighttpd处理文件的下载，比方说JavaEye网站需要统计帖子附件的下载次数，博客相册的点击次数，比方说需要对下载的文件进行权限的控制，特别是对于一些多用户系统，你不能让用户上传的私密文件被其他用户随便下载到，例如JavaEye圈子的共享文件不能够对圈子外的用户开放下载。因此，文件下载目录千万不能放到public目录下，不能让用户直接通过浏览器的URL地址访问到。在这种情况下，文件下载必须由服务器端应用程序来处理。<br /><br />在RoR应用当中，我们可以在controller中使用send_file方法来控制文件的下载。send_file方法将下载的文件以4KB为单位写到一个输出流去。如果我们使用mongrel应用服务器的话，mongrel会在内存当中创建一个StringIO对象，把整个下载文件完整的读入内存，然后再向客户端或者前端的Web服务器写出。如果我们使用fcgi来运行RoR的话，fcgi会直接把输出流的内容向前端的Web服务器写出。<br /><br />毫无疑问，我们可以看到这种下载处理方式有很大的性能缺陷：<br /><br />1、当使用mongrel的时候，如果下载文件很大，会导致mongrel内存暴涨！<br /><br />mongrel创建一个StringIO对象缓存整个输出内容，我们假设用户下载的是一个100MB的文件，该用户又很喜欢用多线程下载工具，他开了10个线程并发下载，那么mongrel的内存占用会暴涨1GB以上。而且最可怕的是，即使当用户下载结束以后，mongrel的内存都不会迅速回落，而是一直保持如此高的内存占用。这个缺陷非常容易被别有用心的黑客利用，攻击网站。这也是JavaEye网站为什么始终不用mongrel的原因之一。<br /><br /><br />2、当使用fcgi的时候，如果前端Web服务器没有足够大buffer，会导致fcgi进程被挂住<br /><br />fcgi自己不开output buffer，而是实时写出输出内容，如果前端Web服务器用的是lighttpd，那么你很幸运，lighttpd会照单全收，一个字节都不拉下；如果前端Web服务器用的是nginx/apache，那么你很不幸，nginx/apache默认只开8K的buffer，收不下的那就对不起了，您慢点嘞，fcgi进程就被挂住了，只要客户端浏览器下载不结束，fcgi进程就被一直占用。<br /><br />3、即使使用lighttpd+fcgi，也会对服务器造成不小的性能开销<br /><br />lighttpd+fcgi是最理想的Rails部署环境，JavaEye网站使用的就是lighttpd+fcgi。当ruby程序执行send_file开始下载的时候，fcgi会以4KB为单位读入文件内容，然后立刻写出到lighttpd去，而lighttpd照单全收。因此当下载文件被完整的通过fcgi被flush到lighttpd的内存里面去以后，即使你杀掉fcgi进程，都丝毫不会影响文件下载。<br /><br />也许你会问，lighttpd都吃下来文件内容，内存会不会暴涨？会的，我们假设同样的用户场景，某用户启动10个线程下载100MB的文件，fcgi进程内存不会发生变化，但是lighttpd会暴涨1GB。但所幸的是lighttpd的内存管理的不错，一旦用户取消下载，或者下载完毕，lighttpd立刻释放掉1GB的内存。<br /><br />但是无论怎么说，ruby还是需要完整的读取下载文件，而lighttpd也需要开辟足够大的内存，处理整个文件的下载过程，对服务器开销还是很大的。我们的问题是，能不能让带权限控制的文件下载像lighttpd下载静态资源文件那样快，开销那样小呢？答案就是X-sendfile！<br /><br />使用X-sendfile方式，服务器端应用程序不需要读取下载文件了，只需要设置response的header信息就足够了，此外还要附加一个信息“X-LIGHTTPD-send-file”信息给lighttpd，告诉lighttpd，文件下载我就不管了，你自己看着办吧：<br /><br /><pre name="code" class="ruby">
response.headers['Content-Type'] = @attachment.content_type
response.headers['Content-Disposition'] = "attachment; filename=\"#{URI.encode(@attachment.filename)}\"" 
response.headers['Content-Length'] = @attachment.size
response.headers["X-LIGHTTPD-send-file"] = @attachment.public_filename
render :nothing => true
</pre><br /><br />X-LIGHTTPD-send-file告诉lighttpd，去硬盘的哪个路径找要下载的文件，最后一行啥都不输出了，下载不用ruby来管了。<br /><br />而lighttpd收到X-LIGHTTPD-send-file信息以后，就会找到硬盘该文件