CentOS WEB緩存服務(wù)器程序使用比較靈活
CentOS WEB對于電腦使用的玩家的常用軟件,然后我就學(xué)習(xí)及深入的研究CentOS WEB,在這里和大家一起探討CentOS WEB的使用方法,希望對大家有用。
CentOS WEB 架構(gòu)布置
1:負(fù)載均衡器大型網(wǎng)站肯定不是單臺服務(wù)器的,為了做負(fù)載均衡,一般用F5,DNS輪詢.我們公司所有的靜態(tài)頁面則采用NGINX做代理,后端掛SQUID服務(wù)器.NGINX的代理模塊能夠根據(jù)url地址HASH到某組服務(wù)器上,NGINX做負(fù)載均衡,SQUID組則考慮容災(zāi)問題.
2:CentOS WEB緩存服務(wù)器原來我們公司使用文件cache,在新版本中使用squid作為頁面緩存,squid組根據(jù)不同地區(qū)做IDC分布,形成了分布式的系統(tǒng).從實(shí)際效果上看,文件cache更容易控制,程序使用比較靈活.考慮到不同的應(yīng)用ncache可能逐步替代squid.
3:后端服務(wù)器后端服務(wù)器就是應(yīng)用服務(wù)器,主要通過F5掛在squid服務(wù)集群后面,處理的都是動態(tài)請求,每臺機(jī)器每天50萬的請求,cpu負(fù)載也不高,并發(fā)請求沒有超過100,使用的是apache1.3,lamp的組合.
JavaEye網(wǎng)站的RoR性能優(yōu)化經(jīng)驗(yàn)談
JavaEye網(wǎng)站從2006年9月11日上線基于RoR的2.0版本開始,到現(xiàn)在已經(jīng)運(yùn)行了將近一年半了。在這一年半的時間里,JavaEye網(wǎng)站的每日PV從最開始的5萬,緩慢增長到了現(xiàn)在的60萬。隨著網(wǎng)站負(fù)載的不斷增加,我們也在不斷嘗試和調(diào)整網(wǎng)站的性能,積累了不少第一手RoR應(yīng)用性能優(yōu)化的實(shí)戰(zhàn)經(jīng)驗(yàn)。
雖然我們并不是RoR性能優(yōu)化的權(quán)威專家,我們所積累的經(jīng)驗(yàn)也許并不是最優(yōu)實(shí)踐,但是作為國內(nèi)最早涉足RoR商業(yè)運(yùn)營的互聯(lián)網(wǎng)網(wǎng)站之一,我們非常樂意分享和交流我們的實(shí)戰(zhàn)經(jīng)驗(yàn),以幫助后來者節(jié)省必要的摸索時間。
RoR驚人的開發(fā)速度恐怕是每個互聯(lián)網(wǎng)創(chuàng)業(yè)者都夢寐以求的,但是隨著網(wǎng)站流量的不斷增大,可能大多數(shù)采用RoR的網(wǎng)站或遲或早會遇到RoR的性能瓶頸,我的一個朋友capitian說過一句很有意思的話:“RoR應(yīng)用做到后來,總有自己修改底層的沖動”。
就我所了解和掌握的情況來看,很多RoR網(wǎng)站都過早的遇到了性能瓶頸,一個很普遍的現(xiàn)象就是:RoR應(yīng)用的CPU負(fù)載要遠(yuǎn)遠(yuǎn)高于數(shù)據(jù)庫的負(fù)載。這是一個有點(diǎn)違背常理的現(xiàn)象,因?yàn)槲覀冎?,硬盤IO速度要比內(nèi)存慢得多,所以一般CentOS WEB應(yīng)用的性能瓶頸往往會出現(xiàn)在數(shù)據(jù)庫IO上,因此優(yōu)化數(shù)據(jù)庫訪問,進(jìn)行對象緩存是非常有效的性能優(yōu)化手段。但是一旦應(yīng)用服務(wù)器負(fù)載比數(shù)據(jù)庫還高的話,單純的對象緩存就無用武之地了。下面我們從幾個方面分別談一談如何進(jìn)行RoR的性能優(yōu)化:
應(yīng)用的部署RoR應(yīng)用的部署包括操作系統(tǒng),CentOS WEB服務(wù)器,應(yīng)用服務(wù)器和數(shù)據(jù)庫四個方面:
一、操作系統(tǒng)
1、發(fā)行版本
RoR適合于部署在Unix類操作系統(tǒng)上面,通常比較多的人使用RHEL/CentOS/Ubuntu,我們比較偏愛SuSE Linux,對于我們服務(wù)器使用的AMD Opteron x86_64的CPU來說,SLES要比RHEL有更多的優(yōu)化。另外應(yīng)該盡量使用64位版本操作系統(tǒng),以充分發(fā)揮x86_64 CPU的性能,并且x86_64的Linux很多Kernel參數(shù)也大很多,代價(jià)就是需要更多的物理內(nèi)存。
2、文件系統(tǒng)
Linux最常用的文件系統(tǒng)是ext3,但我們使用的是Reiserfs文件系統(tǒng)。Reiserfs在讀寫大量小文件的目錄性能非常高,即使處理目錄下面直接存放10萬個文件,性能仍然不會下降。我們知道默認(rèn)情況Rails會對每個瀏覽器會話在硬盤生成session文件,一個繁忙的網(wǎng)站,臨時文件目錄下面有上萬乃至幾萬個session文件是很常見的現(xiàn)象。對于這種目錄下面幾萬個小文件的存取,reiserfs要比ext3性能高一個數(shù)量級。如果希望對session文件有更好的存取性能,可以把臨時目錄鏈接到Linux的內(nèi)存文件系統(tǒng)/dev/shm目錄下面,這樣實(shí)際上session文件的存取都是直接內(nèi)存操作了,這種方式唯一的問題在于不能支持群集部署。如果你已經(jīng)升級到了Rails2.0,可以采取把session保存到Cookie里面的方式,既可以避免服務(wù)器處理session的開銷,而且還支持群集部署,是大規(guī)模網(wǎng)站部署的首選方式。
3、內(nèi)核的網(wǎng)絡(luò)參數(shù)調(diào)整
對于流量很大的網(wǎng)站來說,默認(rèn)的Linux內(nèi)核網(wǎng)絡(luò)參數(shù)偏小,因此如果你的網(wǎng)站流量非常大,或者上傳下載大文件比較多,可以針對性的調(diào)整內(nèi)核網(wǎng)絡(luò)參數(shù),擴(kuò)大內(nèi)核的TCP接收數(shù)據(jù)和發(fā)送數(shù)據(jù)的Buffer緩沖區(qū)大小,比方說:
引用
net.core.rmem_default=262144
net.core.wmem_default=262144
net.core.rmem_max=262144
net.core.wmem_max=262144
net.ipv4.tcp_rmem=4096 65536 524288
net.ipv4.tcp_wmem=4096 65536 524288
參數(shù)具體調(diào)整,可以Google相關(guān)的Linux內(nèi)核參數(shù)的文檔,這里不展開詳談。
二、CentOS WEB服務(wù)器
CentOS WEB服務(wù)器首選Lighttpd,因?yàn)長ighttpd在和后端的應(yīng)用服務(wù)器通訊方式上做了足夠的優(yōu)化:當(dāng)POST大數(shù)據(jù)量的時候, Lighttpd在完整的接收客戶端瀏覽器的數(shù)據(jù)之后,才會一次性發(fā)送給應(yīng)用服務(wù)器;同樣的,Lighttpd也是一次性把應(yīng)用服務(wù)器處理的頁面數(shù)據(jù)全部接收,不設(shè)置Buffer Size的限制。因此Lighttpd能夠盡最大可能的減輕應(yīng)用服務(wù)器的負(fù)擔(dān),減少應(yīng)用服務(wù)器用于處理數(shù)據(jù)傳輸?shù)难舆t,更加有效的利用應(yīng)用服務(wù)器資源。這方面的詳細(xì)的論述請看:RoR部署方案深度剖析。
關(guān)于Lighttpd的安裝可以參考在Linux平臺上安裝和配置Ruby on Rails詳解,這里僅談Lighttpd的性能優(yōu)化的幾個要點(diǎn):
1、網(wǎng)絡(luò)IO調(diào)度方式Linux Kernel 2.6支持sysepoll方式調(diào)度網(wǎng)絡(luò)IO,能夠處理極高的并發(fā)連接請求,Lighttpd可以通過配置文件打開sysepoll支持:引用server.event-handler = “l(fā)inux-sysepoll”
2、網(wǎng)絡(luò)IO傳輸方式Linux Kernel 2.6支持sendfile方式傳輸數(shù)據(jù),Lighttpd可以通過配置文件打開sendfile支持:引用server.network-backend = “l(fā)inux-sendfile”此外Lighttpd還支持應(yīng)用服務(wù)器參與的文件下載控制X-sendfile,詳細(xì)的論述請看:RoR網(wǎng)站如何利用lighttpd的X-sendfile功能提升文件下載性能
3、文件狀態(tài)緩存Lighttpd通過stat()調(diào)用獲得文件被修改的信息,來決定當(dāng)請求同一個靜態(tài)文件資源的時候,是否需要再次讀取硬盤文件。但是每次stat()調(diào)用也有一定的開銷,Lighttpd支持通過Fam Server來減少stat調(diào)用。即每次當(dāng)文件被修改之后,Kernel會發(fā)送一個消息通知Fam Server,而Lighttpd會通過進(jìn)程間通訊連接Fam Server,可以知道文件是否被修改的信息,不必再每次調(diào)用stat()。引用server.stat-cache-engine = “fam”
4、限定POST Size為了避免黑客惡意的攻擊服務(wù)器,偽造超大Post數(shù)據(jù)包轟炸CentOS WEB服務(wù)器和應(yīng)用服務(wù)器,可以限制Request請求的大小,例如限制為10MB:引用server.max-request-size = 10240
5、日志文件Lighttpd是單進(jìn)程單線程的服務(wù)器,調(diào)度網(wǎng)絡(luò)IO性能是極高的,但是在某些極端情況下,單進(jìn)程服務(wù)器也有風(fēng)險(xiǎn),即一旦被某操作系統(tǒng)調(diào)用掛住,整個服務(wù)器就沒有辦法響應(yīng)請求了。比方說服務(wù)器其他進(jìn)程導(dǎo)致的IO WAIT很高,操作系統(tǒng)的buffer又不夠的時候,Lighttpd在大量的寫access log就有被掛住的可能性。
因此如果Lighttpd日志對你的參考價(jià)值不大,可以考慮關(guān)閉掉。像JavaEye網(wǎng)站每天Lighttpd產(chǎn)生430萬條 log,對硬盤IO也是一個不小的負(fù)擔(dān),既然已經(jīng)開著Rais的production.log,那么Lighttpd的access log沒什么參考價(jià)值了,那就關(guān)掉它。
Lighttpd的性能優(yōu)化請看其作者寫的文章:
http://trac.lighttpd.net/trac/wiki/Docs:Performance
三、應(yīng)用服務(wù)器
Ruby的應(yīng)用服務(wù)器可以使用FastCGI,或者M(jìn)ongrel,如果我們使用Lighttpd的話,F(xiàn)astCGI是最好的搭配。
1、FastCGI和Lighttpd的通訊方式如果FastCGI和Lighttpd是在同一臺服務(wù)器,那么建議采用Unix Socket通訊,這種通訊方式比TCP要快一些,F(xiàn)astCGI可以通過Lighttpd自帶的spawn-fcgi命令行工具啟動,創(chuàng)建socket 文件,而Lighttpd監(jiān)聽socket文件。如果兩者不在同一臺服務(wù)器,需要群集部署,那就必須采用TCP Socket通訊,方式是一樣的。
2、FastCGI進(jìn)程應(yīng)該開多少個合適?Rails是單進(jìn)程方式運(yùn)行的,理論上來說,開幾個FastCGI進(jìn)程,就只能并發(fā)響應(yīng)幾個請求。對于繁忙的網(wǎng)站來說,峰值期間每秒有幾十個動態(tài)請求是很正常的事情,但實(shí)際上FastCGI進(jìn)程并不需要開那么多。這是因?yàn)榍岸说腃entOS WEB服務(wù)器在處理用戶瀏覽器連接,發(fā)送Request請求需要相當(dāng)長的時間,在FastCGI處理完請求釋放該連接以后,CentOS WEB服務(wù)器還需要相當(dāng)長的時間才能把頁面數(shù)據(jù)完整的發(fā)送到客戶端瀏覽器。
用戶在點(diǎn)擊一個鏈接以后,等待1-2秒,頁面內(nèi)容就顯示出來,這對用戶的感覺來說已經(jīng)是非??斓牧?,而FastCGI用于處理該請求可能只需要0.1秒,那么一個FastCGI進(jìn)程雖然并不能夠真正的并發(fā)運(yùn)行,但實(shí)際上的效果是他可以在1秒之內(nèi)處理10個請求,讓10個用戶在同時訪問網(wǎng)站的過程當(dāng)中感覺不到明顯的延遲。
因此FastCGI需要開多少個,取決于你的網(wǎng)站峰值期間每秒有多少個用戶請求過來,而你的FastCGI又能夠以多快的速度處理請求。比方說你的網(wǎng)站峰值期間每秒有50個動態(tài)請求,F(xiàn)astCGI在峰值期間處理每個請求需要0.2秒,那么實(shí)際上你只需要開10個FastCGI進(jìn)程就足夠了,為了應(yīng)付突發(fā)的峰值請求,你可以在這個計(jì)算量上面增加一些余量,比方說15-20個進(jìn)程,肯定是綽綽有余了。
關(guān)于FastCGI的性能優(yōu)化,可以參考Lighttpd作者的文章,雖然他是針對PHP跑FastCGI寫的,但對RoR也有參考價(jià)值:
http://trac.lighttpd.net/trac/wiki/Docs:PerformanceFastCGI
四、數(shù)據(jù)庫
JavaEye網(wǎng)站使用MySQL5.0.XX版本,數(shù)據(jù)庫引擎是InnoDB。關(guān)于MySQL數(shù)據(jù)庫的調(diào)優(yōu),推薦大家看MySQL Performance Blog,作者是一個MySQL性能調(diào)優(yōu)方面的專家,并且提供MySQL咨詢服務(wù)。他的博客上面有很豐富的關(guān)于MySQL調(diào)優(yōu)的文章和演講文稿,特別是關(guān)于 InnoDB方面,非常深入。JavaEye的數(shù)據(jù)庫調(diào)優(yōu)就是根據(jù)他的InnoDB演講文稿來調(diào)整的,一般說來,有幾個需要調(diào)整的參數(shù):
innodb_buffer_pool_size這個參數(shù)很重要,越大越好,對于專用的數(shù)據(jù)庫服務(wù)器一般建議開服務(wù)器內(nèi)存的50%以上。query_cache_size查詢緩存,對于查詢的性能提高有很大幫助,但不宜開得過大,查詢緩存的過期可能很頻繁,過大查詢緩存反而降低性能,增加服務(wù)器開銷
innodb_flush_method = O_DIRECT針對InnoDB的數(shù)據(jù)文件,關(guān)閉操作系統(tǒng)的文件緩沖,由于InnoDB自己有巨大的Buffer Pool,操作系統(tǒng)對文件的讀寫緩沖功能反而會降低MySQL的InnoDB的IO性能。最后針對數(shù)據(jù)庫的SQL優(yōu)化來說有兩點(diǎn)原則:
1、對數(shù)據(jù)庫表要適當(dāng)?shù)膭?chuàng)建索引特別是出現(xiàn)在where查詢條件當(dāng)中字段,和關(guān)聯(lián)查詢當(dāng)中的外鍵,要高度注意。
2、盡量避免大表的全表掃描和數(shù)據(jù)庫的硬盤IO查詢比較慢的SQL要explain一下,看看是否發(fā)生了全表掃描,采取各種措施減少或者避免大表的全表掃描問題,例如拆分表等等。
最后針對MySQL數(shù)據(jù)庫運(yùn)行情況,我們可以用show status; 和 show innodb status\G 來監(jiān)測。
Rails應(yīng)用程序的優(yōu)化Rails應(yīng)用程序優(yōu)化包括ruby解析器的優(yōu)化,緩存的使用,以及應(yīng)用代碼級別的優(yōu)化。Stefans Kaes曾經(jīng)在Railsconf 2006有一個Rails應(yīng)用程序優(yōu)化的演講,他的演講PPT是極好的Rails性能優(yōu)化指南,可以在這里下載:http://www.javaeye.com/topic/24508。
他還編寫了一個用于Rails性能測試的軟件包RailsBench,大家可以參考。由于Stefans Kaes的代碼優(yōu)化文檔已經(jīng)寫的非常詳細(xì)了,因此我就不在一一復(fù)述,只提出幾點(diǎn)對性能影響比較大的方面:
一、ruby解析器的優(yōu)化
ruby的解析器性能是很糟糕的,ruby早期的主要用途是取代perl寫批量處理的腳本的,并不是為服務(wù)器應(yīng)用編寫的,因此在內(nèi)存分配策略上非常不適合服務(wù)器應(yīng)用。Stefans Kaes編寫了一個ruby GC的補(bǔ)丁文件,在railsbench下載包里面提供了。雖然當(dāng)前Railsbench提供的GC補(bǔ)丁只有針對ruby 1.8.4和1.8.5版本的,但是在ruby 18,6上面使用1.8.5的GC補(bǔ)丁也完全沒有問題。
GC補(bǔ)丁的作用主要是針對Rails應(yīng)用開大了ruby的內(nèi)存堆,可以有效提高內(nèi)存堆的利用率,降低GC的頻率。根據(jù)Stefans Kaes提供的測試數(shù)據(jù),打補(bǔ)丁并且調(diào)整參數(shù)以后,GC的頻率下降到只有原來的1/10還不到。降低GC頻率盡管并不能夠提高單個請求的執(zhí)行速度,但是可以增加整體應(yīng)用的負(fù)載能力。
我們在JavaEye的服務(wù)器上也使用了GC補(bǔ)丁,并且根據(jù)推薦參數(shù)進(jìn)行了調(diào)整。在使用GC補(bǔ)丁之后,CentOS WEB服務(wù)器的CPU負(fù)載下降了大概15%左右,效果非常顯著。當(dāng)然開大內(nèi)存堆的代價(jià)就是ruby進(jìn)程會多消耗內(nèi)存,在我們的服務(wù)器上,ruby打補(bǔ)丁之后多消耗了50%左右的物理內(nèi)存。
二、緩存的使用
1、對象緩存
JavaEye上面關(guān)于對象緩存的討論很多,我們也提供了JavaEye這方面很多數(shù)據(jù),因此不展開了。RoR可以使用兩個對象緩存,一個是 CachedModel,類似Hibernate,比較簡單,對Model的CRUD操作自動進(jìn)行緩存;另外一個是cache_fu,需要自己編碼來添加對象緩存,但提供了更多高級機(jī)制,目前我們使用的是cache_fu。在使用對象緩存的情況下,應(yīng)該把查詢方法的:include去掉,避免關(guān)聯(lián)查詢無法利用緩存的現(xiàn)象。
2、查詢緩存
對于統(tǒng)計(jì)類耗時查詢,如果不要求實(shí)時性,那么可以使用memcache-client將查詢結(jié)果緩存到memcached里面,例如博客排行榜之類。
3、頁面局部緩存
對象緩存和查詢緩存都是降低數(shù)據(jù)庫訪問負(fù)載的,但如果RoR的負(fù)載很高,那么只能依靠頁面局部緩存了。傳統(tǒng)的互聯(lián)網(wǎng)CentOS WEB1.0網(wǎng)站很流行采用動態(tài)頁面靜態(tài)化技術(shù)來提高網(wǎng)站的負(fù)載,但是對于CentOS WEB2.0網(wǎng)站來說,每個頁面都帶有登陸用戶的個人信息,頁面的很多部分需要實(shí)時更新,例如投票,點(diǎn)擊統(tǒng)計(jì), digg,顯示用戶在線狀態(tài)等等,動態(tài)頁面靜態(tài)化非常困難。當(dāng)然如果你非要采用動態(tài)頁面靜態(tài)化,技術(shù)上也不是實(shí)現(xiàn)不了,可以通過AJAX請求來處理靜態(tài)頁面的動態(tài)部分,但是這種解決方案的開發(fā)成本過高,而且性能未必會有明顯的改善,大家看看新浪和搜狐博客就知道這種技術(shù)被應(yīng)用的有多糟糕了。
CentOS WEB2.0網(wǎng)站比較常用使用頁面局部緩存,一種情況是頁面不需要實(shí)時更新的,那么只需要設(shè)置一個合理的過期時間就行了,這種情況我們目前使用的比較多;另外一種情況是雖然不需要實(shí)時更新,但是會在用戶執(zhí)行某些操作后需要緩存過期,比方說博客個人主頁的很多頁面,這種情況下緩存過期策略會比較復(fù)雜,考慮到合理的開發(fā)成本,我們尚未對這樣的頁面使用局部緩存。
此外,Rails的頁面局部緩存有一個缺點(diǎn),就是和頁面查詢結(jié)果對應(yīng)的Action當(dāng)中的查詢語句要放在View里面,否則每次action里面的查詢還是會被執(zhí)行,但是這樣做會破壞程序代碼良好的MVC結(jié)構(gòu)。這種情況下,也可以采用另外一個Cache插件: better rails caching,在緩存頁面的同時可以緩存Action當(dāng)中的查詢語句。
三、應(yīng)用代碼的優(yōu)化
Stefans Kaes的文檔里面對應(yīng)用代碼的優(yōu)化進(jìn)行了非常詳細(xì)的介紹,因此我這里只提兩個比較重要的注意事項(xiàng):
1、link_to
Rails的link_to是非常慢的,它的代碼實(shí)現(xiàn)過于復(fù)雜,特別是Rails1.2引入了REST以后,大量的命名路由被使用,這些命名路由還需要通過一次method_missing,那就更加緩慢了。因此對于被頻繁使用的內(nèi)部URL地址,一定要自己用字符串拼接方式改寫,可以很明顯提高View的 render性能。此外類似的helper還有很多,例如button_tag,image_tag啥啥的,如非必要,盡量不用他的helper
2、正則表達(dá)式
ruby的正則表達(dá)式也是極慢,例如auto_fix這個helper的正則表達(dá)式就比較復(fù)雜,CentOS WEB造成的結(jié)果就是一但大量使用auto_fix,View的 render就明顯變慢,類似依賴正則表達(dá)式進(jìn)行字符串過濾的helper有很多,如果需要頻繁大量使用,請先自行做benchmark。
Rails應(yīng)用程序的內(nèi)存泄漏問題和解決
內(nèi)存泄漏是服務(wù)器端程序經(jīng)常遇到的,CentOS WEB有時候內(nèi)存泄漏問題會讓人很頭疼,總體來說,Rails的內(nèi)存泄漏問題比Java要少得多,這是因?yàn)镴ava內(nèi)存泄漏最常見的三種情況在Rails當(dāng)中不存在:
1、HttpSession導(dǎo)致的內(nèi)存泄漏
Java程序員喜歡往session里面丟很多東西,最糟糕的是竟然有很多框架軟件也肆無忌憚往session里面丟狀態(tài)數(shù)據(jù),但Rails的session是不放在內(nèi)存里面的,所以無此煩惱。
2、數(shù)據(jù)庫連接釋放不徹底
Java的數(shù)據(jù)庫連接池釋放不徹底,以及查詢游標(biāo)釋放不徹底,都必然導(dǎo)致內(nèi)存泄漏。Rails沒有數(shù)據(jù)庫連接池,而是每個進(jìn)程持有一個長連接,因此不存在這個問題,而且由于持有長連接,也不存在Java里面的OpenSessionInView的煩惱。
3、用靜態(tài)變量持有全局共享數(shù)據(jù)
Java程序員很喜歡通過靜態(tài)全局變量來持有共享數(shù)據(jù),CentOS WEB但共享數(shù)據(jù)忘記清理的話,也很容易導(dǎo)致內(nèi)存泄漏,Ruby是SNA架構(gòu),多進(jìn)程服務(wù)器模式,進(jìn)程間無法共享數(shù)據(jù),反而避免了全局共享數(shù)據(jù)帶來的麻煩。
但是Rails應(yīng)用有一種情況:在Ruby代碼中調(diào)用C寫的第三方ruby類庫的時候,CentOS WEB很容易導(dǎo)致內(nèi)存泄漏,但這種內(nèi)存泄漏反而在Java中極其罕見。Ruby本身有GC來管理內(nèi)存堆,但是代碼一旦調(diào)用C寫的第三方ruby類庫,內(nèi)存堆的分配權(quán)就掌握在第三方C庫的實(shí)現(xiàn)上面了,如果這個C庫的代碼質(zhì)量不夠好,內(nèi)存泄漏就不可避免。由于ruby本身性能很差,因此計(jì)算量大的功能往往依賴底層的C庫來實(shí)現(xiàn),這下內(nèi)存泄漏的潘多拉魔盒就打開了!而Java 性能比較好,功能都是純Java編寫,基本上看不到需要依賴第三方C庫的情況,因此比較安全。
JavaEye也面臨著內(nèi)存泄漏的困擾,CentOS WEB這方面困擾主要來自于Rmagic。Rmagick調(diào)用ImageMagick的C庫來完成圖片的操作,從我們的監(jiān)測來看,RMagick大多數(shù)情況下會緩慢的泄漏內(nèi)存,在某些特定的圖片操作上會急劇的泄漏內(nèi)存。解決辦法就是用mini_magick替代 Rmagick,mini_magick是直接調(diào)用ImageMagick的mogrify命令,另起一個進(jìn)程來操作圖片,操作完進(jìn)程就結(jié)束了,絕無后患,由于Linux的fork進(jìn)程開銷不大,因此也不必?fù)?dān)心性能問題。
此外,調(diào)用第三方C庫的ruby代碼編寫都需要高度小心,比方說JavaEye使用ferret實(shí)現(xiàn)全文檢索,根據(jù)應(yīng)用的需要調(diào)用ferret的 API來編寫自己的analyzer,其中在實(shí)現(xiàn)token_stream方法上面使用了XXXAnalyzer.new和XXXToken.new, XXXFilter.new,結(jié)果內(nèi)存急劇泄漏,經(jīng)過檢查發(fā)現(xiàn)是Analyzer對象不能被反復(fù)創(chuàng)建,改成創(chuàng)建后緩存該對象就好了,但是Filter和 Token對象卻必須每次創(chuàng)建,此外ferret的PerAnalyzerFilter也有內(nèi)存泄漏問題。由于類庫是用C編寫的,單純看API文檔或者看源代碼片斷一般無法判斷出里面的內(nèi)存泄漏陷阱的。
當(dāng)遇到了難以解決和定位的內(nèi)存泄漏問題,Ruby也有類似Java的內(nèi)存Profiler工具:
1、Memory Profiler
一個純r(jià)uby編寫的內(nèi)存探測器,原理很簡單,就是用ruby的對象引用計(jì)數(shù)器ObjectSpace.each_object去遍歷內(nèi)存堆中的每個 ruby對象,進(jìn)行統(tǒng)計(jì)和分析。用起來很簡單,非常適合于開發(fā)環(huán)境下偵測內(nèi)存泄漏問題,但不能用在生產(chǎn)環(huán)境下,極度影響Rails性能。
2、Bleak_house
Bleak_house給Ruby解析器打了補(bǔ)丁,插入相關(guān)的指令,可以從底層探測整個ruby內(nèi)存堆中對象的情況,然后你可以定期dump出來完整的內(nèi)存堆里面的所有對象,再用bleak工具去分析dump文件,他比上面的工具分析的信息要全面,可以在測試環(huán)境和預(yù)發(fā)布環(huán)境下使用,但在生產(chǎn)環(huán)境下,也會對應(yīng)用的性能產(chǎn)生很大的影響,要慎用。
JavaEye網(wǎng)站在RoR性能方面的經(jīng)驗(yàn)就全部分享給大家了,也希望做RoR的朋友都拿出來自己的經(jīng)驗(yàn)和大家分享,共同學(xué)習(xí)和促進(jìn)RoR的應(yīng)用和普及。
【編輯推薦】