一個RoR的站點性能優(yōu)化的故事(3)原文鏈接: http:///articles/2006/03/27/the-adventures-of-scaling-stage-3 中文鏈接: http:///2009/08/01/00/14/一個ror的站點性能優(yōu)化的故事3.html 第三篇 新年了 隨著圣誕和新年的來臨,我們準備從另外一個方面來改變和優(yōu)化系統(tǒng)以提高網(wǎng)站的性能和響應速度。(從以往看來節(jié)日期間是我們流量比較小的時候,人們更愿意花時間跟家人團聚而非泡在社區(qū)里) ×××,再次回到memcaced的優(yōu)化上來了。通過debug發(fā)現(xiàn)了我們 memcache封裝的問題(它是負責通過key來自動查找社區(qū)名和用戶名,或者社區(qū)名或用戶名),許多在memcached的查找都失敗了。查找本身并 沒有失敗,而是從memcached中返回的對象實例有部分“失敗”了。 這句話什么意思?也就是說花費時間很長的計算結(jié)果被放到了緩存中,但是重新從緩存中獲得它們的時候失敗了。結(jié)果再次從新計算(這時memcache封裝里面的一個回退機制)。因此沒有達到我們認為的節(jié)省時間、降低負載的效果。 然而,這個跟先于對象定義的Ruby聲明的類沒有關系,顯然和返回的marshalled數(shù)據(jù)有關。在Google上面搜索了這個錯誤信息沒發(fā)現(xiàn)任何明顯犯同樣錯誤的人,也沒有任何解決辦法。 (譯者評:看看別人解決問題的過程比知道優(yōu)化技巧這樣的結(jié)果更加重要,比如作者也走過很多盲目的彎路,但這些彎路也是思考問題的方式) 通過查看Debian的更新日志提到了一些 Ruby 1.8.4關于marshalling,并一次同時在Rubyonrails.org’s download page 看到了如下信息:
因此升級了Ruby,我們從升級到了1.8.4,重新編譯了所有C擴展的的包,比如Ruby-MySQL和RMagick,然后上線看看。 結(jié)果是沒有變化! 接著在一月的第三個星期,Robot Coop 發(fā)布了他們的memcache-client 庫,作為Ruby-Memcache的替代,現(xiàn)在后者的開發(fā)停止多時了。 使用新的memcache-client庫系統(tǒng)運行得非常流暢。它甚至做了我們自己封裝的memcached包裝器的大部分工作,請大家為Robot Coop的工作歡呼三次,太偉大了! 由于有了如此好性能的memcahced我們冒險向前走了另外一步。我們將session的存儲從 ActiveRecordStore(讀Mysql表的存儲)移到了memcached中。我們希望通過這樣做也是為了減少前面所述的Master- Master模式中只有一個線程往另一個Master中寫的壓力。同時,這樣也能將每次請求頁面而需要到數(shù)據(jù)庫的比例比11月份上線時減少了1/3。 另外通過Robot Coop memcache 客戶端我們可以有理由去跨多臺機器做分布式緩存。memcached對于我們大部分的機器無論是在內(nèi)存消耗上,還是CPU使用上都是非常不錯的。 多臺機器分布式的memcached的配置和session的存儲有過什么聯(lián)系么?哦,天知道?最后沒有人清楚的記得當用戶登錄正常時,是不是我們只是做了將用memcached做session存儲這一件事讓它的好的。(這一個改變對于我們系統(tǒng)減輕了許多壓力) 為 了簡化調(diào)試(也為了減少潛在的隱患)我們又返回去用單臺機器配置一個memcached和一個MySQL的做法。memcached放在一臺(只做數(shù)據(jù)同 步和廣告服務)比較空閑的數(shù)據(jù)庫服務器上。順便提一下memcached的配置非常簡單。經(jīng)常需要去變的參數(shù)是分配的內(nèi)存大小,需要記住的是分配的內(nèi)存可 以很大,但memcached也必須去調(diào)度這么大的內(nèi)存空間。到了一定時候它將會到達它的極限。我們當前給memcache了1024M的內(nèi)存空間,這個 對于文本信息綽綽有余。 這是基于我們系統(tǒng)7周時間的memcached的統(tǒng)計數(shù)據(jù)。(不要問過關于二進制字節(jié)的讀寫比率,我認為這是顛倒的???)
出現(xiàn)新的訪問速度變慢的問題 在一月份的前半個月我們一天就可以支撐110萬的流量,此時的流量達到了95G。接著到了一月份的后半個月系統(tǒng)出現(xiàn)問題,幾乎不能工作了。雖然以前我們所做的所有修改和調(diào)優(yōu)(原本這些都非常好),但我們碰到了新問題,發(fā)現(xiàn)系統(tǒng)在變慢。 是 正常的變慢,還是糟糕的變慢?實際上是不好的變慢。到了一月份的最后一周變得跟去年11月份一樣慢了。為什么會這樣?哦,這是一個好問題。我們已經(jīng)優(yōu)化了 系統(tǒng)的每一個部分(如果你讀完了這一系列文章,你也應該清楚)。在過去的幾周內(nèi),事情看上去都不錯,但現(xiàn)在我們又回到了開始時那樣。 先還是把系統(tǒng)結(jié)構圖圖畫出來吧,這樣清楚些,不如從圖中找問題。(譯者評:我就是在機器上傻看數(shù)據(jù),退一步看看整個架構更容易發(fā)現(xiàn)問題) (對于這些似乎你很眼熟,我以前在寫過一篇文章叫“溫柔地殺死我”) 使 用tpcdump來監(jiān)控偵聽端口的流量,什么也沒有,沒有一個字節(jié)通過管道。使用strace來看看那些忙一些的偵聽在干什么,它們在wait,也沒有做 任何事情。郁悶的是,如果你重啟lighttpd或者×××,最終和開始看到的一樣。我的同事對防火墻做了各種配置,我開始調(diào)整應用服務器和 lighttpd代 理服務器的/proc的參數(shù),我猜測是到了某個參數(shù)的上限。用netstat也發(fā)現(xiàn)有幾百個連接在那些管道中,狀態(tài)都是 TIME_WAIT和CLOSE_WAIT,很像遭受了synflooed攻擊。但這是我們內(nèi)部機器,不會被外面看到。下一步,根據(jù)公共可利用的資源來調(diào) 整/proc中的參數(shù),具體如下:
不要在家使用這些命令,因為它一點都沒有幫到我們。請求始終停在那,網(wǎng)站的性能讓人看上去惡心。另外一個人企圖在每個應用服務器上都啟動一個lighttp (這樣來代替遠程的fastcgi偵聽),然后放一個lighttp的負載均衡的方向代理在前面。事實證明系統(tǒng)還是慢。 剩下比較“土”的辦法,我寫了一個腳本來搜索所有的可用偵聽,如果它們在一定周期內(nèi)沒有響應,就kill它。被kill的請求會有Rails的spinner/spawner很快的重新 啟動,lighttpd只是多花幾秒鐘來重新連接socket。雖然對于業(yè)務來說不能持續(xù)的來監(jiān)控它們了。 這個方法 剩下最后一篇是關于系統(tǒng)擴展性的問題,也總結(jié)一下,哪些有幫助,哪些沒有,同時展望一下將來系統(tǒng)調(diào)優(yōu)的計劃。 |
|
來自: 漂在北方的狼 > 《Architecture》