前面看到有人講j2ee的性能調(diào)優(yōu),雖然這塊不是自己的專長(zhǎng),但是豬養(yǎng)多了,也忍不住跳出來說幾句。

雖然幾乎每本講性能調(diào)優(yōu)的書籍開篇都會(huì)提,沒必要的情況下就不要做調(diào)優(yōu),但是我個(gè)人還是認(rèn)為,所有系統(tǒng)在上線前,都應(yīng)該做一次基本的壓力測(cè)試并對(duì)相關(guān)的性能問題進(jìn)行檢測(cè), 但是迫于資源壓力,很多項(xiàng)目都無法做正規(guī)的壓力測(cè)試,一直到系統(tǒng)上線出現(xiàn)問題,才倒回來找原因。 而正規(guī)的壓力測(cè)試,往往因?yàn)樾枰獓?yán)格模擬生產(chǎn)環(huán)境,需要耗費(fèi)大量的資源,各類專家配合解決問題,并不是那么輕松的可以做下來的。

而j2ee應(yīng)用的特點(diǎn)就是以復(fù)雜性來回避傳統(tǒng)問題,所以任意一個(gè)j2ee的部署,相對(duì)于php那樣的結(jié)構(gòu)都是比較復(fù)雜的。系統(tǒng)一旦發(fā)生性能問題,必須在程序、數(shù)據(jù)庫、應(yīng)用服務(wù)器、jvm、操作系統(tǒng)幾大塊中交叉進(jìn)行考慮,根據(jù)實(shí)際情況問題,問題的原因可能異常復(fù)雜。 我們可以想象一個(gè)項(xiàng)目,從來不做UT不做IT ,只做一次UAT,然后直接提交給用戶上線以后,修補(bǔ)錯(cuò)誤的困難度和成本。

經(jīng)??吹揭恍┱{(diào)優(yōu)的最后解決方案,可以肯定,幾乎80%以上都是一些低級(jí)的程序錯(cuò)誤導(dǎo)致的,剩下的20%雖然可能是用硬件,os參數(shù)調(diào)整等等問題解決了,但是其中很大一塊,歸根到底也是程序的問題。 而在我們回顧這些錯(cuò)誤的時(shí)候可以很驚人的發(fā)現(xiàn),大部分都是一些低級(jí)錯(cuò)誤。

我提倡使用最小化資源的方式做一次壓力測(cè)試,排除大部分淺顯的應(yīng)用問題。最小資源的意思,即在pc環(huán)境,使用應(yīng)用可以運(yùn)行的最小資源狀態(tài)下,進(jìn)行壓力測(cè)試和性能問題偵測(cè)的工作。這種做法的優(yōu)點(diǎn)如下。
1.? 環(huán)境容易搭建, 特別是不需要考慮大型硬件和網(wǎng)絡(luò)條件等等,也回避了開發(fā)人員可能不熟悉unix和特定應(yīng)用服務(wù)器等問題
2.? 不需要特別的數(shù)據(jù)庫,操作系統(tǒng)和應(yīng)用服務(wù)器專家配合,開發(fā)人員自身即可完成。
3.? 不需要特別的依賴os和應(yīng)用服務(wù)器,jvm的監(jiān)測(cè)工具。選擇自己最熟悉的即可。
4.? 開發(fā)人員在熟悉這種過程以后,再轉(zhuǎn)到正式的生產(chǎn)環(huán)境工作時(shí)也更有經(jīng)驗(yàn),更容易解決問題。

對(duì)測(cè)試過程做一點(diǎn)簡(jiǎn)單介紹。

工具準(zhǔn)備:

得益于開源技術(shù)的發(fā)展,大部分工具都可以免費(fèi)獲得,使用也比較簡(jiǎn)單。
1. jvm 監(jiān)控: 對(duì)jvm的運(yùn)行狀態(tài)進(jìn)行分析, 可以使用jvm自身帶的特性輸出日志,結(jié)合hp的jmeter profile進(jìn)行分析。也可以使用jrockit自帶的圖形化工具mession control。 【另: 現(xiàn)在sun新出的visualvm非常出色,可以清晰的顯示線程和perm使用情況,推薦使用這個(gè),不過只能用在java5以后的版本】
熟悉什么用什么,越簡(jiǎn)單越好,目的主要是觀察內(nèi)存堆的變化,線程資源變化,gc情況等。
2. 數(shù)據(jù)庫監(jiān)控工具: 熟悉數(shù)據(jù)庫的使用數(shù)據(jù)庫自身的特性,不熟悉的可以使用第三方工具,主要目的是觀察數(shù)據(jù)庫的鎖,連接數(shù)信息, 對(duì)于db2我比較喜歡使用quest central。 oracle使用OEM或者自身的數(shù)據(jù)字典已經(jīng)可以。
3. 應(yīng)用服務(wù)器監(jiān)控: 主要目的是記錄方法的調(diào)用情況和執(zhí)行時(shí)間?,找出頻繁調(diào)用的方法和執(zhí)行時(shí)間過長(zhǎng)的方法。使用jprobe和jprofile都可以很輕松的做到。 如果使用的應(yīng)用服務(wù)器比較偏門,那么可以換一個(gè)支持這種檢測(cè)工具的應(yīng)用服務(wù)器。反正主要目的只是在找問題。
4.? sql執(zhí)行監(jiān)控:跟蹤找出執(zhí)行時(shí)間過長(zhǎng)的sql。 我喜歡使用p6spy。
5. 壓力工具: jmeter+badboy , 有條件的可以用loadrunner, 和loadrunner近似的還有一個(gè)免費(fèi)的開源產(chǎn)品OpenSTA。 另外web 應(yīng)用的話, 也可以使用selenium這樣的ff擴(kuò)展來做。微軟vs自帶的一個(gè)壓力工具也不錯(cuò),反正是什么簡(jiǎn)單用什么。
6. 記錄表格: 對(duì)問題和資源配置的變更進(jìn)行記錄和對(duì)比。

我發(fā)現(xiàn)有些人做壓力測(cè)試,只用壓力工具來跑,不肯用各類proiling工具來跟蹤應(yīng)用和數(shù)據(jù)庫使用情況,加上經(jīng)驗(yàn)又不足,結(jié)果測(cè)來測(cè)去都是瞎猜,本來一個(gè)小問題,可以跑幾個(gè)月,暈死。

設(shè)置:
1. 數(shù)據(jù)庫: 如果未使用連接池, 則盡可能的將數(shù)據(jù)庫允許連接設(shè)置成最小數(shù)字,推薦是從1開始。如果使用連接池,則設(shè)置為1.
隨著并發(fā)模擬數(shù)的增加也可以適當(dāng)上調(diào),但是一定要低于壓力工具模擬的并發(fā)用戶數(shù)。數(shù)據(jù)庫環(huán)境盡可能接近生產(chǎn)環(huán)境,至少要有足夠的測(cè)試數(shù)據(jù)。
2. 應(yīng)用服務(wù)器: 對(duì)jvm啟動(dòng)堆做最小化設(shè)置。比應(yīng)用服務(wù)器要求的最低內(nèi)存略高,保證應(yīng)用可以正常啟動(dòng)即可。根據(jù)模擬用戶數(shù)增加可以小步適當(dāng)上調(diào),但是以保證應(yīng)用基本運(yùn)行即可。千萬別來大內(nèi)存。
3. 壓力模擬并發(fā)數(shù),從1開始逐步往上加。一次加1,2個(gè),上限不要太高,5-10個(gè)足以。

步驟
1. 按1用戶1連接的方式進(jìn)行檢測(cè)
?? * 找出系統(tǒng)是否存在明顯的資源泄露,比如數(shù)據(jù)庫連接,如果存在泄露此種情況下服務(wù)器很容易就hold。
?? * 找出執(zhí)行時(shí)間過長(zhǎng)的java方法和sql。進(jìn)行分析修改。
?? * 找出那些調(diào)用過多的方法和sql,對(duì)程序進(jìn)行分析,看是否做了不必要的調(diào)用。 這個(gè)問題尤其在使用了第三方包的情況下要小心,我曾經(jīng)監(jiān)測(cè)出某人寫的東西一個(gè)方法間接的調(diào)用了數(shù)據(jù)庫操作近200次。

有些人做測(cè)試喜歡從5以上的數(shù)字開始,實(shí)在不是什么好習(xí)慣,比較明顯的問題都容易回避了。

2.? 適當(dāng)增加并發(fā)用戶,盡可能不調(diào)整應(yīng)用內(nèi)存,對(duì)系統(tǒng)進(jìn)行長(zhǎng)時(shí)間的壓力測(cè)試,比如2-4個(gè)小時(shí)。 重點(diǎn)觀察是否存在內(nèi)存泄露問題。 內(nèi)存泄露的問題比較復(fù)雜,有時(shí)候還依賴于jvm和os,另外有些內(nèi)存泄露只能在大并發(fā)的多線程環(huán)境下才會(huì)出現(xiàn)。 但是這種測(cè)試可以排除掉一些明顯的問題,主要是緩存和隊(duì)列之類的東西。

內(nèi)存泄露一般jvm會(huì)有報(bào)錯(cuò)和相關(guān)的日志dump文件。

3.? 逐步增加并發(fā)用戶和連接數(shù),觀察是否存在sql鎖 和線程鎖的問題。另外并發(fā)情況下也可能存在其他一些資源沖突,比如讀寫文件的情況等等。

線程情況可以使用監(jiān)控工具觀察,比如jrockit帶的mc, 也可以直接dump jvm 內(nèi)存快照找工具分析。

4.? 盡可能增加并發(fā)用戶數(shù),以當(dāng)前應(yīng)用能承擔(dān)的上線進(jìn)行長(zhǎng)時(shí)間測(cè)試,比如半天到1天,觀察是否會(huì)存在內(nèi)存泄露,是否會(huì)存在線程資源消耗的問題。也需要檢查一下數(shù)據(jù)庫的連接數(shù)情況,看是否會(huì)一直持續(xù)增加,這說明連接池實(shí)現(xiàn)有問題,或者設(shè)置過大,也可能是jdbc的問題。

5. 其他: 對(duì)jvm?可以使用sun和bea的都對(duì)比跑一下, 兩個(gè)實(shí)現(xiàn)情況大不同。 jr大并發(fā)支持好,所以可能jr上沒問題,但是sun的就有問題了。?

大部分的問題應(yīng)該都可以在步驟1,2能得到暴露。在完成了這樣的初步測(cè)試以后,正式的測(cè)試就省心不少了,如果客戶有錢,性能不好也可以直接更新硬件了,省事又創(chuàng)造GDP。