Apache Nginx lighttpd HAProx Litespeed 缓冲道理剖析fastcgi机能

因为比来在忙于web server的开辟,对付静态部门跟动态部门的交互一向迟迟不决,缓冲区巨细也一向很头疼,看了下面的这篇文章感觉不错,我仍是如许感觉,简略的便是最好 的,但并不料味着全部处置都用一种体例,正如我在静态输出的socket buffer上面一样,我是按照恳求内容的巨细来决议缓冲区分派的,纵然如许作在体系内部会形成一次内存拷贝(socket归去处置),可是相对付收集的 耽误速率快多了,以是我感觉仍是按照分歧的内容和巨细决议缓冲区巨细,既不是lighttpd的照单全收,也不是nginx等的8K绣花,对付领受,起首 分派一个2k-8K的缓冲区去收,西一头部领受完毕了就可以知道剩下的contentlength,好比内容在8K-64K之间的用32K,64K-无限 大K之间的用64K,如许就可以用历程内的一次内存拷贝调换收集的耽误题目,对付fastcgi的撑持也会更好,下面是原文:
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 > 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便利 啦。
From:http://www.apolov.com/html/2009/06/09/1244533635.html
posted @ 2010-05-28 14:11  Wamei  阅读(898)  评论(0编辑  收藏  举报