- 浏览: 4826327 次
- 性别:
- 来自: 上海
博客专栏
-
robbin谈管理
浏览量:137498
文章分类
最新评论
-
xly1981:
领导者是团队的灵魂。深入一线的过程,包括代码review,能帮 ...
robbin谈管理:改造团队的经验(2) -
jiehuangwei:
像这种总结比较性的ppt文档可以多发啊
Web并发模型粗浅探讨 -
linux1308:
看完学习到了很多东西,感谢推荐!
推荐一篇很好的RoR部署方案性能评测 -
zweite:
直接对搜索的结果进行缓存是不是会更快一点呢
漫谈应用缓存的命中率问题 -
kaogua:
现在已经是ruby2.0了, 不知道这个的效率是怎么样的, 是 ...
Ruby作为服务器端应用已经成熟了
RoR的部署方案可谓五花八门,有Apache/Fastcgi方式的,有Nginx/Mongrel方式的,还有lighttpd/Fastcgi方式,也有人使用HAProxy/Mongrel,各种部署方式都是众说纷纭,让人搞不清楚哪种方式更好一些。我的这篇文章就是希望结合我们运营JavaEye网站一年多以来的经验(通过统计Rails的production.log,JavaEye网站目前每天处理超过70万200 OK状态的Ruby动态请求,应该是国内目前负载量最大的RoR应用了),为大家剖析RoR部署方案的优劣,帮助大家选择适合自己生产环境的RoR部署方式。
在讨论部署方案之前,先让我们看一下RoR网站部署的简单架构:
浏览器的HTTP访问请求首先达到Web服务器,充当Web服务器的一般是Lighttpd/Apache/Nginx,如果访问请求包含静态资源,那么Web服务器就会直接从本地硬盘读取静态资源文件,例如图片,JavaScript,CSS等等,返回给客户端浏览器;如果访问请求是动态请求,那么Web服务器把URL请求转发到后端的FastCGI/Mongrel来处理,等到FastCGI/Mongrel处理完请求,将生成的页面数据返回给Web服务器,最后Web服务器把页面数据发送到客户端的浏览器。
从RoR的部署方式来看,主要由前端的Web服务器和后端的应用服务器构成:前端的Web服务器可以使用Apache,Lighttpd,Nginx和Litespeed,后端的应用服务器可以使用FastCGI和Mongrel,下面我们分门别类的介绍和剖析:
一、介绍Web服务器
Web服务器的主要作用有两点:一是处理静态资源,二是将动态请求分发到后端应用服务器,然后接收后端应用服务器生成的页面数据,将其返回浏览器,充当了一个信息沟通的桥梁作用,在本文当中我们重点分析后者的作用。
1、Apache 2.2
Apache是全球互联网使用最广泛的Web服务器,但在处理静态资源文件上却不是性能最优秀的Web服务器,不过一般情况下,静态资源的访问并不是RoR网站的瓶颈,因此也不必过于在意这一点。
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,有了很大的改善。
2、Nginx
Nginx是俄国人出品的轻量级Web服务器,在处理静态资源方面,据说性能还略微超过Lighttpd的10%,而且资源消耗更小。
Nginx内置了良好的HTTP Proxy和FastCGI支持,因此即可以连接Mongrel,也可以连接FastCGI服务器,在这两种情况下,Nginx默认的接收应用服务器返回数据的Buffer Size也只有区区的8KB,但是你可以自行设置更大Buffer Size。
3、Lighttpd
Lighttpd是全球互联网排名第五的Web服务器,也是近两年来上升最快的Web服务器,特别是很受一些著名Web 2.0大网站的欢迎,例如wikipedia的某些服务器,youtube的视频服务器,在国内,豆瓣网站和JavaEye网站都是Lighttpd的绝对拥护者。在处理静态资源方面,Lighttpd性能远远超过Apache。
Lighttpd既支持HTTP Proxy连接Mongrel,也支持FastCGI方式,但是Lighttpd的FastCGI支持在所有流行的Web服务器当中可能是最优秀的,所以用FastCGI的网站都很喜欢Lighttpd。Lighttpd在接收后端应用服务器返回数据的方式上和Apache/Nginx有非常大的区别:
Apache/Nginx是针对每个应用服务器连接分配固定Size的Buffer,而且默认只开8KB,这个Size对于现在网页动辄50-100KB的情况来说,显得过于保守,如果应用服务器的返回数据无法一次填满Web服务器的Buffer,那么就会导致应用服务器和Web服务器之间多次数据传输,这对于RoR网站的性能会造成一些相关的影响,我们在后面会详细的分析。
Lighttpd并不针对应用服务器的每个连接分配固定的Buffer,而是尽可能的把应用服务器返回的数据一次性接收下来,因此无论应用服务器返回多大的数据量,Lighttpd都是照单全收,胃口非常惊人。
4、Litespeed
Litespeed是一个商业收费的Web服务器,静态资源处理能力据它自己的评测数据比Lighttpd略高。Litespeed也同时支持HTTP Proxy连接Mongrel和FastCGI连接应用服务器。此外Litespeed专门为单机运行的RoR开发了一个lsapi协议,号称性能最好的RoR通讯协议,比HTTP Proxy和FastCGI都要好。但是lsapi的运行方式有很大缺陷:因为lsapi不是web server启动的时候启动固定数目的ruby进程,而是根据请求繁忙程度,动态创建和销毁ruby进程,貌似节省资源,实则留下很大的黑客攻击漏洞。只要黑客瞬时发起大量动态请求,就会让服务器忙于创建ruby进程而导致CPU资源耗尽,失去响应。
由于Litespeed在运行RoR方面并没有表现出比Lighttpd优越之处,而且还是收费软件,企业版本售价在双核CPU上面每年收费499美元,并且也不开源,因此我们就不再把关注点放在Litespeed上面。当然Litespeed收费也不是白收的,它提供了非常好用的基于Web的服务器管理界面,以及非常多的安全性方面的设置参数。
5、HAProxy
HAProxy并不是一个Web服务器,他既不能处理静态资源,也不能充当浏览器和应用服务器之间的缓冲桥梁,他只是充当了一个请求分发的软件网关作用。ThoughtWorks公司的RubyWorks选择使用HAProxy + Mongrel Cluster的方式来部署RoR应用,不能不说是一个愚蠢的方案。这种方案其实相当于把n个Mongrel应用服务器捆绑起来,直接充当Web服务器,而Mongrel毕竟是一个Ruby写的服务器,无论是网络IO能力,还是静态资源的处理速度,无法和真正的Web服务器相提并论,让Mongrel直接处理静态资源和调度网络IO,会造成服务器资源毫无必要的极大开销,因此HAProxy也不在我们的考虑之列。
二、分析应用服务器的处理方式
无论是Mongrel还是FastCGI,都能够良好的运行Rails服务器,但是他们在和Web服务器之间的数据传输方式上存在一些差别,而正是这些差别,对部署方式有重大的影响:
1、Mongrel
Mongrel本身可以直接充当Web服务器,但在这种情况下性能并不会好。因为Mongrel只有HTTP协议的解析部分是用C语言编写的,其余所有代码都是纯Ruby的。在处理静态资源下载上面,Mongrel的实现方式非常低效率,他只是简单的以16KB为单位,依次读入文件内容,再写出到网络Socket端口,其性能远远比不上传统的Web服务器调用操作系统的read()和write()库实现的静态文件下载速度,如果和现代Web服务器实现的sendfile方式的“零拷贝”下载相比,简直就是望尘莫及。
Mongrel使用了Ruby的用户线程机制来实现多线程并发,并且使用了一个fastthread补丁,改善了Ruby用户线程的同步互斥锁问题。但是Ruby并不是本地线程,我们也不要对Mongrel的网络IO负载能力抱有什么不切实际的幻想。同时Rails本身也不是线程安全的,因此Mongrel在执行Rails代码的过程中,完全是加锁的状态,那和单进程其实也没有太大差别。
因此,当我们使用Mongrel的时候,一般会在前端放置Web服务器,通过HTTP Proxy方式把请求转发给后端的Mongrel应用服务器。在这种情况下,Mongrel只处理动态请求,在运行Rails框架生成页面数据之后,把数据返回给Web服务器就可以了。但是在这种部署方案下,有一个很重要的细节被我们忽视了,Mongrel运行Rails生成的页面数据是怎么返回给Web服务器的呢?通过仔细钻研源代码我们可以搞清楚Mongrel处理Rails请求的细节:
1) Mongrel接收到请求以后,启动一个ruby线程解析请求信息
2) 加锁,调用Rails Dispatcher启动Rails框架
3) Rails处理完毕,创建一个StringIO对象,把Rails生成的页面数据写入到StringIO中
4) 解锁,把StringIO的数据flush到Web服务器
这个StringIO对象其实很重要!它充当了一个输出缓冲区的作用,我们设想一下,当Mongrel作为独立的Web服务器的时候,如果Rails生成的页面比较大,而客户端浏览器下载页面的速度又比较慢,假设没有这个StringIO对象,会发生什么问题? Rails线程在执行render方法的时候就会被挂住!同步互斥锁没有解锁,Mongrel再也无法处理下一个动态请求了。
当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。
Mongrel使用StringIO对象缓存输出结果,在某些特殊的情况下会带来很大的安全隐忧。我们假设使用服务器端程序控制带权限的文件下载,某用户下载的是一个100MB的文件,该用户使用了多线程下载工具,他开了10个线程并发下载,那么每个线程Mongrel在响应之后,都会把整个文件读入到内存的StringIO对象当中,所以总共会创建出来10个StringIO对象保存10份文件内容,所以Mongrel的内存会一下暴涨到1GB以上。而且最可怕的是,即使当用户下载结束以后,Mongrel的内存都不会迅速回落,而是一直保持如此高的内存占用,这是因为Ruby的GC机制不好,不能够及时进行垃圾回收。
也许你会觉得不太可能下载100MB那么大的附件,但是以JavaEye网站为例,圈子的共享文件最大允许10MB,只要用户在多台机器上面,每台机器开100个线程下载圈子共享文件,每个Mongrel的内存占用都会立刻超过1GB,用不了几分钟,服务器的物理内存就会被耗尽,网站失去响应。这个缺陷非常容易被别有用心的黑客利用,攻击网站。这也是JavaEye网站为什么始终不用mongrel的原因之一。
通过上面的剖析,我们知道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服务器去。
2、FastCGI
很多人对FastCGI谈虎色变,仿佛FastCGI就是内存泄漏,性能故障的罪魁祸首,又或者嫌弃FastCGI太古老了,已经被淘汰掉的技术了,其实这是一个很大的误解。FastCGI本质上只是一种进程间通讯的协议,虽然是一个比较古老的协议,但是还是比HTTP协议年轻多了,HTTP协议不是照样现在很流行吗?
在PHP/ASP/JSP流行之前,FastCGI曾经非常普及,只不过那个时代的FastCGI程序是用C语言编写的,写起来太费劲,而PHP/ASP/JSP相比之下,写起来就太简单了,所以FastCGI就渐渐被丢到了历史的故纸堆里面。但是最近两年来,由于Ruby和Python的快速Web开发框架的强势崛起,FastCGI仿佛又咸鱼翻身了。
当我们以FastCGI方式运行Rails应用服务器的时候,每个FastCGI进程都是单线程运行的,考虑到Rails本身不是线程安全的,所以和Mongrel运行Rails的实际效果是一样的,都是每个进程只能跑一个Rails实例。但是FastCGI在Rails生成页面数据返回给Web服务器的方式和Mongrel截然不同:
前面我们说到Mongrel自己开了输出缓冲区,而FastCGI则完全不开任何缓冲区,当Rails执行render方法的时候,FastCGI实际执行的是FCGI::Stream.write方法调用,直接把数据写给Web服务器了。此时如果Web服务器是Apache/Nginx,会发生什么?
如果我们使用mod_fastcgi模块,那么Apache的接收缓冲区就是8KB;
如果我们使用mod_fcgid模块,那么Apache的接收缓冲区就是64KB;(mod_fcgid是中国人开发的取代mod_fastcgi的开源项目,在Apache社区很受欢迎,谁敢说中国人只是开源“消费”国?)
如果我们使用Nginx服务器,那么默认的接收缓冲区就是8KB,但是可以改得更大;
如果页面数据比较大,超过8KB,会怎么样? FastCGI进程被挂在render方法上!必须等到Web服务器的缓冲区清空,把页面数据全部接收下来以后,FastCGI进程才能结束本次Rails调用,处理下一个请求!所以千万别用Apache/Nginx搭配FastCGI应用服务器,否则你的RoR应用会死的很难看。根据我个人的测试数据表明,同样的测试负载,Apache搭配70个FastCGI进程挂掉,但是Lighttpd搭配30个FastCGI进程轻松跑完!
当FastCGI搭配Lighttpd的时候,我们知道Lighttpd会一次性照单全收FastCGI送过来的页面数据,所以FastCGI进程并不会被挂住。如果我们对比一下Lighttpd搭配Mongrel和FastCGI会发现,Lighttpd搭配FastCGI性能最好,为什么呢?
Mongrel首先自己会用StringIO缓冲页面数据,然后推送给Lighttpd以后,Lighttpd也在内存当中缓冲了一份页面数据,造成了毫无必要的double buffer的开销。这自然不如FastCGI不做任何缓冲,直接推给Lighttpd性能来得高,内存消耗少了。
我们的方案分析到这里,大家应该自己心里有结论了,Lighttpd+FastCGI是性能最佳,服务器资源消耗最少的RoR部署方案,事实上目前RoR网站部署使用最多最流行的也是Lighttpd+FastCGI方式,而JavaEye网站,自然也是这种方式的部署。因此我们可以对各种方案进行一个性能优劣的排队:
其中Lighttpd+FastCGI是性能最佳方案,而Apache+FastCGI是性能最差方案。
有些细心的同学可能会产生一个新的疑问?你说到底,之所以Lighttpd跑RoR性能最好,还是在于Lighttpd接收数据不限定缓冲区的大小,而Apache/Nginx限定了缓冲区大小所至。那为什么Nginx要限制呢?Lighttpd如果不限制的话,会不会导致Lighttpd内存爆掉?
Nginx限制Proxy Buffer Size其实也有道理,因为Nginx并不是为RoR量身打造的Web服务器,Nginx最广泛的用途还是高负载大访问量的代理服务器,在Nginx主要的应用场合,如果不做这样的限制,那Nginx端的资源消耗就相当高了,有可能会拖累所代理的服务速度。
Lighttpd主要用途之一就是提供高性能的FastCGI支持的Web服务器,所以必须为FastCGI量身打造。Lighttpd端承担的负载越高,就越能有效的加快FastCGI执行速度。其实我们稍微心算一下,假设Lighttpd后面挂1000个FastCGI进程,每个FastCGI进程同时送过来50KB的页面数据,Lighttpd就是全部吃下来,也不过只消耗50MB的内存而已,而事实上1000个FastCGI进程足以支撑每日上千万的大网站了。
只有当我们使用服务器端程序控制大文件下载的时候,有可能造成Lighttpd内存暴涨,例如某个用户使用100个线程并发下载JavaEye圈子的共享文件,在没有特殊处理的情况下,Lighttpd将全部吃下100个FastCGI进程送过来的10MB数据,就会立刻暴涨1GB的内存。这种情况怎么办呢?其实我们也有办法让Lighttpd一点内存都不吃, 请看我写的另外一篇文章:RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能
可能很多人看了我的文章,对结论觉得很诧异,既然Lighttpd+FastCGI这样好,为什么那么多人都推崇Mongrel,否定FastCGI呢?我想,不外乎几个原因:
一、Lighttpd+FastCGI配置起来比较专业,而Mongrel配置简单
尽管我当初第一次搭建Lighttpd+FastCGI环境没费什么周折,但是我观察到非常多的Ruby程序员很难成功搭建一个Lighttpd+FastCGI的环境出来,很多人连Lighttpd都无法独立的运行起来。这也许是因为很多程序员习惯了Windows开发环境,对于Unix上面通过源代码编译安装的方式过于陌生造成的。而我从97年开始使用Unix,至今已有10年历史,因此搭建这样简单的系统,对我来说不造成什么障碍。
而Mongrel就简单了,gem install mongrel安装完毕,mongrel_rails start启动,哪个人不会?毕竟绝大多数开发人员和部署人员不是高手,他们熟悉哪种方式,自然就会推崇哪种方式。
二、Mongrel可以独立作为Web服务器运行,开发环境和部署环境统一
一般来说,程序员肯定是尽量保持开发环境和部署环境的一致性,避免部署到生产环境出现不测的后果。既然在开发环境熟悉了Mongrel,当然更加愿意在生产环境使用Mongrel,而不愿意碰没有接触过的Lighttpd。
三、Mongrel支持HTTP协议,因此不论监控还是集成其他服务都比较简单,容易玩出更多的花活。
HTTP协议要比FastCGI协议普及的多,因此通过HTTP方式的监控工具,群集管理工具,集成其他服务的工具都是一抓一大把。而支持FastCGI的第三方工具就少得可怜了。你要玩很多花活出来,用FastCGI的话,就难免得自己开发相应的工具,那当然不如使用Mongrel方便啦。
最后,如果你看了这篇文章,想摩拳擦掌的安装一把Lighttpd+FastCGI的话,那么我的这篇文章就是最好的安装指南:
在Linux平台上安装和配置Ruby on Rails详解
我还真的没有注意到这个问题,刚才研究了一下,发现Lighttpd的确做的很棒!具体的过程是这样的:
Lighttpd在接收到POST请求以后,会在硬盘的/var/tmp目录下面创建相应的临时文件,每个临时文件最大1MB,如果POST请求超过1MB,会创建更多的硬盘临时文件。在处理整个文件上传的过程中,Lighttpd都不会和FastCGI打交道,即使你杀掉FastCGI进程,文件上传过程也不会受什么影响。
当Lighttpd完整的收下来整个POST数据以后,才会将数据推给FastCGI进程去处理。
因此,当上传大文件,整个上传过程无论多慢,都只是Lighttpd在处理,并不会影响到FastCGI进程。但是如果黑客刻意上传非常大的文件,比如说1GB的大文件,当Lighttpd完整的接受下来以后,还是会一股脑推给FastCGI,导致FastCGI的内存暴涨。要解决这个问题,可以在Lighttpd端设置request的最大限制,例如:
设置为10MB,这样黑客要伪造POST提交,最大只允许10MB,就可以解决问题了。
一个FastCGI进程只能运行一个Rails实例。你要分别运行多个应用,当然要开多个FastCGI进程了。
我没有说过FastCGI比Mongrel好,每种方式有自己适合的运行环境,无所谓好坏。我只是说FastCGI搭配Lighttpd会比Mongrel好。如果你用FastCGI搭配Apache/Nginx,FastCGI就会很糟糕。
我不了解HostingRails,但作为虚拟主机提供商,使用Mongrel,不需要他提供额外的Web服务器和相关的配置,每个Mongrel独立的管理,他当然喜欢这种方式了。
《Web开发敏捷之道》的部署那一章节是DHH本人所写,但是第二版部署章节的作者叫做James Duncan Davidson,写的比第一版内容差多了,让我不得不保留第一版作为参考。这也是为什么我家里的书架上第一版第二版都放在一起,而我没有把第一版给扔掉的原因。
在讨论部署方案之前,先让我们看一下RoR网站部署的简单架构:
浏览器的HTTP访问请求首先达到Web服务器,充当Web服务器的一般是Lighttpd/Apache/Nginx,如果访问请求包含静态资源,那么Web服务器就会直接从本地硬盘读取静态资源文件,例如图片,JavaScript,CSS等等,返回给客户端浏览器;如果访问请求是动态请求,那么Web服务器把URL请求转发到后端的FastCGI/Mongrel来处理,等到FastCGI/Mongrel处理完请求,将生成的页面数据返回给Web服务器,最后Web服务器把页面数据发送到客户端的浏览器。
从RoR的部署方式来看,主要由前端的Web服务器和后端的应用服务器构成:前端的Web服务器可以使用Apache,Lighttpd,Nginx和Litespeed,后端的应用服务器可以使用FastCGI和Mongrel,下面我们分门别类的介绍和剖析:
一、介绍Web服务器
Web服务器的主要作用有两点:一是处理静态资源,二是将动态请求分发到后端应用服务器,然后接收后端应用服务器生成的页面数据,将其返回浏览器,充当了一个信息沟通的桥梁作用,在本文当中我们重点分析后者的作用。
1、Apache 2.2
Apache是全球互联网使用最广泛的Web服务器,但在处理静态资源文件上却不是性能最优秀的Web服务器,不过一般情况下,静态资源的访问并不是RoR网站的瓶颈,因此也不必过于在意这一点。
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,有了很大的改善。
2、Nginx
Nginx是俄国人出品的轻量级Web服务器,在处理静态资源方面,据说性能还略微超过Lighttpd的10%,而且资源消耗更小。
Nginx内置了良好的HTTP Proxy和FastCGI支持,因此即可以连接Mongrel,也可以连接FastCGI服务器,在这两种情况下,Nginx默认的接收应用服务器返回数据的Buffer Size也只有区区的8KB,但是你可以自行设置更大Buffer Size。
3、Lighttpd
Lighttpd是全球互联网排名第五的Web服务器,也是近两年来上升最快的Web服务器,特别是很受一些著名Web 2.0大网站的欢迎,例如wikipedia的某些服务器,youtube的视频服务器,在国内,豆瓣网站和JavaEye网站都是Lighttpd的绝对拥护者。在处理静态资源方面,Lighttpd性能远远超过Apache。
Lighttpd既支持HTTP Proxy连接Mongrel,也支持FastCGI方式,但是Lighttpd的FastCGI支持在所有流行的Web服务器当中可能是最优秀的,所以用FastCGI的网站都很喜欢Lighttpd。Lighttpd在接收后端应用服务器返回数据的方式上和Apache/Nginx有非常大的区别:
Apache/Nginx是针对每个应用服务器连接分配固定Size的Buffer,而且默认只开8KB,这个Size对于现在网页动辄50-100KB的情况来说,显得过于保守,如果应用服务器的返回数据无法一次填满Web服务器的Buffer,那么就会导致应用服务器和Web服务器之间多次数据传输,这对于RoR网站的性能会造成一些相关的影响,我们在后面会详细的分析。
Lighttpd并不针对应用服务器的每个连接分配固定的Buffer,而是尽可能的把应用服务器返回的数据一次性接收下来,因此无论应用服务器返回多大的数据量,Lighttpd都是照单全收,胃口非常惊人。
4、Litespeed
Litespeed是一个商业收费的Web服务器,静态资源处理能力据它自己的评测数据比Lighttpd略高。Litespeed也同时支持HTTP Proxy连接Mongrel和FastCGI连接应用服务器。此外Litespeed专门为单机运行的RoR开发了一个lsapi协议,号称性能最好的RoR通讯协议,比HTTP Proxy和FastCGI都要好。但是lsapi的运行方式有很大缺陷:因为lsapi不是web server启动的时候启动固定数目的ruby进程,而是根据请求繁忙程度,动态创建和销毁ruby进程,貌似节省资源,实则留下很大的黑客攻击漏洞。只要黑客瞬时发起大量动态请求,就会让服务器忙于创建ruby进程而导致CPU资源耗尽,失去响应。
由于Litespeed在运行RoR方面并没有表现出比Lighttpd优越之处,而且还是收费软件,企业版本售价在双核CPU上面每年收费499美元,并且也不开源,因此我们就不再把关注点放在Litespeed上面。当然Litespeed收费也不是白收的,它提供了非常好用的基于Web的服务器管理界面,以及非常多的安全性方面的设置参数。
5、HAProxy
HAProxy并不是一个Web服务器,他既不能处理静态资源,也不能充当浏览器和应用服务器之间的缓冲桥梁,他只是充当了一个请求分发的软件网关作用。ThoughtWorks公司的RubyWorks选择使用HAProxy + Mongrel Cluster的方式来部署RoR应用,不能不说是一个愚蠢的方案。这种方案其实相当于把n个Mongrel应用服务器捆绑起来,直接充当Web服务器,而Mongrel毕竟是一个Ruby写的服务器,无论是网络IO能力,还是静态资源的处理速度,无法和真正的Web服务器相提并论,让Mongrel直接处理静态资源和调度网络IO,会造成服务器资源毫无必要的极大开销,因此HAProxy也不在我们的考虑之列。
二、分析应用服务器的处理方式
无论是Mongrel还是FastCGI,都能够良好的运行Rails服务器,但是他们在和Web服务器之间的数据传输方式上存在一些差别,而正是这些差别,对部署方式有重大的影响:
1、Mongrel
Mongrel本身可以直接充当Web服务器,但在这种情况下性能并不会好。因为Mongrel只有HTTP协议的解析部分是用C语言编写的,其余所有代码都是纯Ruby的。在处理静态资源下载上面,Mongrel的实现方式非常低效率,他只是简单的以16KB为单位,依次读入文件内容,再写出到网络Socket端口,其性能远远比不上传统的Web服务器调用操作系统的read()和write()库实现的静态文件下载速度,如果和现代Web服务器实现的sendfile方式的“零拷贝”下载相比,简直就是望尘莫及。
Mongrel使用了Ruby的用户线程机制来实现多线程并发,并且使用了一个fastthread补丁,改善了Ruby用户线程的同步互斥锁问题。但是Ruby并不是本地线程,我们也不要对Mongrel的网络IO负载能力抱有什么不切实际的幻想。同时Rails本身也不是线程安全的,因此Mongrel在执行Rails代码的过程中,完全是加锁的状态,那和单进程其实也没有太大差别。
因此,当我们使用Mongrel的时候,一般会在前端放置Web服务器,通过HTTP Proxy方式把请求转发给后端的Mongrel应用服务器。在这种情况下,Mongrel只处理动态请求,在运行Rails框架生成页面数据之后,把数据返回给Web服务器就可以了。但是在这种部署方案下,有一个很重要的细节被我们忽视了,Mongrel运行Rails生成的页面数据是怎么返回给Web服务器的呢?通过仔细钻研源代码我们可以搞清楚Mongrel处理Rails请求的细节:
1) Mongrel接收到请求以后,启动一个ruby线程解析请求信息
2) 加锁,调用Rails Dispatcher启动Rails框架
3) Rails处理完毕,创建一个StringIO对象,把Rails生成的页面数据写入到StringIO中
4) 解锁,把StringIO的数据flush到Web服务器
这个StringIO对象其实很重要!它充当了一个输出缓冲区的作用,我们设想一下,当Mongrel作为独立的Web服务器的时候,如果Rails生成的页面比较大,而客户端浏览器下载页面的速度又比较慢,假设没有这个StringIO对象,会发生什么问题? Rails线程在执行render方法的时候就会被挂住!同步互斥锁没有解锁,Mongrel再也无法处理下一个动态请求了。
当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。
Mongrel使用StringIO对象缓存输出结果,在某些特殊的情况下会带来很大的安全隐忧。我们假设使用服务器端程序控制带权限的文件下载,某用户下载的是一个100MB的文件,该用户使用了多线程下载工具,他开了10个线程并发下载,那么每个线程Mongrel在响应之后,都会把整个文件读入到内存的StringIO对象当中,所以总共会创建出来10个StringIO对象保存10份文件内容,所以Mongrel的内存会一下暴涨到1GB以上。而且最可怕的是,即使当用户下载结束以后,Mongrel的内存都不会迅速回落,而是一直保持如此高的内存占用,这是因为Ruby的GC机制不好,不能够及时进行垃圾回收。
也许你会觉得不太可能下载100MB那么大的附件,但是以JavaEye网站为例,圈子的共享文件最大允许10MB,只要用户在多台机器上面,每台机器开100个线程下载圈子共享文件,每个Mongrel的内存占用都会立刻超过1GB,用不了几分钟,服务器的物理内存就会被耗尽,网站失去响应。这个缺陷非常容易被别有用心的黑客利用,攻击网站。这也是JavaEye网站为什么始终不用mongrel的原因之一。
通过上面的剖析,我们知道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服务器去。
2、FastCGI
很多人对FastCGI谈虎色变,仿佛FastCGI就是内存泄漏,性能故障的罪魁祸首,又或者嫌弃FastCGI太古老了,已经被淘汰掉的技术了,其实这是一个很大的误解。FastCGI本质上只是一种进程间通讯的协议,虽然是一个比较古老的协议,但是还是比HTTP协议年轻多了,HTTP协议不是照样现在很流行吗?
在PHP/ASP/JSP流行之前,FastCGI曾经非常普及,只不过那个时代的FastCGI程序是用C语言编写的,写起来太费劲,而PHP/ASP/JSP相比之下,写起来就太简单了,所以FastCGI就渐渐被丢到了历史的故纸堆里面。但是最近两年来,由于Ruby和Python的快速Web开发框架的强势崛起,FastCGI仿佛又咸鱼翻身了。
当我们以FastCGI方式运行Rails应用服务器的时候,每个FastCGI进程都是单线程运行的,考虑到Rails本身不是线程安全的,所以和Mongrel运行Rails的实际效果是一样的,都是每个进程只能跑一个Rails实例。但是FastCGI在Rails生成页面数据返回给Web服务器的方式和Mongrel截然不同:
前面我们说到Mongrel自己开了输出缓冲区,而FastCGI则完全不开任何缓冲区,当Rails执行render方法的时候,FastCGI实际执行的是FCGI::Stream.write方法调用,直接把数据写给Web服务器了。此时如果Web服务器是Apache/Nginx,会发生什么?
如果我们使用mod_fastcgi模块,那么Apache的接收缓冲区就是8KB;
如果我们使用mod_fcgid模块,那么Apache的接收缓冲区就是64KB;(mod_fcgid是中国人开发的取代mod_fastcgi的开源项目,在Apache社区很受欢迎,谁敢说中国人只是开源“消费”国?)
如果我们使用Nginx服务器,那么默认的接收缓冲区就是8KB,但是可以改得更大;
如果页面数据比较大,超过8KB,会怎么样? FastCGI进程被挂在render方法上!必须等到Web服务器的缓冲区清空,把页面数据全部接收下来以后,FastCGI进程才能结束本次Rails调用,处理下一个请求!所以千万别用Apache/Nginx搭配FastCGI应用服务器,否则你的RoR应用会死的很难看。根据我个人的测试数据表明,同样的测试负载,Apache搭配70个FastCGI进程挂掉,但是Lighttpd搭配30个FastCGI进程轻松跑完!
当FastCGI搭配Lighttpd的时候,我们知道Lighttpd会一次性照单全收FastCGI送过来的页面数据,所以FastCGI进程并不会被挂住。如果我们对比一下Lighttpd搭配Mongrel和FastCGI会发现,Lighttpd搭配FastCGI性能最好,为什么呢?
Mongrel首先自己会用StringIO缓冲页面数据,然后推送给Lighttpd以后,Lighttpd也在内存当中缓冲了一份页面数据,造成了毫无必要的double buffer的开销。这自然不如FastCGI不做任何缓冲,直接推给Lighttpd性能来得高,内存消耗少了。
我们的方案分析到这里,大家应该自己心里有结论了,Lighttpd+FastCGI是性能最佳,服务器资源消耗最少的RoR部署方案,事实上目前RoR网站部署使用最多最流行的也是Lighttpd+FastCGI方式,而JavaEye网站,自然也是这种方式的部署。因此我们可以对各种方案进行一个性能优劣的排队:
引用
Lighttpd+FastCGI > Lighttpd+Mongrel > Nginx+Mongrel > Apache+Mongrel > Ngignx+FastCGI > Apache+FastCGI
其中Lighttpd+FastCGI是性能最佳方案,而Apache+FastCGI是性能最差方案。
有些细心的同学可能会产生一个新的疑问?你说到底,之所以Lighttpd跑RoR性能最好,还是在于Lighttpd接收数据不限定缓冲区的大小,而Apache/Nginx限定了缓冲区大小所至。那为什么Nginx要限制呢?Lighttpd如果不限制的话,会不会导致Lighttpd内存爆掉?
Nginx限制Proxy Buffer Size其实也有道理,因为Nginx并不是为RoR量身打造的Web服务器,Nginx最广泛的用途还是高负载大访问量的代理服务器,在Nginx主要的应用场合,如果不做这样的限制,那Nginx端的资源消耗就相当高了,有可能会拖累所代理的服务速度。
Lighttpd主要用途之一就是提供高性能的FastCGI支持的Web服务器,所以必须为FastCGI量身打造。Lighttpd端承担的负载越高,就越能有效的加快FastCGI执行速度。其实我们稍微心算一下,假设Lighttpd后面挂1000个FastCGI进程,每个FastCGI进程同时送过来50KB的页面数据,Lighttpd就是全部吃下来,也不过只消耗50MB的内存而已,而事实上1000个FastCGI进程足以支撑每日上千万的大网站了。
只有当我们使用服务器端程序控制大文件下载的时候,有可能造成Lighttpd内存暴涨,例如某个用户使用100个线程并发下载JavaEye圈子的共享文件,在没有特殊处理的情况下,Lighttpd将全部吃下100个FastCGI进程送过来的10MB数据,就会立刻暴涨1GB的内存。这种情况怎么办呢?其实我们也有办法让Lighttpd一点内存都不吃, 请看我写的另外一篇文章:RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能
可能很多人看了我的文章,对结论觉得很诧异,既然Lighttpd+FastCGI这样好,为什么那么多人都推崇Mongrel,否定FastCGI呢?我想,不外乎几个原因:
一、Lighttpd+FastCGI配置起来比较专业,而Mongrel配置简单
尽管我当初第一次搭建Lighttpd+FastCGI环境没费什么周折,但是我观察到非常多的Ruby程序员很难成功搭建一个Lighttpd+FastCGI的环境出来,很多人连Lighttpd都无法独立的运行起来。这也许是因为很多程序员习惯了Windows开发环境,对于Unix上面通过源代码编译安装的方式过于陌生造成的。而我从97年开始使用Unix,至今已有10年历史,因此搭建这样简单的系统,对我来说不造成什么障碍。
而Mongrel就简单了,gem install mongrel安装完毕,mongrel_rails start启动,哪个人不会?毕竟绝大多数开发人员和部署人员不是高手,他们熟悉哪种方式,自然就会推崇哪种方式。
二、Mongrel可以独立作为Web服务器运行,开发环境和部署环境统一
一般来说,程序员肯定是尽量保持开发环境和部署环境的一致性,避免部署到生产环境出现不测的后果。既然在开发环境熟悉了Mongrel,当然更加愿意在生产环境使用Mongrel,而不愿意碰没有接触过的Lighttpd。
三、Mongrel支持HTTP协议,因此不论监控还是集成其他服务都比较简单,容易玩出更多的花活。
HTTP协议要比FastCGI协议普及的多,因此通过HTTP方式的监控工具,群集管理工具,集成其他服务的工具都是一抓一大把。而支持FastCGI的第三方工具就少得可怜了。你要玩很多花活出来,用FastCGI的话,就难免得自己开发相应的工具,那当然不如使用Mongrel方便啦。
最后,如果你看了这篇文章,想摩拳擦掌的安装一把Lighttpd+FastCGI的话,那么我的这篇文章就是最好的安装指南:
在Linux平台上安装和配置Ruby on Rails详解
评论
16 楼
robbin
2008-01-15
catoc 写道
robbin提到了服务器到用户端的数据传输,我再补充一下用户端到服务器的数据传输:
我们知道 IO 相对于 cpu 是很慢的,在 linux 上 lighttpd 使用了epoll,解决的大并发慢速链接的问题。
那么,在有很多用户同时上传大文件的时候,lighttpd 是怎么处理的呢?上面的资料解释了这个问题:在
有很多慢速上行数据时,lighttpd 将数据接收完毕后才会发送给backend,这样的话 backend 就不会被一
个慢速请求占用,可以服务更多的请求。nginx 也有类似的设计。Mongrel 不清楚。
我使用 php 的时候,一直倾向于 apache + mod_php,了解了 lighttpd 的上述功能后,打算试试
lighttpd + php_fastcgi, 估计性能会有大幅的提高。
引用
The tracking of the progress is handled completely in the core of the web-server and the backend is only called when the upload is finished. It reduces the impact of slow clients which try to upload to your site in parallel and would block a backend-process otherwise.
我们知道 IO 相对于 cpu 是很慢的,在 linux 上 lighttpd 使用了epoll,解决的大并发慢速链接的问题。
那么,在有很多用户同时上传大文件的时候,lighttpd 是怎么处理的呢?上面的资料解释了这个问题:在
有很多慢速上行数据时,lighttpd 将数据接收完毕后才会发送给backend,这样的话 backend 就不会被一
个慢速请求占用,可以服务更多的请求。nginx 也有类似的设计。Mongrel 不清楚。
我使用 php 的时候,一直倾向于 apache + mod_php,了解了 lighttpd 的上述功能后,打算试试
lighttpd + php_fastcgi, 估计性能会有大幅的提高。
我还真的没有注意到这个问题,刚才研究了一下,发现Lighttpd的确做的很棒!具体的过程是这样的:
Lighttpd在接收到POST请求以后,会在硬盘的/var/tmp目录下面创建相应的临时文件,每个临时文件最大1MB,如果POST请求超过1MB,会创建更多的硬盘临时文件。在处理整个文件上传的过程中,Lighttpd都不会和FastCGI打交道,即使你杀掉FastCGI进程,文件上传过程也不会受什么影响。
当Lighttpd完整的收下来整个POST数据以后,才会将数据推给FastCGI进程去处理。
因此,当上传大文件,整个上传过程无论多慢,都只是Lighttpd在处理,并不会影响到FastCGI进程。但是如果黑客刻意上传非常大的文件,比如说1GB的大文件,当Lighttpd完整的接受下来以后,还是会一股脑推给FastCGI,导致FastCGI的内存暴涨。要解决这个问题,可以在Lighttpd端设置request的最大限制,例如:
引用
server.max-request-size = 10240
设置为10MB,这样黑客要伪造POST提交,最大只允许10MB,就可以解决问题了。
15 楼
catoc
2008-01-15
robbin提到了服务器到用户端的数据传输,我再补充一下用户端到服务器的数据传输:
我们知道 IO 相对于 cpu 是很慢的,在 linux 上 lighttpd 使用了epoll,解决的大并发慢速链接的问题。
那么,在有很多用户同时上传大文件的时候,lighttpd 是怎么处理的呢?上面的资料解释了这个问题:在
有很多慢速上行数据时,lighttpd 将数据接收完毕后才会发送给backend,这样的话 backend 就不会被一
个慢速请求占用,可以服务更多的请求。nginx 也有类似的设计。Mongrel 不清楚。
我使用 php 的时候,一直倾向于 apache + mod_php,了解了 lighttpd 的上述功能后,打算试试
lighttpd + php_fastcgi, 估计性能会有大幅的提高。
引用
The tracking of the progress is handled completely in the core of the web-server and the backend is only called when the upload is finished. It reduces the impact of slow clients which try to upload to your site in parallel and would block a backend-process otherwise.
我们知道 IO 相对于 cpu 是很慢的,在 linux 上 lighttpd 使用了epoll,解决的大并发慢速链接的问题。
那么,在有很多用户同时上传大文件的时候,lighttpd 是怎么处理的呢?上面的资料解释了这个问题:在
有很多慢速上行数据时,lighttpd 将数据接收完毕后才会发送给backend,这样的话 backend 就不会被一
个慢速请求占用,可以服务更多的请求。nginx 也有类似的设计。Mongrel 不清楚。
我使用 php 的时候,一直倾向于 apache + mod_php,了解了 lighttpd 的上述功能后,打算试试
lighttpd + php_fastcgi, 估计性能会有大幅的提高。
14 楼
robbin
2008-01-15
mongrel_cluster的功能很简单,就是控制n个mongrel实例启动关闭重起,自己写个类似的shell脚本,不过十几行代码。比方说JavaEye网站现在FastCGI应用服务器群集的启动关闭重起,也是我写的shell脚本,也许可以命名为fastcgi_cluster了,呵呵。Lighttpd+FastCGI水平扩展的方式和HTTP Proxy是一样的,唯一不同的就是一个走HTTP协议,一个走FastCGI协议。
13 楼
lemonzc
2008-01-15
Mongrel官网上的一篇文章:
http://mongrel.rubyforge.org/docs/apache.html
讲述了 apache+mongrel 的部署方式。 上面还提及了apache的 mod_proxy_balancer 模块。
大家可以参考一下。
:D
http://mongrel.rubyforge.org/docs/apache.html
讲述了 apache+mongrel 的部署方式。 上面还提及了apache的 mod_proxy_balancer 模块。
大家可以参考一下。
:D
12 楼
fsword
2008-01-15
不错,这些是关键,而且,robbin似乎没有提mongrel_cluster(也许觉得没必要),其实这个东西才真正让mongrel方案变得可行,linux我也用了很久(虽然不能和robbin比),但是能够把精力节省出来放在业务上当然更好了,我觉得nginx/mongrel_cluster是一个比较平衡的策略,部署十分简单,基于debian/ubuntu系很容易就搞定了,而且因为采用http proxy,以后水平扩展也很简单,动态部分proxy,静态资源用nfs,一般有点基础的半天就能入门,这样可能效率的确不如lighttpd/fastcgi,但是也算是次优了......
robbin 写道
可能很多人看了我的文章,对结论觉得很诧异,既然Lighttpd+FastCGI这样好,为什么那么多人都推崇Mongrel,否定FastCGI呢?我想,不外乎几个原因:
一、Lighttpd+FastCGI配置起来比较专业,而Mongrel配置简单
二、Mongrel可以独立作为Web服务器运行,开发环境和部署环境统一
三、Mongrel支持HTTP协议,因此不论监控还是集成其他服务都比较简单,容易玩出更多的花活。
一、Lighttpd+FastCGI配置起来比较专业,而Mongrel配置简单
二、Mongrel可以独立作为Web服务器运行,开发环境和部署环境统一
三、Mongrel支持HTTP协议,因此不论监控还是集成其他服务都比较简单,容易玩出更多的花活。
11 楼
rainchen
2008-01-14
rubyonrails 官方网站是用mongrel_cluster + Apache 2.2,是另一种选择的一个例证:
http://weblog.rubyonrails.org/2006/6/11/rails-system-back-on-track
虽然他的访问量比JE大2-3倍,不过似乎用到RAILS的地方只是那个BLOG,动态请求的地方估计没有JE那么频繁(BLOG的缓存也容易做)。
http://weblog.rubyonrails.org/2006/6/11/rails-system-back-on-track
虽然他的访问量比JE大2-3倍,不过似乎用到RAILS的地方只是那个BLOG,动态请求的地方估计没有JE那么频繁(BLOG的缓存也容易做)。
10 楼
lemonzc
2008-01-14
我想补充下,其实http proxy的这种转发,类似路由器的的转发功能,所以内网的机器可以做成服务器。 就像我可以把javaeye安装在家里面的一个机器上。当然你路由器拨号获取的是一个动态真实ip, 用花生壳类似的服务,可以绑定到你的域名上。这里的前端 web 服务器 和 后面的处理动态请求的服务器应该是类似的应用。
目前我用的是 InstantRails ,这个比较傻瓜式的,类似easyPHP. 就是 apache+Mongrel
我的主业是搞j2ee的,不过没有看到 类似这种集成了的 apache+tomcat,
目前我用的是 InstantRails ,这个比较傻瓜式的,类似easyPHP. 就是 apache+Mongrel
我的主业是搞j2ee的,不过没有看到 类似这种集成了的 apache+tomcat,
9 楼
robbin
2008-01-14
可能很多人看了我的文章,对结论觉得很诧异,既然Lighttpd+FastCGI这样好,为什么那么多人都推崇Mongrel,否定FastCGI呢?我想,不外乎几个原因:
一、Lighttpd+FastCGI配置起来比较专业,而Mongrel配置简单
尽管我当初第一次搭建Lighttpd+FastCGI环境没费什么周折,但是我观察到非常多的Ruby程序员很难成功搭建一个Lighttpd+FastCGI的环境出来,很多人连Lighttpd都无法独立的运行起来。这也许是因为很多程序员习惯了Windows开发环境,对于Unix上面通过源代码编译安装的方式过于陌生造成的。而我从97年开始使用Unix,至今已有10年历史,因此搭建这样简单的系统,对我来说不造成什么障碍。
而Mongrel就简单了,gem install mongrel安装完毕,mongrel_rails start启动,哪个人不会?毕竟绝大多数开发人员和部署人员不是高手,他们熟悉哪种方式,自然就会推崇哪种方式。
二、Mongrel可以独立作为Web服务器运行,开发环境和部署环境统一
一般来说,程序员肯定是尽量保持开发环境和部署环境的一致性,避免部署到生产环境出现不测的后果。既然在开发环境熟悉了Mongrel,当然更加愿意在生产环境使用Mongrel,而不愿意碰没有接触过的Lighttpd。
三、Mongrel支持HTTP协议,因此不论监控还是集成其他服务都比较简单,容易玩出更多的花活。
HTTP协议要比FastCGI协议普及的多,因此通过HTTP方式的监控工具,群集管理工具,集成其他服务的工具都是一抓一大把。而支持FastCGI的第三方工具就少得可怜了。你要玩很多花活出来,用FastCGI的话,就难免得自己开发相应的工具,那当然不如使用Mongrel方便啦。
一、Lighttpd+FastCGI配置起来比较专业,而Mongrel配置简单
尽管我当初第一次搭建Lighttpd+FastCGI环境没费什么周折,但是我观察到非常多的Ruby程序员很难成功搭建一个Lighttpd+FastCGI的环境出来,很多人连Lighttpd都无法独立的运行起来。这也许是因为很多程序员习惯了Windows开发环境,对于Unix上面通过源代码编译安装的方式过于陌生造成的。而我从97年开始使用Unix,至今已有10年历史,因此搭建这样简单的系统,对我来说不造成什么障碍。
而Mongrel就简单了,gem install mongrel安装完毕,mongrel_rails start启动,哪个人不会?毕竟绝大多数开发人员和部署人员不是高手,他们熟悉哪种方式,自然就会推崇哪种方式。
二、Mongrel可以独立作为Web服务器运行,开发环境和部署环境统一
一般来说,程序员肯定是尽量保持开发环境和部署环境的一致性,避免部署到生产环境出现不测的后果。既然在开发环境熟悉了Mongrel,当然更加愿意在生产环境使用Mongrel,而不愿意碰没有接触过的Lighttpd。
三、Mongrel支持HTTP协议,因此不论监控还是集成其他服务都比较简单,容易玩出更多的花活。
HTTP协议要比FastCGI协议普及的多,因此通过HTTP方式的监控工具,群集管理工具,集成其他服务的工具都是一抓一大把。而支持FastCGI的第三方工具就少得可怜了。你要玩很多花活出来,用FastCGI的话,就难免得自己开发相应的工具,那当然不如使用Mongrel方便啦。
8 楼
robbin
2008-01-14
mifly 写道
感谢robbin提供那么详细的资料,本人有些疑问:
hostingrails提到:
Can I run one Mongrel app and multiple FastCGI apps in one shared hosting account? [back to top]
Yes, this is typically what our clients on the "Professional" plan do. They run their key site on Mongrel and often host their blog and other applications on FastCGI. You can host as many FastCGI apps as you'd like.
所以我有疑问:
是一个FastCGI进程可以运行多个FastCGI应用?还是一个FastCGI进程运行一个应用,但空间会开多个进程来运行多个应用?还是上面的many FastCGI apps指的并不是rails应用,所以可以同时运行多个呢?
还有疑问:FastCGI hosting 3.59$/mo,mongel hosting 9.79$/mo.难道便宜的比贵的还好?
我不是在做广告呀,真的是有疑问,探讨下。
hostingrails提到:
Can I run one Mongrel app and multiple FastCGI apps in one shared hosting account? [back to top]
Yes, this is typically what our clients on the "Professional" plan do. They run their key site on Mongrel and often host their blog and other applications on FastCGI. You can host as many FastCGI apps as you'd like.
所以我有疑问:
引用
当我们以FastCGI方式运行Rails应用服务器......都是每个进程只能跑一个Rails实例。
是一个FastCGI进程可以运行多个FastCGI应用?还是一个FastCGI进程运行一个应用,但空间会开多个进程来运行多个应用?还是上面的many FastCGI apps指的并不是rails应用,所以可以同时运行多个呢?
还有疑问:FastCGI hosting 3.59$/mo,mongel hosting 9.79$/mo.难道便宜的比贵的还好?
我不是在做广告呀,真的是有疑问,探讨下。
一个FastCGI进程只能运行一个Rails实例。你要分别运行多个应用,当然要开多个FastCGI进程了。
我没有说过FastCGI比Mongrel好,每种方式有自己适合的运行环境,无所谓好坏。我只是说FastCGI搭配Lighttpd会比Mongrel好。如果你用FastCGI搭配Apache/Nginx,FastCGI就会很糟糕。
我不了解HostingRails,但作为虚拟主机提供商,使用Mongrel,不需要他提供额外的Web服务器和相关的配置,每个Mongrel独立的管理,他当然喜欢这种方式了。
7 楼
robbin
2008-01-14
老王 写道
web开发敏捷之道(第二版)里似乎明确反对使用fastcgi的方式,不过我看了robin的解释,还是决定尝试一下。
《Web开发敏捷之道》的部署那一章节是DHH本人所写,但是第二版部署章节的作者叫做James Duncan Davidson,写的比第一版内容差多了,让我不得不保留第一版作为参考。这也是为什么我家里的书架上第一版第二版都放在一起,而我没有把第一版给扔掉的原因。
6 楼
lgn21st
2008-01-14
超赞文章,解了我心中n多疑惑~今天用虚拟机配置lighttpd+fcgi测试自己的项目中~~~
5 楼
DigitalSonic
2008-01-14
谢谢Robbin详细的解释,收益颇多,呵呵。
Mongrel也有JRuby版本的,JRuby不像Ruby,它使用的是真正的系统线程,不知道对网络IO的负载有所改善~
robbin 写道
Mongrel使用了Ruby的用户线程机制来实现多线程并发,并且使用了一个fastthread补丁,改善了Ruby用户线程的同步互斥锁问题。但是Ruby并不是本地线程,我们也不要对Mongrel的网络IO负载能力抱有什么不切实际的幻想。同时Rails本身也不是线程安全的,因此Mongrel在执行Rails代码的过程中,完全是加锁的状态,那和单进程其实也没有太大差别。
Mongrel也有JRuby版本的,JRuby不像Ruby,它使用的是真正的系统线程,不知道对网络IO的负载有所改善~
4 楼
mifly
2008-01-14
感谢robbin提供那么详细的资料,本人有些疑问:
hostingrails提到:
Can I run one Mongrel app and multiple FastCGI apps in one shared hosting account? [back to top]
Yes, this is typically what our clients on the "Professional" plan do. They run their key site on Mongrel and often host their blog and other applications on FastCGI. You can host as many FastCGI apps as you'd like.
所以我有疑问:
是一个FastCGI进程可以运行多个FastCGI应用?还是一个FastCGI进程运行一个应用,但空间会开多个进程来运行多个应用?还是上面的many FastCGI apps指的并不是rails应用,所以可以同时运行多个呢?
还有疑问:FastCGI hosting 3.59$/mo,mongel hosting 9.79$/mo.难道便宜的比贵的还好?
我不是在做广告呀,真的是有疑问,探讨下。
hostingrails提到:
Can I run one Mongrel app and multiple FastCGI apps in one shared hosting account? [back to top]
Yes, this is typically what our clients on the "Professional" plan do. They run their key site on Mongrel and often host their blog and other applications on FastCGI. You can host as many FastCGI apps as you'd like.
所以我有疑问:
引用
当我们以FastCGI方式运行Rails应用服务器......都是每个进程只能跑一个Rails实例。
是一个FastCGI进程可以运行多个FastCGI应用?还是一个FastCGI进程运行一个应用,但空间会开多个进程来运行多个应用?还是上面的many FastCGI apps指的并不是rails应用,所以可以同时运行多个呢?
还有疑问:FastCGI hosting 3.59$/mo,mongel hosting 9.79$/mo.难道便宜的比贵的还好?
我不是在做广告呀,真的是有疑问,探讨下。
3 楼
iceskysl
2008-01-14
you might use pound as a load balancer, pointing dynamic requests at mongrels, and static requests at lighttpd.
2 楼
t0uch
2008-01-14
太棒了,不但剖析了内部的一些东西,而且还给出建议和方案
很感谢robbin连夜给大家赶出的好文
很感谢robbin连夜给大家赶出的好文
1 楼
老王
2008-01-14
web开发敏捷之道(第二版)里似乎明确反对使用fastcgi的方式,不过我看了robin的解释,还是决定尝试一下。
发表评论
-
《松本行弘的程序世界》推荐序
2011-07-21 13:47 15311在流行的编程语言中,ruby是一个比较另类的存在,这是因为大多 ... -
从Rails聊聊小公司的研发团队建设
2011-03-23 10:49 37234首先分享一点数据吧: JavaEye的PV到了140万了,一 ... -
Ruby作为服务器端应用已经成熟了
2009-11-17 14:55 15980JavaEye网站在过去的Ruby on rails实践当中, ... -
基于资源的HTTP Cache的实现介绍
2009-09-05 00:27 17079我们都知道浏览器会缓 ... -
请注意Rails2.3自带的memcache-client有性能问题
2009-03-23 18:05 14516Rails2.3版本发布了,这个版本内部的改动非常大,相关介绍 ... -
监视Rails进程内存泄漏的技巧
2008-12-30 21:56 10975Rails应用比较容易遇到的两类性能问题:一类是Rails执行 ... -
ruby MBARI大补丁性能评测报告
2008-12-23 12:19 5075JavaEye之前的新闻ruby内存泄漏的罪魁祸首 - 幽灵指 ... -
在top监视窗口显示Rails当前正在执行的请求URL
2008-12-01 14:15 9864这是一个从PragDave的博客上面学来的技巧,很实用,很co ... -
对Ruby VM的GC的思考
2008-09-02 23:41 8988Ruby虽然是动态脚本语言 ... -
推荐一篇很好的RoR部署方案性能评测
2008-07-08 11:55 9684今年年初的时候,我写了一篇RoR部署方案深度剖析的文章,分析了 ... -
Ruby和Rails的缺点
2008-06-25 21:08 17409有人说,robbin你说了那么多RoR的优点,你啥时候说说Ro ... -
Skynet --- ruby的类Google Map/Reduce框架
2008-06-02 00:39 8303Skynet是一个很响亮的名 ... -
rmmseg-cpp - 简洁高效的ruby中文分词程序
2008-05-27 00:47 11243我在前一篇文章向大家 ... -
使用libmmseg实现Ruby的中文分词功能
2008-05-24 21:43 11339用Ruby on Rails开发web2.0网站的人都知道,r ... -
mod_rails尝鲜
2008-04-13 14:32 8086Passenger(俗称mod_rails)是 ... -
Lighttpd和RoR安装配置的疑难解答
2008-03-07 11:09 14868之前写过一篇在Linux平 ... -
JavaEye网站的RoR性能优化经验谈
2008-01-20 16:11 18471JavaEye网站从2006年9月11 ... -
RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能
2008-01-12 17:45 10269传统的Web服务器在处理文件下载的时候,总是先读入文件内容到应 ... -
Ruby为什么会受程序员的欢迎?
2008-01-07 20:08 15755孟岩最近写了一篇博客 ... -
Ruby on Rails 2.0的新特性介绍
2007-12-10 21:32 15635万众瞩目的Ruby on Rails 2.0已经发布了,Rai ...
相关推荐
标题中的“RoR中文解决方案”指的是Ruby on Rails(简称RoR)的一个针对中文环境的优化方案,Ruby on Rails是一款基于Ruby编程语言的开源Web开发框架,以其MVC(Model-View-Controller)架构和DRY(Don't Repeat ...
首先,RoR性能优化涉及到多个层面,包括应用程序的部署、服务器配置以及代码优化。在部署方面,操作系统的选择至关重要。RoR通常在Unix类操作系统上运行最佳,如RHEL、CentOS、Ubuntu和SuSE Linux。对于AMD Opteron ...
ResNet和Ror模型是深度学习领域的关键进展,通过解决深度网络的训练难题,使得我们能够构建出更深、更强大的模型。在CIFAR数据集上的优秀表现证明了这些模型的有效性。通过不断的研究和改进,我们可以期待在未来的AI...
NULL 博文链接:https://xuxiangpan888.iteye.com/blog/266696
**Ruby on Rails(简称RoR)中文资料** Ruby on Rails(RoR)是一个基于Ruby编程语言的开源Web应用框架,遵循MVC(Model-View-Controller)架构模式,旨在简化Web开发过程,提高开发效率。RoR强调“约定优于配置”...
`rake-0.7.3.gem`使得你可以定义任务,并通过命令行执行,简化了项目的构建、测试和部署流程。 `actionwebservice`是Rails早期版本中用于创建Web服务的组件,允许Rails应用程序提供SOAP接口。然而,自Rails 3之后,...
1. **Gemfile与Gemfile.lock**:项目中的Gemfile用于指定项目依赖的gem库,Gemfile.lock则记录了具体版本,确保团队成员或部署环境具有相同的依赖。 2. **ActiveRecord**:这是Rails中的ORM(对象关系映射),它...
Ruby on Rails(RoR)是一种基于Ruby语言的开源Web应用程序框架,它遵循MVC(Model-View-Controller)架构模式,旨在简化Web开发过程。在这个选题方向中,我们主要探讨的是与RoR相关的源代码分析和学习。源代码是...
**初探ROR** Ruby on Rails(简称ROR)是一个基于Ruby编程语言的开源Web应用程序框架,它遵循MVC(模型-视图-控制器)架构模式,旨在促进开发过程的简洁性和效率。Ruby on Rails的核心理念是“Don't Repeat ...
基于RoR的博客系统,代码风格简单清晰,前后太完善,适合初学者。
### Windows上搭建Ruby on Rails(ROR)环境详解 #### 一、引言 随着Web开发技术的不断发展,Ruby on Rails(简称Rails或ROR)作为一种高效、简洁且优雅的Web开发框架,受到了广大开发者的青睐。然而,在Windows...
《机遇ROR的图书管理系统》是一份以Ruby on Rails(简称ROR)技术为核心,旨在构建高效、便捷的图书管理解决方案的学习资料。Ruby on Rails,是基于Ruby编程语言的开源Web应用框架,它遵循MVC(Model-View-...
### RoR培训课程PPT知识点概述 #### 一、课程概览与背景介绍 - **课程性质**:本课程为为期五天的Ruby on Rails(简称RoR)入门级培训,适合初学者快速掌握RoR的基本概念和技术要点。 - **讲师信息**:由Peter ...
### ROR 文件的上传与下载:深入解析与实践 在Ruby on Rails(简称ROR)框架下,处理文件的上传与下载是一项常见的需求,尤其是在构建包含媒体内容的应用程序时。本文将基于给定的文件信息,详细阐述如何在Rails...
此外,Begin的目的是教育开发者理解RoR部署的原理,而不仅仅是提供一套固定的部署方案。他认为,开发者应该能够在阅读书籍后根据自己的需求创造适应性强的部署策略,比如使用Thin服务器替代Mongrel。 尽管Java和C#...
ROR环境 Ruby version 1.9.3 (java) RubyGems version 1.8.24 Rack version 1.4 Rails version 3.2.12 JavaScript Runtime therubyrhino (Rhino) Active Record version 3.2.12 Action Pack version 3.2.12 ...