网站性能优化的三重境界
這篇文章是關(guān)于網(wǎng)站性能優(yōu)化體驗(yàn)的,性能優(yōu)化是一個(gè)復(fù)雜的話題,牽涉的東西非常多,我只是按照我的理解列出了性能優(yōu)化整個(gè)過(guò)程中需要考慮的種種因素。點(diǎn)到為止,包含的內(nèi)容以淺顯的介紹為主,如果你有見(jiàn)解能告知我那再好不過(guò)了。無(wú)論如何,希望閱讀它的你有所收獲。
?
我眼中的網(wǎng)站性能問(wèn)題都反映了一個(gè)網(wǎng)站的“Availability”(中文叫做可用性,但是這個(gè)翻譯也不足夠達(dá)意),以往我的認(rèn)識(shí)是,這個(gè)網(wǎng)站如果全部或者部分不可用,那是功能問(wèn)題,但是如果響應(yīng)慢、負(fù)載差,這才是性能問(wèn)題;可是后來(lái)我逐漸意識(shí)到,性能問(wèn)題涵蓋的范圍更廣,我還沒(méi)法給出一個(gè)準(zhǔn)確定義,但是許多非業(yè)務(wù)邏輯錯(cuò)誤引起的網(wǎng)站問(wèn)題都可能可以算做性能問(wèn)題,比如可擴(kuò)展性差,比如單點(diǎn)故障問(wèn)題。
?
?
在網(wǎng)站性能優(yōu)化的最初階段,也就是所謂的“第一重境界”,做局部的定位、分析和修正,考慮的僅僅是“優(yōu)化”,這也是初涉性能優(yōu)化問(wèn)題的大多數(shù)人的認(rèn)識(shí)。在問(wèn)題發(fā)生以后,發(fā)現(xiàn)它和業(yè)務(wù)邏輯沒(méi)有太大關(guān)系,就開(kāi)始嘗試尋找問(wèn)題產(chǎn)生的原因并加以解決。
?
無(wú)論是網(wǎng)站無(wú)響應(yīng)還是響應(yīng)緩慢,還是響應(yīng)曲線異常波動(dòng),比如,可以圍繞CPU的使用問(wèn)自己這樣幾個(gè)問(wèn)題:
?
- 從CPU使用看系統(tǒng)是否繁忙?
- 如果系統(tǒng)繁忙,系統(tǒng)在做什么,為什么?(典型問(wèn)題:HashMap不安全并發(fā)導(dǎo)致的死循環(huán))
- 如果系統(tǒng)空閑,那么瓶頸在哪里?(典型問(wèn)題:IO無(wú)響應(yīng))
- 如果響應(yīng)波動(dòng),是否存在周期,周期是什么?(典型問(wèn)題:連接迅速占滿,每一周期批量超時(shí)斷開(kāi)一批)
- 如果響應(yīng)波動(dòng),性能到波谷時(shí)系統(tǒng)在做什么?
- 是否有背景CPU使用?(即無(wú)壓力下觀察CPU的使用情況。典型問(wèn)題:正執(zhí)行的定時(shí)任務(wù)占用過(guò)多系統(tǒng)資源)
在這些問(wèn)題中,情況雖然千變?nèi)f化,簡(jiǎn)單地說(shuō),CPU的使用是核心,CPU使用率高,說(shuō)明可能系統(tǒng)在實(shí)實(shí)在在地做事,反之,需要尋找其他瓶頸。通過(guò)結(jié)合進(jìn)程、線程的快照,來(lái)初步確定問(wèn)題的范圍。CPU使用率低的情況居多而且容易定位,只需要尋找其他的系統(tǒng)瓶頸;CPU占用率偏高的問(wèn)題往往比較不容易定位,雖然也有一些辦法。關(guān)于具體性能問(wèn)題的定位技術(shù),這里不著過(guò)多筆墨,后續(xù)有機(jī)會(huì)詳細(xì)介紹。
?
對(duì)于一個(gè)剛開(kāi)始做性能優(yōu)化的網(wǎng)站系統(tǒng),下面的事情不妨都做一做,會(huì)有立竿見(jiàn)影的效果(如果你需要更多的建議,不妨參考這張圖):
?
- 對(duì)于使用的成熟的技術(shù),技術(shù)社區(qū)、官方文檔,往往會(huì)給出這種技術(shù)的白皮書(shū)或者優(yōu)化指導(dǎo),請(qǐng)參考。比如?Struts2的官方性能調(diào)優(yōu)指南、Java6性能優(yōu)化白皮書(shū)。
- 平臺(tái)和虛擬機(jī)調(diào)優(yōu)。對(duì)于使用平臺(tái)和虛擬機(jī)的項(xiàng)目來(lái)說(shuō),這是必須要做的,一個(gè)JVM的參數(shù)可以對(duì)系統(tǒng)有顯著的影響。比如Linux下連接管理的參數(shù),JVM關(guān)于堆大小分布的參數(shù)等等。
- 前端審查。這里的審查指的是通過(guò)Page speed、YSlow等工具,以及一些業(yè)界通用的法則和經(jīng)驗(yàn)(比如yahoo的若干條前端性能優(yōu)化法則)來(lái)評(píng)估現(xiàn)有頁(yè)面的問(wèn)題。
從使用的工具上說(shuō),性能問(wèn)題的定位很大程度上是面向操作系統(tǒng)、虛擬機(jī)系統(tǒng)的問(wèn)題定位(這里有一些定位方法介紹)。從問(wèn)題定位的時(shí)機(jī)上說(shuō),又可以分為:
?
- 截取型:截取系統(tǒng)某個(gè)層面的一個(gè)快照加以分析。比如一些堆棧切面和分析的工具,jstack、jmap、kill -3、MAT、Heap Analyser等。
- 監(jiān)控型:監(jiān)視系統(tǒng)變化,甚至數(shù)據(jù)流向。比如JProfiler、JConsole、JStat、BTrace等等。
- 驗(yàn)尸型:系統(tǒng)已經(jīng)宕機(jī)了,但是留下了一些“罪證”,在事后來(lái)分析它們。最有名的就是JVM掛掉之后可能會(huì)留下的hs_err_pid.log,或者是生成的crash dump文件。
?
?
好,暫時(shí)說(shuō)到這里,下面來(lái)看第二重境界。達(dá)到這重境界意味著已經(jīng)能夠跳出“事后優(yōu)化”的局限了,在設(shè)計(jì)和編碼的過(guò)程當(dāng)中,能夠正式和全面地考慮性能的因素,比如:
?
- 減少使用時(shí)間敏感的容器管理,而使用容量或數(shù)量敏感的容器管理。比如我往一個(gè)緩沖里面存放若干數(shù)據(jù),一種設(shè)計(jì)是每10分鐘flush入庫(kù)一次,還有一種設(shè)計(jì)是數(shù)據(jù)到達(dá)10M大小的時(shí)候flush入庫(kù)一次,通常情況下,你覺(jué)得哪個(gè)方案更可靠?
- 線程的統(tǒng)一管理使用。我的經(jīng)驗(yàn)是,10次對(duì)線程創(chuàng)建或者線程池的使用,往往就有5次是會(huì)出問(wèn)題的。
- 避免使用同步Ajax。同步Ajax會(huì)造成瀏覽器假死,直至響應(yīng)返回。
- 分析對(duì)同步、鎖的使用。即便在一些有名的開(kāi)源庫(kù)中,我們也不止一次發(fā)現(xiàn)過(guò)不合理的同步設(shè)計(jì),N多數(shù)據(jù),單一的全局同步塊(這是一種性能設(shè)計(jì)層面上的“中心化”),結(jié)果它就成為了瓶頸,改動(dòng)還不容易下手,很麻煩。
對(duì)于不成熟的團(tuán)隊(duì),建議能安排有經(jīng)驗(yàn)的程序員把關(guān)設(shè)計(jì)文檔和編碼中的性能問(wèn)題,把常見(jiàn)的問(wèn)題列出來(lái)參考學(xué)習(xí)。
?
達(dá)到第二重境界還有一個(gè)明顯的特征就是在軟件流程的前中期就開(kāi)始做性能目標(biāo)的論證和性能問(wèn)題的驗(yàn)證:
?
- 性能切面分析。這指的是在系統(tǒng)設(shè)計(jì)初期,為了評(píng)估一個(gè)系統(tǒng)的性能表現(xiàn),做出一個(gè)性能類似的系統(tǒng)原型,并對(duì)其做性能測(cè)試和評(píng)估,這時(shí)候因?yàn)樾阅軉?wèn)題而涉及到方案的變更,影響較小。據(jù)我所知,能夠做到這一點(diǎn)的項(xiàng)目極少。在大多數(shù)團(tuán)隊(duì)中,依賴于架構(gòu)師和掌握話語(yǔ)權(quán)的設(shè)計(jì)者依靠經(jīng)驗(yàn)來(lái)避免性能問(wèn)題帶來(lái)的大的方案變更(或者,干脆摔一次跤,再進(jìn)行痛苦的“重構(gòu)”)。
- 性能的自動(dòng)化測(cè)試驗(yàn)證。這一步必須伴隨著Coding進(jìn)行才有較大的意義,以便盡早發(fā)現(xiàn)性能問(wèn)題。
- 設(shè)計(jì)和代碼層面的評(píng)審。我的博客里面一再地強(qiáng)調(diào)評(píng)審的價(jià)值,不妨看看這篇和這篇。其實(shí)功能問(wèn)題考慮得多、暴露得早,真正有危險(xiǎn)的往往都是那些被忽視的非功能性問(wèn)題,比如性能問(wèn)題。
?
最后是第三重境界。達(dá)到這重境界的團(tuán)隊(duì)能夠在早期規(guī)劃構(gòu)想階段就將性能作為一個(gè)必備因素包含在內(nèi),這可不是隨口說(shuō)說(shuō)的經(jīng)驗(yàn)的估計(jì),而是要有數(shù)據(jù)驅(qū)動(dòng)的理論設(shè)計(jì),比如做性能建模,根據(jù)市場(chǎng)大小、業(yè)務(wù)量、服務(wù)等級(jí)等等計(jì)算出性能的具體指標(biāo),并且在此要求下做合理的架構(gòu)設(shè)計(jì)。
?
這里涉及的東西有很多,除了數(shù)據(jù),還需要有大量的思考,對(duì)于一個(gè)網(wǎng)站來(lái)說(shuō),不妨問(wèn)問(wèn)如下的問(wèn)題:
?
- 數(shù)據(jù)量會(huì)有多大,我該設(shè)計(jì)什么樣的存儲(chǔ)?一致性的要求又如何?
- 實(shí)時(shí)性要求是怎么樣的?用戶可以接受多少時(shí)間的數(shù)據(jù)延遲?
- 網(wǎng)站需要考慮到什么程度的可伸縮性?
- 哪些流程的數(shù)據(jù)處理有性能風(fēng)險(xiǎn),數(shù)據(jù)量是什么級(jí)別的?怎么解決這個(gè)問(wèn)題?
- 主要的業(yè)務(wù)時(shí)間消耗是怎樣的,我需要設(shè)計(jì)怎樣的業(yè)務(wù)流來(lái)滿足?
所有的性能問(wèn)題和其他一切非功能性問(wèn)題一樣,都是一定程度上的trade off,所以越優(yōu)秀的設(shè)計(jì)者越需要思考,來(lái)規(guī)劃這些問(wèn)題的解決方案。在規(guī)劃中因?yàn)樾阅軉?wèn)題而涉及到的因素有哪些,太多太多了,這里列了一些供參考。
?
要達(dá)到第三重境界還要能夠預(yù)測(cè)性能問(wèn)題。這就需要成熟的監(jiān)控體系,監(jiān)控系統(tǒng)的變化,盡快做出反應(yīng)。
?
比如國(guó)內(nèi)發(fā)生了重大事件,用戶量陡增,監(jiān)控系統(tǒng)能夠及時(shí)識(shí)別出用戶量監(jiān)控曲線一個(gè)非常明顯的跳躍過(guò)程(比如持續(xù)事件超過(guò)某個(gè)值,且曲線斜率超過(guò)某個(gè)值),發(fā)出告警,并且自動(dòng)擴(kuò)容來(lái)應(yīng)付潛在的風(fēng)險(xiǎn)。這些,都是建立在常規(guī)的業(yè)務(wù)運(yùn)營(yíng)數(shù)據(jù)收集基礎(chǔ)之上的,然后需要做數(shù)據(jù)挖掘,給出關(guān)鍵點(diǎn)。
?
再比如互聯(lián)網(wǎng)應(yīng)用“緩存為王”。對(duì)于緩存的設(shè)計(jì),甚至很大程度上決定了應(yīng)用的成敗(如果你很有錢,靠大量的CDN這種非常規(guī)路線的另說(shuō),呵呵)。緩存的設(shè)計(jì)需要考慮到緩存的大小、分級(jí)、隊(duì)列、命中率計(jì)算、生命周期、更新?lián)Q頁(yè)、數(shù)據(jù)分發(fā)、數(shù)據(jù)一致性和數(shù)據(jù)持久化等等問(wèn)題,這些東西往往被很多只重視那些頁(yè)面展示效果和功能的人所忽視,但如果你是優(yōu)秀的設(shè)計(jì)者,你需要積累這些思考。
?
Think big。有這樣一個(gè)真實(shí)的例子,我們?cè)?jīng)發(fā)現(xiàn)頁(yè)面模板的OGNL性能不高(兩次反射之故),遂在項(xiàng)目中把大部分OGNL表達(dá)式都改成了EL表達(dá)式,花了很多時(shí)間精力,性能也確實(shí)提高了,但是能提高多少呢?大概只有30%,這是一種細(xì)水長(zhǎng)流的改進(jìn),對(duì)系統(tǒng)的破壞性不大,但是收效也不足以令人沾沾自喜,還失去了一些OGNL的靈活性。之后,我們換了一個(gè)思路,從大局入手,給頁(yè)面劃分區(qū)域,定制緩存框架,引入頁(yè)面緩存能力,雖然整套方案有些復(fù)雜,但是這種架構(gòu)上的進(jìn)化,由于頁(yè)面的生成或者部分生成直接命中了緩存文件,性能一下有了飛躍,提高了600%~800%。這就是Think big,從大處著想,見(jiàn)得到工程大塊的結(jié)構(gòu),需要足夠的視野、足夠的經(jīng)驗(yàn)和積累,可以帶來(lái)顯著的效果。
?
通常系統(tǒng)容量的設(shè)計(jì)都會(huì)要求到峰值容量以上,如果是像秒殺、搶購(gòu)之類對(duì)性能要求非常高的系統(tǒng),往往還存在一個(gè)問(wèn)題:設(shè)計(jì)了這么大的容量,平時(shí)大部分時(shí)間業(yè)務(wù)量都比較小,這些資源浪費(fèi)怎么辦?(題外話:這大概也是Amazon涉足云存儲(chǔ)和云計(jì)算的初始緣由吧)
?
同時(shí),也要看到,性能因素也是一個(gè)網(wǎng)站系統(tǒng)發(fā)展的最大推動(dòng)力,再細(xì)致的思考也難以兼容那么多未知的場(chǎng)景,不妨多在擴(kuò)展性和兼容性上下下功夫,避免網(wǎng)站冷清痛苦,網(wǎng)站大熱更痛苦。
總結(jié)
以上是生活随笔為你收集整理的网站性能优化的三重境界的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: c++中用new和不用new创建对象的本
- 下一篇: 浅谈跳槽